jhipster / jhipster-core

JHipster Domain Language, used by JHipster UML and JDL-Studio to generate entities
Apache License 2.0
345 stars 116 forks source link

Import of Microservice Entity Fails #176

Closed ruddell closed 6 years ago

ruddell commented 6 years ago

The issue

Importing the following JDL in its microservice results in an error:

entity A {
    name String
}
microservice A with ms
$ jhipster import-jdl test.jdl
TypeError: Cannot set property 'microserviceName' of undefined
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: ERROR! 
Error while parsing entities from JDL

    at Environment.error (/Users/ruddell/Dev/Contrib/generator-jhipster/node_modules/yeoman-environment/lib/environment.js:157:40)
    at module.exports.error (/Users/ruddell/Dev/Contrib/generator-jhipster/generators/generator-base.js:2030:18)
    at module.exports.parseJDL (/Users/ruddell/Dev/Contrib/generator-jhipster/generators/import-jdl/index.js:116:26)
    at Object.<anonymous> (/Users/ruddell/Dev/Contrib/generator-jhipster/node_modules/yeoman-generator/lib/index.js:399:25)
    at /Users/ruddell/Dev/Contrib/generator-jhipster/node_modules/yeoman-generator/node_modules/run-async/index.js:25:25
    at new Promise (<anonymous>)
    at /Users/ruddell/Dev/Contrib/generator-jhipster/node_modules/yeoman-generator/node_modules/run-async/index.js:24:19
    at self.env.runLoop.add.completed (/Users/ruddell/Dev/Contrib/generator-jhipster/node_modules/yeoman-generator/lib/index.js:400:11)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)

Suggest a fix

The method causing issues is setEntityNamesOptions in entity_parser.js. It attempts to set the microserviceName for a * entity which does not exist as a key in the entities object.

Reproduce the error

Generate a microservice with the ms basename and import the above JDL. Config provided below.

Related issues

https://github.com/jhipster/generator-jhipster/issues/7015 https://github.com/jhipster/generator-jhipster/issues/6712

Suggest a Fix

Not sure

The JDL file

entity A {
    name String
}
microservice A with ms
JHipster configuration, a .yo-rc.json file generated in the root folder
.yo-rc.json file
{
  "generator-jhipster": {
    "promptValues": {
      "packageName": "com.mycompany.myapp",
      "nativeLanguage": "en"
    },
    "jhipsterVersion": "4.13.3",
    "baseName": "ms",
    "packageName": "com.mycompany.myapp",
    "packageFolder": "com/mycompany/myapp",
    "serverPort": "8081",
    "authenticationType": "jwt",
    "cacheProvider": "hazelcast",
    "enableHibernateCache": true,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "prodDatabaseType": "mysql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": "eureka",
    "buildTool": "maven",
    "enableSocialSignIn": false,
    "enableSwaggerCodegen": false,
    "jwtSecretKey": "replaced-by-jhipster-info",
    "enableTranslation": true,
    "applicationType": "microservice",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "nativeLanguage": "en",
    "languages": [
      "en"
    ],
    "clientPackageManager": "yarn",
    "skipClient": true,
    "skipUserManagement": true
  }
}

Versions

JHipster
v4.13.3
MathieuAA commented 6 years ago

I'll have a look

MathieuAA commented 6 years ago

I couldn't reproduce it... in the JCore project using a custom test suite:

/* eslint-disable no-unused-expressions,mocha/no-exclusive-tests */
const expect = require('chai').expect;
const parseFromFiles = require('../../../lib/reader/jdl_reader').parseFromFiles;
const EntityParser = require('../../../lib/parser/entity_parser');
const JDLParser = require('../../../lib/parser/jdl_parser');

describe.only('176', () => {
  let content = null;

  before(() => {
    const input = parseFromFiles(['./test/spec/debug/debug.jdl']);
    content = EntityParser.parse({
      jdlObject: JDLParser.parse(input, 'mysql'),
      databaseType: 'mysql'
    });
  });

  it('works', () => {
    expect(content).not.to.be.null;
  });
});

and by creating an application from your .yo-rc.json file and importing the JDL file. Did I miss something here?

ruddell commented 6 years ago

Here's a failing test, it's this section of the parseJDL method from the import-jdl subgenerator.

/* eslint-disable no-unused-expressions,mocha/no-exclusive-tests */
const expect = require('chai').expect;
const parseFromFiles = require('../../../lib/reader/jdl_reader').parseFromFiles;
const EntityParser = require('../../../lib/parser/entity_parser');
const JDLParser = require('../../../lib/parser/jdl_parser');

