Generator-jhipster: Same entity name in several MicroServices collide in the Gateway

Created on 5 Oct 2017  ยท  16Comments  ยท  Source: jhipster/generator-jhipster

Overview of the issue

When doing microservices, you often find the same entity name but with different purposes. For example, a Customer in the Invoice microservice, does not have the same attributes/methods as a Customer in the Shipping microservice.

When those two Customer entities are generated in the Gateway, they collide: only the last one remains. So it makes it totally unusable to have the same entity name in different services.

Motivation for or Use Case

We have an architecture with a few microservices. Following some DDD principles, we end up with a few similar entity names, but doing different things (eg. Customer, Document, Service, Event....). They have the same name because it's important for our business, but they have totally different attributes.

We would need the Gateway to make a clear separation between those "similar" entities (in terms of TypeScript code, and in terms of graphical components and menus).

Reproduce the error

Create an Invoice microservice and import the following JDL :

entity Customer {
    firstName String,
    lastName String,
    company String,
    linkedInUrl String
}
Create a `Shipping` microservice and import the following JDL:
entity Customer {
    firstName String,
    lastName String,
    gender Gender,
    blogUrl String,
    twitterUrl String,
    githubUrl String
}

enum Gender {
M, F
}
Now, create a Gateway, import first the `Invoice` JDL, and then the `Shipping` JDL. Only the `Customer` from `Shipping` will remain. ##### **Related issues** * https://github.com/jhipster/generator-jhipster/issues/6480 * https://github.com/jhipster/generator-jhipster/issues/4431 ##### **Suggest a Fix** One easy fix would be for us to have different entity names. Instead of `Customer`, we could have `ShippingCustomer` and `InvoiceCustomer`. But this is not acceptable. One fix would be to have different packages (based on the `baseName` of the microservice). For example, on the web part of it, instead of having :
gateway/src/main/webapp/app/entities/customer
We would have a sub-package with the `baseName` of the microservice:
gateway/src/main/webapp/app/entities/invoice/customer
gateway/src/main/webapp/app/entities/shipping/customer
There is also one and only one "Customer" entry in the "Entities" menu. There should be two (with sub-menus) ##### **JHipster Version(s)**
[email protected] /Users/agoncal/Documents/Code/Temp/jhipster/buggateway/gateway
โ””โ”€โ”€ [email protected] 

##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
.yo-rc.json file
{
  "generator-jhipster": {
    "promptValues": {
      "packageName": "org.demo.gateway"
    },
    "jhipsterVersion": "4.9.0",
    "baseName": "gateway",
    "packageName": "org.demo.gateway",
    "packageFolder": "org/demo/gateway",
    "serverPort": "8080",
    "authenticationType": "jwt",
    "hibernateCache": "hazelcast",
    "clusteredHttpSession": false,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Memory",
    "prodDatabaseType": "postgresql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": "eureka",
    "buildTool": "maven",
    "enableSocialSignIn": false,
    "enableSwaggerCodegen": false,
    "jwtSecretKey": "replaced-by-jhipster-info",
    "clientFramework": "angularX",
    "useSass": false,
    "clientPackageManager": "yarn",
    "applicationType": "gateway",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "enableTranslation": false
  }
}

JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory


JDL entity definitions

entity Customer (customer) {
  firstName String,
  lastName String,
  company String,
  linkedInUrl String
}




Environment and Tools

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

git version 2.14.2

node: v8.6.0

npm: 5.3.0

bower: 1.8.0

gulp:
[21:40:22] CLI version 1.3.0

yeoman: 2.0.0

yarn: 1.1.0

Docker version 17.09.0-ce, build afdb6d4

docker-compose version 1.16.1, build 6d1ac21

microservice

Most helpful comment

  • as @deepu105 says this has never been thought of
  • and @agoncal I agree having a prefix is better

Who's OK for doing the prefix solution? Please vote ๐Ÿ‘ on this comment, and help on a PR if you can.

  • I have no idea of the work this involves, but at least it needs quite a lot of tests
  • this is going to be breaking change for many people

All 16 comments

I've solved this in a project by using the entity-suffix option when generating an entity. This adds a suffix only in the client (gateway), so the Java files and API endpoints remain the same.

JDL:
angularSuffix * with -suffix-here

This does not work out of the box as the index.ts file is overriden.

I've now changed the JDL files to :

entity Customer {
    firstName String,
    lastName String,
    company String,
    linkedInUrl String
}
angularSuffix * with invoice

and

entity Customer {
    firstName String,
    lastName String,
    gender Gender,
    blogUrl String,
    twitterUrl String,
    githubUrl String
}

enum Gender {
M, F
}
angularSuffix * with shipping

