JHipster Domain Language (JDL) - Applications
Syntax
The application declaration is done as follows:
application {
config {
<application option name> <application option value>
}
[entities <application entity list>]
[<options>]
}
- Application configuration keys/values are specified under
config
(which must be insideapplication
) - There can be 0, 1 or any application option as you want (provided they are valid)
- Entities that will be generated inside the application are listed via
entities
, this is the recommended way to generate entities in applications.- This can be omitted but generating entities inside the app would require doing it:
- from another JDL file inside the app
- or with the CLI
- This can be omitted but generating entities inside the app would require doing it:
- The
entities
keyword is optional: you can omit it, but every entity in the JDL file will be generated inside the application - Applications can have regular options (like
dto
orservice
), more information in the next section.
Options in applications
Option declarations (dto
, service
, skipServer
, etc.) are supported in JDL applications, but with some rules.
Say we have this JDL file:
application {
config {
baseName app1
}
entities A, B, C
dto * with mapstruct
}
application {
config {
baseName app2
}
entities C, D
paginate * with pagination except D
}
application {
config {
baseName app3
}
entities * except A, B, C, D, F
service * with serviceClass
}
entity A
entity B
entity C
entity D
entity E
entity F
paginate * with infinite-scroll
In this sample, we can see a few things:
- There are 6 declared entities in the JDL file:
A, B, C, D, E and F
. - We have 3 applications:
app1, app2 and app3
app1
usesA, B and C
app2
usesC and D
app3
usesE
(* except A, B, C, D, F
)
- Each of these applications declare options and a global option in also declared.
app1
usesdto
forA, B and C
app2
usespaginate
forC
(because there's an exception)app3
usesservice
forE
- The global one also uses
pagination
(for every entity)
Here's how files are generated:
app1
A
: will usepaginate with infinite-scroll
(the global option isn't overridden by a local one) anddto with mapstruct
B
: will use the same optionsC
: will also use the same options
app2
:C
: will usepaginate with pagination
(and notinfinite-scroll
, because the local one takes precedence)D
: will usepaginate with infinite-scroll
as the previous option doesn't includeD
app3
:E
: willpaginate with infinite-scroll
andservice E with serviceClass
This example illustrates the shadowing principle. Global options are supported and will be used by every declared application unless options are also declared in applications.
Also note this snippet taken from the previous sample in app3
:
entities * except A, B, C, D, F
service * with serviceClass
This basically means that app3
will only use E
and that the application's entities will use the service
option,
that means E
and not A to F
.
Finally, there the F
entity which isn't in any application and this entity will not be generated because of that.
Note: all regular options are supported at the moment.
Examples
Basic example
application {
config {
baseName exampleApp
applicationType gateway
}
}
More than one application
application {
config {
baseName exampleApp1
applicationType microservice
serverPort 9001
}
}
application {
config {
baseName exampleApp2
applicationType microservice
serverPort 9002
}
}
application {
config {
baseName exampleApp3
applicationType gateway
serverPort 9000
}
}
With entities
application {
config {
baseName exampleApp1
applicationType microservice
serverPort 9001
}
entities A
}
application {
config {
baseName exampleApp2
applicationType microservice
serverPort 9002
}
entities * except A
}
entity A
entity B
entity C
With options
application {
config {
baseName exampleApp1
applicationType microservice
serverPort 9001
}
entities A
dto A with mapstruct
}
application {
config {
baseName exampleApp2
applicationType microservice
serverPort 9002
}
entities * except A
paginate C with pagination
}
entity A
entity B
entity C
Complete example breakdowns
Example 1:
application {
config {
baseName myMonolith
applicationType monolith
}
entities * except C, D
}
application {
config {
baseName myGateway
applicationType gateway
serverPort 9042
}
entities * except A, B
}
application {
config {
baseName microserviceA
applicationType microservice
}
entities C
}
application {
config {
baseName microserviceB
applicationType microservice
serverPort 8082
}
entities D
}
entity A
entity B
entity C
entity D
dto * with mapstruct
service * with serviceClass
paginate D with pagination
Now, several things will happen when generating these applications and folders:
- Four applications will be created:
- myMonolith in
./myMonolith
, with the server port8080
- myGateway in
./myGateway
, with the server port9042
- microserviceA in
./microserviceA
, with the server port8081
- Even though we didn't specify a server port, JHipster sets one by default.
- For microservices, the default one is
8081
- For gateways and monoliths, it's
8080
- microserviceB in
./microserviceB
with the server port8082
- myMonolith in
- Four entities will be generated
A
andB
in the monolithC
andD
both in the gatewayC
in the first microserviceD
in the second microservice
- The
microservice
option is implicit forC
andD
- Because they get generated on the two microservices, this option will be set by default.
- Options work the same way as before
Note that the generator sets default values if they aren't present (like the databaseType
).
JHipster Core does the exact same things for you.
Example 2: with options
See the option section.
Microservice workflow
Dealing with microservices is a almost tricky, but the JDL gives you some options to handle your entities as you see fit.
With the microservice <ENTITIES> with <MICROSERVICE_APP_NAME>
you can specify which entity gets generated in which microservice.
Take this setup for instance:
entity A
entity B
entity C
microservice A with firstMS
microservice B with secondMS
Given two JHipster applications ('firstMS' and 'secondMS'), here's what you're going to get if you import the JDL file in the two applications:
- In 'firstMS', entities
A
andC
will be generated. - In 'secondMS', entities
B
andC
will be generated.
C
gets generated in both because if there's no microservice option specifying where this entity gets generated, it
will be generated everywhere.
If you decide to import this JDL in a monolith app, every entity will be generated (monoliths don't have restriction options in the JDL).
Note: if you want to make the same entity be generated in two different microservices, you can write two JDL files instead of updating the JDL file. Everytime.
The previous example couldn't have been written like this:
entity A
entity B
entity C
microservice * except B with firstMS
microservice * except A with secondMS
Here's the result:
- In 'firstMS', only the entity
C
will be generated - In 'secondMS', entities
B
andC
will be generated.
It's because, at parsing-time, if an option overlaps with another, the latter takes precedence. You can also create an entire microservice stack using JDL, see this blog post for example
Available application configuration options
Here are the application options supported in the JDL:
Not what you're looking for? Check the regular options.
JDL option name | Default value | Possible values | Comment |
---|---|---|---|
applicationType | monolith | monolith, microservice, gateway | - |
authenticationType | jwt | jwt, session, oauth2 | jwt |
baseName | jhipster | - | - |
DEPRECATED | See blueprints | ||
blueprints | [] | Names of additional blueprints. See Marketplace including custom blueprints internally published | Array of blueprints to use, e.g., [blueprint1, blueprint2] |
buildTool | maven | maven, gradle | - |
cacheProvider | ehcache or hazelcast | caffeine, ehcache, hazelcast, infinispan, memcached, redis, no | ehcache for monoliths and gateways, hazelcast otherwise |
clientFramework | angularX | angularX, angular, react, vue, svelte, no | - |
clientPackageManager | npm | npm | - |
clientTheme | none | Something or none | You can put whatever value you want, provided you know it will work (like yeti) |
clientThemeVariant | - | Something or primary | You can put whatever value you want, provided you know it will work (like dark, or light), can also be empty |
databaseType | sql | sql, mongodb, cassandra, couchbase, no | - |
devDatabaseType | h2Disk | h2Disk, h2Memory | * + the prod database type |
dtoSuffix | DTO | - | Suffix for DTOs. false for empty string |
enableHibernateCache | true | - | - |
enableSwaggerCodegen | false | - | - |
enableTranslation | true | - | - |
entitySuffix | - | - | Suffix for entities. false for empty string |
jhiPrefix | jhi | - | - |
languages | [en, fr] | Languages available in JHipster | Braces are mandatory |
messageBroker | no | kafka, pulsar, no | - |
nativeLanguage | en | Any language supported by JHipster | - |
packageName | com.mycompany.myapp | - | Sets the packageFolder option |
prodDatabaseType | mysql | mysql, mariadb, mssql, postgresql, oracle, no | - |
reactive | false | - | - |
searchEngine | no | elasticsearch, couchbase, no | - |
serverPort | 8080, 8081 or 9999 | - | Depends on the app type |
serviceDiscoveryType | no | consul, eureka, no | - |
skipClient | false | - | - |
skipServer | false | - | - |
skipUserManagement | false | - | - |
testFrameworks | [] | cypress, protractor, cucumber, gatling | Braces mandatory |
websocket | no | spring-websocket, no | - |
See also
The regular options are available here