describe.only('176', () => {
  let content = null;

  before(() => {
    this.prodDatabaseType = 'mysql';
    this.applicationType = 'microservice';
    this.baseName = 'ms';
    this.jdlFiles = ['./test/spec/debug/debug.jdl'];

    const jdlObject = JDLParser.parse(
      parseFromFiles(this.jdlFiles),
      this.prodDatabaseType,
      this.applicationType,
      this.baseName
    );
    content = EntityParser.parse({
      jdlObject,
      databaseType: this.prodDatabaseType,
      applicationType: this.applicationType
    });
  });

  it('works', () => {
    expect(content).not.to.be.null;
  });
});
sendilkumarn commented 6 years ago

There is a similar issue when using enum with microservices.

MathieuAA commented 6 years ago

Thanks, I'm on it

MathieuAA commented 6 years ago

I still can't reproduce... this is kinda frustrating as this looks like a big issue. My tests:

I may have missed something here, but this is crazy

ruddell commented 6 years ago

@MathieuAA Does the test in my last message pass for you? From what I see the issue only happens when the baseName in the .yo-rc.json matches the microservice specified in the JDL.

# in a new folder

# this yo-rc.json file has a matching baseName and fails
echo '{ "generator-jhipster": { "promptValues": { "packageName": "com.mycompany.myapp", "nativeLanguage": "en" }, "jhipsterVersion": "4.13.3", "baseName": "ms",       "packageName": "com.mycompany.myapp", "packageFolder": "com/mycompany/myapp", "serverPort": "8081", "authenticationType": "jwt", "cacheProvider": "hazelcast", "enableHibernateCache": true, "websocket": false, "databaseType": "sql", "devDatabaseType": "h2Disk", "prodDatabaseType": "mysql", "searchEngine": false, "messageBroker": false, "serviceDiscoveryType": "eureka", "buildTool": "maven", "enableSocialSignIn": false, "enableSwaggerCodegen": false, "jwtSecretKey": "replaced-by-jhipster-info", "enableTranslation": true, "applicationType": "microservice", "testFrameworks": [], "jhiPrefix": "jhi", "nativeLanguage": "en", "languages": [ "en" ], "clientPackageManager": "yarn", "skipClient": true, "skipUserManagement": true } }' > .yo-rc.json

# this yo-rc.json file has a different baseName and the entity generates without issue (even though it doesn't belong to this microservice)
#echo '{ "generator-jhipster": { "promptValues": { "packageName": "com.mycompany.myapp", "nativeLanguage": "en" }, "jhipsterVersion": "4.13.3", "baseName": "jhipster", "packageName": "com.mycompany.myapp", "packageFolder": "com/mycompany/myapp", "serverPort": "8081", "authenticationType": "jwt", "cacheProvider": "hazelcast", "enableHibernateCache": true, "websocket": false, "databaseType": "sql", "devDatabaseType": "h2Disk", "prodDatabaseType": "mysql", "searchEngine": false, "messageBroker": false, "serviceDiscoveryType": "eureka", "buildTool": "maven", "enableSocialSignIn": false, "enableSwaggerCodegen": false, "jwtSecretKey": "replaced-by-jhipster-info", "enableTranslation": true, "applicationType": "microservice", "testFrameworks": [], "jhiPrefix": "jhi", "nativeLanguage": "en", "languages": [ "en" ], "clientPackageManager": "yarn", "skipClient": true, "skipUserManagement": true } }' > .yo-rc.json

# generate the project
jhipster

# write the JDL to a file
echo 'entity A { name String } microservice A with ms' > test.jdl

# import the JDL
jhipster import-jdl test.jdl --force

I verified this with the jhipster docker image so it's definitely reproducible.

# running the jhipster image which contains the latest version pre-installed
docker run --name jhipster -td jhipster/jhipster
docker container exec -it jhipster bash 

# run the commands from the previous code section

I haven't looked into the enum issue at all

MathieuAA commented 6 years ago

Ah! Now it fails, good!

MathieuAA commented 6 years ago

It works when using * or all, that's one good bug :)

MathieuAA commented 6 years ago

Okay, got it. Fixing it now and releasing right after. Thanks @ruddell and @sendilkumarn (I've yet to reproduce yours by the way, but I think it's the same, enums being field types...).

MathieuAA commented 6 years ago

Some background for the fix:

Now, we had this bug because I didn't respect the contract (I typed entities instead of entityNames, which is just plain stupid... my bad). The microservice option was created without any entity (should have used the right key in my object), and the default behavior being of the second case... that's why the entity had in its JSON microservice: ms.