I use JDL file
entity Material {
name String
}
entity MaterialOrigin {
name String
}
relationship ManyToMany {
Material{origin} to MaterialOrigin{material}
}
This wrongly generates relationship table name as "material_origin" instead of "material_origin_material" in files:
* `.../domain/Material.java`
* `.../changelog/..._added_entity_constraints_Material.xml`
* `.../changelog/..._added_entity_Material.xml`
The issue reveals itself on `./mvnw` with the error
WARN 26590 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'servletEndpointRegistrar' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar]: Factory method 'servletEndpointRegistrar' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'auditEventsEndpoint' defined in class path resource [org/springframework/boot/actuate/autoconfigure/audit/AuditEventsEndpointAutoConfiguration.class]: Unsatisfied dependency expressed through method 'auditEventsEndpoint' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customAuditEventRepository' defined in file [.../target/classes/com/company/app/repository/CustomAuditEventRepository.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistenceAuditEventRepository': Cannot create inner bean '(inner bean)#1c95bc62' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1c95bc62': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FKipo7e0wsvsnrag9hoy1hnmeb6:material_origin [origin_id])) must have same number of columns as the referenced primary key (material_origin [material_id,origin_id])
##### **Motivation for or Use Case**
The app fails to run without a proper relation table. The `material_origin_material` is not even described anywhere despite being referenced from `.../changelog/..._added_entity_MaterialOrigin.xml`.
##### **Reproduce the error**
1. Initialize fresh app with `jhipster` and all the defaults (just hit enter like 10 times)
2. Save the JDL above to the `jhipster-many-to-many-bug.jdl`
3. Bootstrap models with `jhipster import-jdl ./jhipster-many-to-many-bug.jdl --force`
4. `./mvnw`
##### **Related issues**
I didn't find any.
##### **Suggest a Fix**
##### **JHipster Version(s)**
6.5.1
##### **JHipster configuration**
INFO! Using JHipster version installed locally in current project's node_modules
INFO! Executing jhipster:info
INFO! Options: from-cli: true
##### **JHipster Version(s)**
[email protected] /home/nikolay.seliverstov/Projects/jh-manytomany-bug
└── [email protected]
##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
{
"generator-jhipster": {
"promptValues": {
"packageName": "com.janssen.fsra",
"nativeLanguage": "en"
},
"jhipsterVersion": "6.5.1",
"applicationType": "monolith",
"baseName": "jhipster",
"packageName": "com.janssen.fsra",
"packageFolder": "com/janssen/fsra",
"serverPort": "8080",
"authenticationType": "jwt",
"cacheProvider": "ehcache",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "mysql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSwaggerCodegen": false,
"jwtSecretKey": "bXktc2VjcmV0LXRva2VuLXRvLWNoYW5nZS1pbi1wcm9kdWN0aW9uLWFuZC10by1rZWVwLWluLWEtc2VjdXJlLXBsYWNl",
"embeddableLaunchScript": false,
"useSass": true,
"clientPackageManager": "npm",
"clientFramework": "angularX",
"clientTheme": "none",
"clientThemeVariant": "",
"testFrameworks": [],
"jhiPrefix": "jhi",
"entitySuffix": "",
"dtoSuffix": "DTO",
"otherModules": [],
"enableTranslation": true,
"nativeLanguage": "en",
"languages": ["en"],
"blueprints": []
}
}
entityName.json files generated in the .jhipster directory
JDL entity definitions
entity Material {
name String
}
entity MaterialOrigin {
name String
}
relationship ManyToMany {
Material{origin} to MaterialOrigin{material}
}
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.5+10, mixed mode)
git version 2.17.1
node: v8.15.1
npm: 6.4.1
yeoman: 3.1.1
Docker version 19.03.5, build 633a0ea838
docker-compose version 1.23.2, build 1110ad01
entityName.json files generated in the .jhipster directory
Material.json
{
"name": "Material",
"fields": [
{
"fieldName": "name",
"fieldType": "String"
}
],
"relationships": [
{
"relationshipType": "many-to-many",
"otherEntityName": "materialOrigin",
"otherEntityRelationshipName": "material",
"relationshipName": "origin",
"otherEntityField": "id",
"ownerSide": true
}
],
"changelogDate": "20191220115447",
"entityTableName": "material",
"dto": "no",
"pagination": "no",
"service": "no",
"jpaMetamodelFiltering": false,
"fluentMethods": true,
"readOnly": false,
"clientRootFolder": "",
"applications": "*"
}
MaterialOrigin.json
{
"name": "MaterialOrigin",
"fields": [
{
"fieldName": "name",
"fieldType": "String"
}
],
"relationships": [
{
"relationshipType": "many-to-many",
"otherEntityName": "material",
"otherEntityRelationshipName": "origin",
"relationshipName": "material",
"otherEntityField": "id",
"ownerSide": false
}
],
"changelogDate": "20191220115448",
"entityTableName": "material_origin",
"dto": "no",
"pagination": "no",
"service": "no",
"jpaMetamodelFiltering": false,
"fluentMethods": true,
"readOnly": false,
"clientRootFolder": "",
"applications": "*"
}
Ubuntu 18.04
Firefox 71
The second issue is that the FK descriptions for the relationship keys are being created twice:
entity_constraints_Materialentity_constraints_MaterialOriginI referenced this bug on a commit by mistake.
Hm. I can try to follow the https://github.com/jhipster/jhipster-core/issues/404#issuecomment-566462309 but do not think that can help with the issue. Let me check.
You can try these steps
jhipster-many-to-many-bug.jdl inside the folder with the contents
application {
config {
databaseType sql
devDatabaseType h2Disk
enableHibernateCache true
enableSwaggerCodegen false
enableTranslation true
jhiPrefix jhi
languages [en]
messageBroker false
nativeLanguage en
packageName com.acme
//packageFolder "com/acme"
prodDatabaseType mysql
searchEngine false
serviceDiscoveryType false
skipClient false
skipServer false
testFrameworks []
websocket false
jhipsterVersion "6.5.1"
applicationType monolith
baseName jhipster
serverPort 8080
authenticationType jwt
cacheProvider ehcache
buildTool maven
//jwtSecretKey MGNhZjk2ZTFlYTU0YmQ0NWU0MTYxMWVjZjBiMGI1YzE1N2Q1YzFkN2M5M2EwODcxNWM5OTI4NTFhMGY4NDdkMTkzNmZmN2Q1MTljZWE4N2U3MmFjNDQ5NzZlNmRkYjcyNGRjMWUxMTQ1NWYwNGIxMWQ2OWUyODY2MTI4ZmQxMmM=
//embeddableLaunchScript false
useSass true
clientPackageManager npm
clientFramework angularX
clientTheme none
clientThemeVariant
entitySuffix
dtoSuffix DTO
//otherModules []
//blueprints []
skipUserManagement false
}
entities Material, MaterialOrigin
}
entity Material {
name String
}
entity MaterialOrigin {
name String
}
relationship ManyToMany {
Material{origin} to MaterialOrigin{material}
}
jhipster import-jdl jhipster-many-to-many-bug.jdlAnd you still can observe the bug above. So it's not related to the config conflicts (jhipster/jhipster-core#404).
I'm moving it to JCore. And I don't think it's related to the 404.
I've tried generating the entities/relationship with the CLI, the only difference I've got between the generated JSON is in MaterialOrigin.json, is the "otherEntityField": "id" attribute that shouldn't be here.
Apart from that, the generation is the same...
Well, the issue is not about difference between cli and something else. The issue that I have entity that generates the table material_origin plus the framework tries to generate the many to many relationship table with the same name. Which is obviously wrong.
In the JDL, you have the option to specify the table name.
Like that
entity MyEntity(my_table_name)
Currently I see two workarounds. One is to rename the material_origin table to something like MaterialOrigin(material_origin_name). The second one is to change the owner of the relationship. But that's usually not desirable. Personally I go by simply fixing the generated files
The issue that I have my own table material_origin and the framework tries to generate the many to many relationship table with the same name. Which is obviously wrong.
Do you mean that you had an existing table in your DB and you used JHipster on top of the same schema?
No, I'm not. The entity Material Origin generates table with the name material_origin and the many to many relationship generates a table with the exact same name. The compilation is ok but these explode in runtime.
Moving it back to the generator, it's a deeper issue than just JDL generation.
Should we rename the issue to express that?
Currently I see two workarounds. One is to rename the material_origin table to something like MaterialOrigin(material_origin_name). The second one is to change the owner of the relationship. But that's usually not desirable. Personally I go by simply fixing the generated files
Which files needs to be fixed?
Please see the list of the affected files in the issue description. If you are asking about list of jhipster source files then I cannot help here. I didn't dive into the issue that deep.
https://github.com/jhipster/generator-jhipster/blob/307ab155caae45ed466eb5b0875f1a3f62632263/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity.xml.ejs#L167
https://github.com/jhipster/generator-jhipster/blob/307ab155caae45ed466eb5b0875f1a3f62632263/generators/entity-server/templates/src/main/resources/config/liquibase/changelog/added_entity_constraints.xml.ejs#L45
https://github.com/jhipster/generator-jhipster/blob/307ab155caae45ed466eb5b0875f1a3f62632263/generators/entity-server/templates/src/main/java/package/domain/Entity.java.ejs#L333
You can fix by changing the relationship name.
To fix this issue on generator we have 2 options:
http://dev.mysql.com/doc/refman/5.5/en/identifiers.html
https://www.postgresql.org/docs/8.0/sql-syntax.html#SQL-SYNTAX-IDENTIFIERS
https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm
Added a test to jdl integration-test at:
https://github.com/mshima/generator-jhipster/commit/806935756e280d38210ad02c69c65ff6bc6bf847
I would go with ability to change the resulting relationship table name. But I guess this is too hard since JDL syntax lacks the feature.
I guess jhipster just messed up some variables in the templates. Since there is ../changelog/..._added_entity_constraints_MateriaOriginl.xml that refers the correct relationship table name (material_origin_material). The problem that the table being created with a different name (material_origin).
If you are not using any blueprint, you can try the following:
npm install generator-jhipster-customizer
jhipster import-jdl many-to-many-bug.jdl --blueprints customizer --customizers relationship_separator
jhipster import-jdl many-to-many-bug.jdl --blueprints customizer --customizers relationship_separator
You have to rerun the command after first error.
Let me know if it fixes the problem.
@mshima I'm sorry, but why do we need a separate generator in order to fix the bug?
Is it possible to detect name clashing beforehand and generate an alternative relationship table name in case of clashing like <rel_name1>_<rel_name2> -> <rel_name1>_<rel_name2>_rel ?
But I guess the collision finding is out of the scope that's why the current solution is like that.
@mshima I'm sorry, but why do we need a separate generator in order to fix the bug?
No, it's just a workaround.
The bug is triaged.
The fix is simple.
The patch is ready.
But it's a breaking change when regenerating.
JHipster Developers don't agree that we should create a config to workaround this.
https://github.com/jhipster/generator-jhipster/pull/11030#discussion_r362032865
Is it possible to detect name clashing beforehand and generate an alternative relationship table name in case of clashing like
<rel_name1>_<rel_name2>-><rel_name1>_<rel_name2>_rel?
Adding prefix of suffix, will not fix relations like
relation_name -> other = relation_name_other
rel -> name_other = relation_name_other
I think we should add prefix rel_ to tables.
It will be easier to differentiate between other tables, but is not needed to fix this.
But I guess the collision finding is out of the scope that's why the current solution is like that.
Yes, too hard.
Should implement this?
Change relationships table name with:
To be honest I would use $tablename1_$tablename2 instead of the current $tablename1_$reffieldname.
rel_ sounds good to me
@pascalgrimaud with our current entities adding a rel_ prefix and __ separator tests do not pass.
Only pass with 1 character prefix.
To be honest I would use
$tablename1_$tablename2instead of the current$tablename1_$reffieldname.
Then you would have conflict when creating 2 relationships with same entity.
with our current entities adding a rel_ prefix and __ separator tests do not pass. Only pass with 1 character prefix.
Do you understand why ?
So what do you suggest for this @mshima ?
@pascalgrimaud table name conflicts due to trimming.
Could be fixed by renaming some entities.
IMO change separator only.
r_ prefix would be nice, not sure about _ prefix.
another idea would be to generate a hash, using the name of entities: rel_hash
so with this solution, we can regenerate entities without changing the name of relationships
what do you think ?
@pascalgrimaud I like the idea of hashing.
But more like rel_ prefix, __ separator, _xxx 3 char hash suffix.
I think it’s important to keep entity name for db maintenance.
keeping entity name is important for db maintenance, you're right, and 3 char hash suffix would be enough to avoid conflict