JHipster Domain Language (JDL) - Getting Started
In this page, you'll learn about the JDL and how to create applications and everything around them.
Generating content
Using files
You can use JDL files to generate entities:
- Create a file with the extension '.jh' or '.jdl',
- Declare your applications, deployments, entities and relationships or create and download the file with JDL-Studio or JHipster IDE,
- If you are creating only entities then run
jhipster jdl my_file.jdl
in your JHipster application's root folder. - If you are creating applications then run
jhipster jdl my_file.jdl
in a folder.
and Voilà, you are done!
If you work in a team, perhaps you would like to have multiple files instead of one. We added this option so that you don't manually concatenate all the files into one, you have to run:
jhipster jdl my_file1.jdl my_file2.jdl
If you do not want to regenerate your entities while importing a JDL, you can use the --json-only
flag to skip the
entity creation part and create only the json files in .jhipster
folder.
jhipster jdl ./my-jdl-file.jdl --json-only
By default jdl
regenerates only entities that have changed, if you want all your entities to be regenerated
then pass in the --force
flag.
Please note that this will overwrite all your local changes to the entity files:
jhipster jdl ./my-jdl-file.jdl --force
If you want to use it in your project, you can add do so by doing:
npm install jhipster-core --save
to install it locally, and save it in your package.json
file.
Using an inline JDL
The other way to generate content is to pass a JDL code in your CLI, this way:
jhipster jdl --inline "application { config { baseName jhipster, applicationType microservice } }"
.
This way of generating content is especially useful when generating entities.
For now, we'll start with small JDL content to get to know the various ways to generate content. The focus here is on the generation of code. Explanation about the syntax is made in other sections.
Here's the basic content we'll use:
application {
config {
baseName jhipster
applicationType microservice
}
}
This is a very basic microservice application named "jhipster", and we'll see the various ways to generate a application from this sample.
You'll see that, with this little sample, you've managed to create an application from scratch.
Using a remote JDL file
You can also use an URL with the jdl
command. Just pass the URL instead of the file name as below
jhipster jdl https://my-site.com/my.jdl
jhipster jdl https://gist.githubusercontent.com/user/id/raw/id/myapp.jdl
You can also fetch a remote JDL file from our JDL sample repository by just specifying the filename and we will automatically resolve the URL
jhipster jdl default.jdl
Generating applications
As we've seen in the previous example, generating applications is quite straightforward, let's take the previous example and add more things to it:
application {
config {
baseName jhipster
applicationType microservice
serverPort 4242
buildTool gradle
}
}
Let's break it down:
application
is the keyword to say you want to declare an applicationconfig
to say that you want to specify the configuration- we'll later see that you can also declare entities in applications
baseName
,applicationType
, etc. are keywords to tweak the application
This is how you create an application using the JDL. To see all supported application options, head to this page.
Generating entities
Generating entities is a bit less straightforward. You can also go to the dedicated entity page to know more about what you can do with entities.
Generating a basic entity
entity A
This entity doesn't have fields, or even an explicit table name (even though JHipster sets one for you from the entity's name). This is the simplest way possible to declare an entity.
Note that this form is equivalent to:
entity A(a) {}
We've added a table name and braces. By default, JHipster generates a table name based on the specified entity name.
The braces are needed when declaring fields.
Adding comments
This is the way to add a comment to an entity:
/**
* This is a simple entity
*/
entity A
If the backend is in Java, this will add a Javadoc comment.
Entities in applications
To only generate some entities in an application, the entities
keyword can be used:
application {
config {}
entities A, B
}
application {
config {}
entities C
}
entity A
entity B
entity C
This is especially useful in microservice architectures.
Generating fields
Fields are declared in entities, by specifying a body to an entity:
entity MyEntity {
name String
closed Boolean
}
There are more than these two types, check them out in the entities & fields page.
Adding comments and validations
The same way we've added comments to entities, we can add comments to fields:
entity MyEntity {
/** My field */
name String required minlength(2) maxlength(50)
}
Validations depend on the field type, and are also detailed in the entities & fields page.
Enumerations
Enumerations are types with fixed values:
enum Type {
A,
B(b)
}
entity E {
name Type
}
Notice how enumeration's values are optional.
They only have one validation: required
.
You can check the dedicated enum page for details about enums.
Adding relationships
Relationships between entities are also available and are declared with the relationship
keyword.
entity A
entity B
relationship OneToOne {
A{a} to B{b}
}
Here's what we can see:
OneToOne
is the relationship type- there are also
OneToMany
,ManyToMany
andManyToOne
- there are also
- we declare the source and the destination of the relationship (from
A
toB
) - we also declare the injected fields in each entity (
a
inB
, andb
inA
)- this means the relationship is bidirectional
To know more about relationships, you can head to the dedicated page.
Unidirectional or bidirectional relationships?
Depending on how you design your models, you may want unidirectional relationships instead of bidirectional ones. This is achieved by not specifying an injected field like this:
relationship OneToOne {
A{a} to B
}
You can also not specify them, and at least one will be injected by default (the source)
relationship OneToOne {
A to B
}
Relationship comments & validations
Relationships also have comments, validations (only one: required
):
relationship OneToOne {
A{a} to B{b required}
}
In this example we can see:
required
to specify if a side of the relationship is required- instead of having 0..1, this One to One relationship requires 1 side not to be nil
To know more about relationships, you can go to the dedicated relationship page
Options
The same way you can apply options to entities in the CLI, you can also do that in the JDL:
entity A
entity B
entity C
readOnly A
dto * with mapstruct
service * with serviceImpl
paginate A, B with pager
There a some interesting things happening here:
dto
,paginate
andservice
are binary options as they need an entity list and a valuewith
is used to specify the option value- note the
*
which means the option is to be applied to all the entities
readOnly
is an unary option, that means that such options only take an entity list
There are more than one way to declare an entity list:
- you can enumerate them one by one:
A, B, C
- you can select all of them:
*
orall
- you can have exceptions to exclude entities:
service * with serviceImpl except A, B
- you can have exceptions to exclude entities:
Annotations
Annotations are another way to declare options, let's rewrite the previous example:
@readOnly
@dto(mapstruct)
@service(serviceImpl)
@paginate(pager)
entity A
@dto(mapstruct)
@service(serviceImpl)
@paginate(pager)
entity B
@dto(mapstruct)
@service(serviceImpl)
entity C
Similar to Java, or Typescript, annotations are "decorators", options to entities.
This example and the previous are equivalent as they can be used to generate the same code.
To know more about options, you can go to the option page
Deployments
Finally, deployments can also be generated from a JDL file using the deployment
keyword, compatible with JHipster
v5.7 and above:
deployment {
deploymentType docker-compose
appsFolders [foo, bar]
dockerRepositoryName "yourDockerLoginName"
}
To import one or several deployments, you need not be in a JHipster application folder.
Deployments are described in their own page.
A JHipster deployment has a config with default values for all other properties and using the previous syntax will ensure your deployment will use the default values (as if you didn't make any specific choice). The resulting deployment will have:
- deploymentType:
docker-compose
- appsFolders:
foo, bar
- dockerRepositoryName:
yourDockerLoginName
- serviceDiscoveryType:
consul
- gatewayType:
SpringCloudGateway
- directoryPath:
../
- etc.
Now, if you want some custom options:
deployment {
deploymentType kubernetes
appsFolders [store, invoice, notification, product]
dockerRepositoryName "yourDockerLoginName"
serviceDiscoveryType no
istio autoInjection
kubernetesServiceType Ingress
kubernetesNamespace jhipster
ingressDomain "jhipster.192.168.99.100.nip.io"
}
Those options are only a sample of what's available in the JDL. The complete list of options is available in the deployment page, here.
Constants
The JDL supports numerical constants. Here is an example:
DEFAULT_MIN_LENGTH = 1
DEFAULT_MAX_LENGTH = 42
DEFAULT_MIN_BYTES = 20
DEFAULT_MAX_BYTES = 40
DEFAULT_MIN = 0
DEFAULT_MAX = 41
entity A {
name String minlength(DEFAULT_MIN_LENGTH) maxlength(DEFAULT_MAX_LENGTH)
content TextBlob required
count Integer min(DEFAULT_MIN) max(DEFAULT_MAX)
}
Exporting to a JDL file
If you already have entities in your application and wish to have a JDL file, don't worry! You don't have to write it from scratch as there's a sub-generator that does that for you.
Run jhipster export-jdl <FILE_NAME>
in your app's root folder and you'll have all your applications, entities,
relationships and options exporting in a single JDL file.
Note: you can also not provide a file name to the sub-generator, the exported JDL file will be named after the app's
base name. For instance, if your application's named 'mySuperApp' then your JDL file will be mySuperApp.jdl
.