jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.55k stars 4.03k forks source link

Combined fields or 'calculated field' in relationship display field #18589

Closed sytzefluenc closed 2 years ago

sytzefluenc commented 2 years ago
Overview of the feature request

When using relationships one can provide the display field:

\<display field> is the name of the field that should show up in select boxes (default: id)

Motivation for or Use Case

In a lot of cases a single field however is not sufficient to identify the entity that you want to select. In the often used example of Employees and Departments for example, it would be nice to be able to select an employee based on their full name (i.e. their first and last name).

Of course this can all be accomplished by changing the code once it has been generated, but to be able to update a jdl in future I prefer to change the generated as little as possible.

I see two solution directions:

1. provide the ability to create a display field (based on string values) in the relationship display name:
entity Job {
    jobTitle String
}
entity Employee{
    firstName String
    lastName String
}
entity Department{
    title String
}

relationship OneToMany {
    Employee{job(jobTitle)} to Job{employee(firstName + ' ' + lastName)},
    Department{employee(firstName + ' ' lastName)} to Employee{Department(title)}
}
2. provide the ability for a calculated field, which then can be used as display field
entity Job {
    jobTitle String
}
entity Employee{
    firstName String
    lastName String
    name= firstName + ' ' + lastName
}
entity Department{
    title String
}

relationship OneToMany {
    Employee{job(jobTitle)} to Job{employee(name)},
    Department{employee(name)} to Employee{Department(title)}
}
Related issues or PR

Issue sligthly relates to https://github.com/jhipster/generator-jhipster/issues/8361

mshima commented 2 years ago

You can implement using dto/mapstruct mapping like: https://github.com/jhipster/generator-jhipster/blob/ba71168e1b9a6747af9cfe31e9f7d62e304750e1/test-integration/samples/jdl-entities/entities.jdl#L7-L8

By other’s means it would make templates more complex and out of JHipster scope.

sytzefluenc commented 2 years ago

So what you are actually stating is that the 'calculated field' functionality is already available using MapstructExpressions.

Do I understand the matter correctly that this means I can have the 'firstName lastName' displayed in a drop down list by specifying the jdl as:

entity Job {
    jobTitle String
}
entity Employee{
    firstName String
    lastName String

   @MapstructExpression("java(s.getFistName() + ' ' + s.get.LastName())") 
    fullName String
}
entity Department{
    title String
}

relationship OneToMany {
    Employee{job(jobTitle)} to Job{employee(fullName)},
    Department{employee(fullName)} to Employee{Department(title)}
}

 dto Employee with mapstruct

This results in my project (different entities, but same structure) in the fact that I do have a displayName as read-only field in my entity (view, edit and add) page. However having fullName as display field in the relationship gives a compile error on the microservice:

error: No property named "fullName" exists in source parameter(s). Did you mean "firstName"?
    EmployeeDTO toDtoFullName(Employee employee);

Anything that I do wrong?

mshima commented 2 years ago

@sytzefluenc relationships with dto entities with non dto entities are not supported. dto * with mapstruct

sytzefluenc commented 2 years ago

Well :-(

This is my complete fullName.jdl:

application {
  config {
    baseName hrfrontend
    packageName com.example.fullname.hrfrontend
    applicationType gateway
    authenticationType oauth2
    prodDatabaseType postgresql
    devDatabaseType postgresql
    buildTool gradle
    serviceDiscoveryType eureka
    testFrameworks [gatling]
  }
  entities Job, Employee, Department
}

application {
  config {
    baseName hrservice
    packageName com.example.fullname.hrservice
    applicationType microservice
    authenticationType oauth2
    prodDatabaseType postgresql
    devDatabaseType postgresql
    buildTool gradle
    serverPort 8081
    serviceDiscoveryType eureka
    searchEngine elasticsearch
  }
  entities Job, Employee, Department
}

entity Job {
    jobTitle String
}

entity Employee{
    firstName String
    lastName String

   @MapstructExpression("java(s.getFirstName() + ' ' + s.getLastName())") 
    fullName String
}

entity Department{
    title String
}

relationship OneToMany {
    Employee{job(jobTitle)} to Job{employee(fullName)},
    Department{employee(fullName)} to Employee{Department(title)}
}

dto Job, Employee, Department with mapstruct

microservice Job, Employee, Department with hrservice

// will be created under 'docker-compose' folder
deployment {
  deploymentType docker-compose
  appsFolders [hrfrontend,hrservice]
}

I run a jhipster import-jdl fullName.jdl and then try to create the docker images as mentioned in the output:

To generate the missing Docker image(s), please run:
  ./gradlew bootJar -Pprod jibDockerBuild in <path-to>/hrfrontend
  ./gradlew bootJar -Pprod jibDockerBuild in <path-to>/hrservice

the hrfrontend compile is successful, the hrservice compile fails with an error (and 4 warnings):

<path-to>/hrservice/src/main/java/com/example/fullname/hrservice/service/mapper/EntityMapper.java:17: warning: Unmapped target properties: "employees, removeEmployee".
    E toEntity(D dto);
      ^
<path-to>/hrservice/src/main/java/com/example/fullname/hrservice/service/mapper/EntityMapper.java:27: warning: Unmapped target properties: "employees, removeEmployee".
    void partialUpdate(@MappingTarget E entity, D dto);
         ^
<path-to>/hrservice/src/main/java/com/example/fullname/hrservice/service/mapper/EntityMapper.java:17: warning: Unmapped target properties: "jobs, removeJob".
    E toEntity(D dto);
      ^
<path-to>/hrservice/src/main/java/com/example/fullname/hrservice/service/mapper/EntityMapper.java:27: warning: Unmapped target properties: "jobs, removeJob".
    void partialUpdate(@MappingTarget E entity, D dto);
         ^
<path-to>/hrservice/src/main/java/com/example/fullname/hrservice/service/mapper/EmployeeMapper.java:20: error: No property named "fullName" exists in source parameter(s). Did you mean "firstName"?
    EmployeeDTO toDtoFullName(Employee employee);
                ^
Note: Hibernate JPA 2 Static-Metamodel Generator 5.4.32.Final
1 error
4 warnings

So it seems somewhere I make a mistake? (thanks for your patience)

sytzefluenc commented 2 years ago

Should I report above mentioned behavior as a bug?