When you generate the Customer entity for Invoice, you end up with customer-invoice* components under the customer directory. At this point index.ts contains:

export * from './customer-invoice.model';
export * from './customer-invoice-popup.service';
export * from './customer-invoice.service';
export * from './customer-invoice-dialog.component';
export * from './customer-invoice-delete-dialog.component';
export * from './customer-invoice-detail.component';
export * from './customer-invoice.component';
export * from './customer-invoice.route';

Then, you generate the Customer entity for Shipping. You end up with new customer-shipping* components under the same customer directory. But, unfortunatelly, at this point, the index.ts is overwridden and does not contain both components anymore (the customer-invoice is gone):

export * from './customer-shipping.model';
export * from './customer-shipping-popup.service';
export * from './customer-shipping.service';
export * from './customer-shipping-dialog.component';
export * from './customer-shipping-delete-dialog.component';
export * from './customer-shipping-detail.component';
export * from './customer-shipping.component'; 
export * from './customer-invoice.route';

So we end up with nasty errors:

ERROR in [at-loader] ./src/main/webapp/app/entities/customer/customer-invoice.module.ts:6:5 
    TS2305: Module '/src/main/webapp/app/entities/customer/index"' has no exported member 'CustomerInvoiceService'.

The way to solve this would be to have both components under two different directories:

  • customer-invoice
  • customer-shipping

I think this use case was never handled, maybe the folder name should be
suffixed with the angularSuffix value as well

Thanks & Regards,
Deepu

On Fri, Oct 6, 2017 at 9:26 AM, Antonio Goncalves notifications@github.com
wrote:

This does not work out of the box as the index.ts file is overriden.

I've now changed the JDL files to :

entity Customer {
firstName String,
lastName String,
company String,
linkedInUrl String
}
angularSuffix * with invoice

and

entity Customer {
firstName String,
lastName String,
gender Gender,
blogUrl String,
twitterUrl String,
githubUrl String
}

enum Gender {
M, F
}
angularSuffix * with shipping

When you generate the Customer entity for Invoice, you end up with
customer-invoice* components under the customer directory. At this point
index.ts contains:

export * from './customer-invoice.model';
export * from './customer-invoice-popup.service';
export * from './customer-invoice.service';
export * from './customer-invoice-dialog.component';
export * from './customer-invoice-delete-dialog.component';
export * from './customer-invoice-detail.component';
export * from './customer-invoice.component';
export * from './customer-invoice.route';

Then, you generate the Customer entity for Shipping. You end up with new
customer-shipping* components under the same customer directory. But,
unfortunatelly, at this point, the index.ts is overwridden and does not
contain both components anymore (the customer-invoice is gone):

export * from './customer-shipping.model';
export * from './customer-shipping-popup.service';
export * from './customer-shipping.service';
export * from './customer-shipping-dialog.component';
export * from './customer-shipping-delete-dialog.component';
export * from './customer-shipping-detail.component';
export * from './customer-shipping.component';
export * from './customer-invoice.route';

So we end up with nasty errors:

ERROR in [at-loader] ./src/main/webapp/app/entities/customer/customer-invoice.module.ts:6:5
TS2305: Module '/src/main/webapp/app/entities/customer/index"' has no exported member 'CustomerInvoiceService'.

The way to solve this would be to have both components under two different
directories:

  • customer-invoice
  • customer-shipping

โ€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/6480#issuecomment-334679543,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF37mMDy6mxeua3pti4kub1jwLQWnks5spdYSgaJpZM4PvmUE
.

If I can give my 2 cents here, prefixing the directory would be better than suffixing (event if you keep on suffixing the component name). This way, I would add the angularSuffix to all my JDL, and would have a nice directory structure ordered by the prefix. For example, I would end up with:

โ”œโ”€โ”€ shipping-customer
โ”‚ย ย  โ”œโ”€โ”€ customer-shipping.ts
โ”œโ”€โ”€ shipping-document
โ”‚ย ย  โ”œโ”€โ”€ document-shipping.ts
โ”œโ”€โ”€ shipping-event
โ”œโ”€โ”€ shipping-destination
โ”œโ”€โ”€ invoice-customer
โ”œโ”€โ”€ invoice-document
โ”œโ”€โ”€ invoice-event

Clearer to understand which entity belong to which microservice

  • as @deepu105 says this has never been thought of
  • and @agoncal I agree having a prefix is better

Who's OK for doing the prefix solution? Please vote ๐Ÿ‘ on this comment, and help on a PR if you can.

  • I have no idea of the work this involves, but at least it needs quite a lot of tests
  • this is going to be breaking change for many people

There's even a better way (well, that's the way I do ;o). To have a directory per microservice

