Generator-jhipster: Reactive doesn't work with all NoSQL databases

Created on 28 Feb 2020  路  5Comments  路  Source: jhipster/generator-jhipster

Overview of the issue

After experiencing some failing tests when integrating Spring Cloud Gateway, I discovered it was caused by using Couchbase for the DB. If I switch to Mongo, it works.

Here's the .yo-rc.json that causes failing tests with ./mvnw verify -P '!webpack,dev'. Note that it fails for both monolith and gateway application types.

{
  "generator-jhipster": {
    "applicationType": "monolith",
    "reactive": true,
    "baseName": "reactiveGateway",
    "packageName": "io.github.jhipster.gateway",
    "packageFolder": "io/github/jhipster/gateway",
    "authenticationType": "jwt",
    "cacheProvider": "no",
    "enableHibernateCache": false,
    "websocket": false,
    "databaseType": "couchbase",
    "devDatabaseType": "couchbase",
    "prodDatabaseType": "couchbase",
    "searchEngine": false,
    "serviceDiscoveryType": "eureka",
    "buildTool": "maven",
    "enableTranslation": true,
    "nativeLanguage": "en",
    "languages": ["en", "es"],
    "testFrameworks": ["protractor"],
    "serverPort": "8080",
    "jhiPrefix": "jhi",
    "jhipsterVersion": "6.7.1",
    "messageBroker": false,
    "jwtSecretKey": "NWE0MjUyY2Y3ZjExNDBlMTZhNDQ2NjQxYjkxYWZmNDA2OWRlZDBiZWY2M2Q3M2IxYjYzNmZiMmNkN2QxMzUwMTg0NmQ0ZTQwOTFiZjc3YTdjNjEyODM0YmEzZjFmODgwMzlkMjUwYWFlODg4MGE0NzQ5NDY5ZTIzOTU3NGIxZDE=",
    "embeddableLaunchScript": false,
    "useSass": true,
    "clientPackageManager": "npm",
    "clientFramework": "angularX",
    "clientTheme": "none",
    "creationTimestamp": 1582856430345,
    "entitySuffix": "",
    "dtoSuffix": "DTO",
    "otherModules": [],
    "blueprints": []
  }
}

Failing tests are:

[ERROR] Failures: 
[ERROR]   AuditResourceIT.getAllAudits:68 Status expected:<200 OK> but was:<500 INTERNAL_SERVER_ERROR>

> GET /management/audits
> WebTestClient-Request-Id: [37]

No content

< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Vary: [Origin, Access-Control-Request-Method, Access-Control-Request-Headers]
< Content-Type: [application/problem+json]
< Content-Length: [213]
< Cache-Control: [no-cache, no-store, max-age=0, must-revalidate]
< Pragma: [no-cache]
< Expires: [0]
< X-Content-Type-Options: [nosniff]
< X-XSS-Protection: [1 ; mode=block]
< Feature-Policy: [geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none']
< Content-Security-Policy: [default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:]
< Referrer-Policy: [strict-origin-when-cross-origin]

213 bytes of content.

[ERROR]   UserResourceIT.getAllAuthorities:462 Status expected:<200 OK> but was:<500 INTERNAL_SERVER_ERROR>

> GET /api/users/authorities
> WebTestClient-Request-Id: [47]
> Accept: [application/json]

No content

< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Vary: [Origin, Access-Control-Request-Method, Access-Control-Request-Headers]
< Content-Type: [application/problem+json]
< Content-Length: [217]
< Cache-Control: [no-cache, no-store, max-age=0, must-revalidate]
< Pragma: [no-cache]
< Expires: [0]
< X-Content-Type-Options: [nosniff]
< X-XSS-Protection: [1 ; mode=block]
< Feature-Policy: [geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none']
< Content-Security-Policy: [default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:]
< Referrer-Policy: [strict-origin-when-cross-origin]

217 bytes of content.

[INFO] 
[ERROR] Tests run: 88, Failures: 2, Errors: 0, Skipped: 0

Because of this, I decided to try Cassandra and Neo4J.

With Cassandra, the app doesn't even compile:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project tmp: Compilation failure: Compilation failure: 
[ERROR] /home/mraible/tmp/src/main/java/com/mycompany/myapp/web/rest/UserJWTController.java:[6,35] cannot find symbol
[ERROR]   symbol:   class AuditEventService
[ERROR]   location: package com.mycompany.myapp.service
[ERROR] /home/mraible/tmp/src/main/java/com/mycompany/myapp/web/rest/UserJWTController.java:[33,19] cannot find symbol
[ERROR]   symbol:   class AuditEventService
[ERROR]   location: class com.mycompany.myapp.web.rest.UserJWTController
[ERROR] /home/mraible/tmp/src/main/java/com/mycompany/myapp/web/rest/UserJWTController.java:[35,112] cannot find symbol
[ERROR]   symbol:   class AuditEventService
[ERROR]   location: class com.mycompany.myapp.web.rest.UserJWTController
[ERROR] -> [Help 1]

With Neo4J, there's an error when running tests and it takes forever:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [ac.simons.neo4j.migrations.core.MigrationsConfig]: Factory method 'neo4jMigrationsConfig' threw exception; nested exception is ac.simons.neo4j.migrations.core.MigrationsException: No package to scan is configured and none of the configured locations exists.
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
    ... 84 common frames omitted
Caused by: ac.simons.neo4j.migrations.core.MigrationsException: No package to scan is configured and none of the configured locations exists.
    at ac.simons.neo4j.migrations.springframework.boot.autoconfigure.MigrationsAutoConfiguration.checkLocationExists(MigrationsAutoConfiguration.java:92)
    at ac.simons.neo4j.migrations.springframework.boot.autoconfigure.MigrationsAutoConfiguration.neo4jMigrationsConfig(MigrationsAutoConfiguration.java:57)
    at sun.reflect.GeneratedMethodAccessor495.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 85 common frames omitted
Motivation for or Use Case

In theory, WebFlux should work with all NoSQL databases.

Reproduce the error

Create a reactive app with Couchbase, Cassandra, or Neo4J. Run mvn verify.

Related issues
Suggest a Fix
JHipster Version(s)

master branch

$$ bug-bounty $$ $100 area couchbase reactive 鈿涳笍

Most helpful comment

@pascalgrimaud, working on it

All 5 comments

@tchlyah : as you're our expert on Couchbase, can you help plz ?

For Neo4j we are aware of that issues. Looking into it with Michael and Gerrit. Most likely a mistake in the entity definition and bi-directional relationships (or with sdn/rx beta).

@pascalgrimaud, working on it

@tchlyah Thanks for your help! I've added a $100 bounty to this issue.

After extensive investigation I found that Spring Reactor is not fully compatible with SpEL expressions (DATACMNS-1108), which we are using here.

As you can see in SecurityEvaluationContextExtension#117, we are trying to get SecurityContext from SecurityContextHolder, which doesn't hold the authentication in reactor. I tried to implement a version with ReactiveSecurityContextHolder, but since the call is made on the reactor thread, we can't block in order to get Authentication object.

Since we are not using security in our spEL expressions, we can disable SecurityEvaluationContextExtension, sadly, the bean is created in SecurityDataConfiguration which is imported by SecurityAutoConfiguration. So there is no easy way to disable that.

The only workaround I came up with is very ugly, but working:

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension() {
        @Override
        public Object getRootObject() {
            return null;
        }
    };
}

If it is ok with you I can make a PR with this along with some other fixes for Couchbase Reactive

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomj0101 picture tomj0101  路  3Comments

kaidohallik picture kaidohallik  路  3Comments

SudharakaP picture SudharakaP  路  3Comments

edvjacek picture edvjacek  路  3Comments

trajakovic picture trajakovic  路  4Comments