โ”œโ”€โ”€ shipping
โ”‚   โ”œโ”€โ”€ customer
โ”‚   โ”œโ”€โ”€โ”œโ”€ customer.ts
โ”‚   โ”œโ”€โ”€โ”œโ”€ customer.html
โ”‚   โ”œโ”€โ”€ document
โ”‚   โ”œโ”€โ”€โ”œโ”€ document.ts
โ”‚   โ”œโ”€โ”€โ”œโ”€ document.html
โ”‚   โ”œโ”€โ”€ event
โ”‚   โ”œโ”€โ”€ destination
โ”œโ”€โ”€ invoice
โ”‚   โ”œโ”€โ”€ customer
โ”‚   โ”œโ”€โ”€ document
โ”‚   โ”œโ”€โ”€ event

And this could be the same structure for the "Entities" menu. When you have several entities, and several microservices, agreggating everything into a single gateway is fine (for security, admin....) but it becomes difficult to look for your entities in long menus. If there was a sub-menu per microservice, it would be easier.

using the suffix as prefix might be confusing, if prefix is really required I suggest adding a new flag for that

@agoncal yes that would be the best solution but unfortunately that would be a lot of changes but if anyone is willing to do then it is better than prefix/suffix

In either case since we use angularSuffix to suffix all the files I suggest we suffix the folder as well for consistency

@agoncal for this https://github.com/jhipster/generator-jhipster/pull/6609 is a quick fix for the moment as its better than nothing. Of course, organizing entities by microservice would be much nicer but I guess that can be a future enhancement. If you want I can keep this ticket open for tracking creating entities in separate folder based on microservice or we can close this and open a new issue for that.

@deepu105 Sounds good, I'll give it a try.

Just wondering. Do you have an issue for breaking changes for the next major release ? Reorganizing the packages could maybe be done in a 5.0 version. WDYT ?

The current change wouldn't be much of a breaking change in terms of API but in generated applications, this will cause trouble but that will be true for most of the changes we do unfortunately and I guess the users who use the suffix would have to rely on git to merge the folder name changes. If you are asking about organising entities by microservice then yes it might be nicer to do in next major as it will be much more difficult to merge

@deepu105 So any "JHipster 5.0 Roadmap" issue we could add this to ?

We will create a project when it's time, but at the moment none of the "big things" that are planned (like ReactJS support) require a major release. Besides, there are many things (like a book!) that require we don't break stuff now.

closing this as the issue in itself is resolved. But of course the organization of code can be improved but its a separate task that can be done later as improvement

@deepu105 I just regenerate my app with the latest version of JHipster. Now, all my components directory are suffixed with AngularJS suffix. So, under entities instead of:

โ”œโ”€โ”€ entities
โ”‚   โ”œโ”€โ”€ address
โ”‚   โ”œโ”€โ”€ contact
โ”‚   โ”œโ”€โ”€ tenant
โ”‚   โ””โ”€โ”€ venue

I have

โ”œโ”€โ”€ entities
โ”‚   โ”œโ”€โ”€ address-sponsor
โ”‚   โ”œโ”€โ”€ contact-sponsor
โ”‚   โ”œโ”€โ”€ tenant-sponsor
โ”‚   โ””โ”€โ”€ venue-sponsor

And because in my entities json files I have:

    "microserviceName": "sponsor",
    "angularJSSuffix": "sponsor"

I now have my modules that are named SponsorEventSponsorModule (the first Sponsor being the microservice name, the second Sponsor being the Angular suffix). We were worried about the merge issue if subdirectories were introduced, but now, with different directory name, we'll have the same merge issues.

I still think that subdirectories would be better. An easy one would be:

โ”œโ”€โ”€ entities
โ”‚   โ”œโ”€โ”€ sponsor   // microservice name
โ”‚   โ”‚   โ”œโ”€โ”€ address
โ”‚   โ”‚   โ”œโ”€โ”€ contact
โ”‚   โ”‚   โ”œโ”€โ”€ tenant
โ”‚   โ”‚   โ””โ”€โ”€ venue

A better one (well, in my opinion)

โ”œโ”€โ”€ sponsor   // microservice name
โ”‚   โ”œโ”€โ”€ entities
โ”‚   โ”‚   โ”œโ”€โ”€ address
โ”‚   โ”‚   โ”œโ”€โ”€ contact
โ”‚   โ”‚   โ”œโ”€โ”€ tenant
โ”‚   โ”‚   โ””โ”€โ”€ venue

BTW I've created an issue about directory structure in general https://github.com/jhipster/generator-jhipster/issues/6693

Was this page helpful?
0 / 5 - 0 ratings