JHipster Domain Language (JDL)
The JDL is a JHipster specific domain language where we have added the possibility to describe all your entities and their relationships in a single file (or more than one) with a simple and user-friendly syntax.
You can use our online JDL-Studio IDE to create JDL and its UML visualization. You can create and export or share URL of your JDL as well.
You can also generate entities from a JDL file using the import-jdl sub generator. Simply run yo jhipster:import-jdl yourJdlFilePath.jh
from the root of the generated JHipster application. Or by using JHipster UML.
- this can be used as a replacement to using the entity sub-generator. The idea is that it is much easier to manage relationships using a visual tool than with the classical Yeoman questions and answers.
The JDL project is available on GitHub, it is an Open Source project like JHipster (Apache 2.0 licence). This can be used a node library to do JDL parsing. If you like this project, don’t forget to give us a star on GitHub!
Here’s what’s covered on this page:
- JDL Sample
- How to use it
- The language
3.1 Entity Declaration
3.2 Relationship Declaration
3.3 Enumerations
3.4 Blobs
3.5 Option declaration
3.6 Microservice-related options - Commenting
- All the relationships
- Annexes
- Issues and bugs
JDL Sample
The Oracle example has been translated into JDL, and is available here. The same is loaded by default in JDL-Studio as well.
How to use it
You can use it by:
- simply creating a file with the extension ‘.jh’ or ‘.jdl’,
- declare your entities and relationships or create and download the file with JDL-Studio,
- in your JHipster application’s root folder, simply run
yo jhipster:import-jdl yourfile.jh
, - you can also use JDL files in JHipster UML with
jhipster-uml my_file.jdl
.
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 to JHipster UML so that you don’t manually
concatenate all the files into one, you just have to run jhipster-uml my_file1.jh my_file2.jh
.
If you want to use it in your project, you can add do so by doing npm install jhipster-domain-language --save
to install it locally, and save it in your package.json
file.
The language
We tried to keep the syntax as friendly as we can for developers. You can do three things with it:
- Declare entities with their attributes,
- Declare the relationships between them,
- And declare some JHipster specific options.
Entity declaration
The entity declaration is done as follows:
entity <entity name> {
<field name> <type> [<validation>*]
}
<entity name>
is the name of the entity,<field name>
the name of one field of the entity,<type>
the JHipster supported type of the field,- and as an option
<validation>
the validations for the field.
The possible types and validations are those described here, if the validation requires a value, simply add (<value>)
right after the name of the validation.
Here’s an example of a JDL code:
entity A
entity B
entity C {}
entity D {
name String required,
address String required maxlength(100),
age Integer required min(18)
}
Because the JDL was made to be simple to use and read, if your entity is empty (no field), you can just declare an entity with entity A
or entity A {}
.
Note that JHipster adds a default id
field so that you don’t have to worry about it.
Relationship declaration
The relationships declaration is done as follows:
relationship (OneToMany | ManyToOne | OneToOne | ManyToMany) {
<from entity>[{<relationship name>}] to <to entity>[{<relationship name>}]
}
(OneToMany | ManyToOne| OneToOne | ManyToMany)
is the type of your relationship,<from entity>
is the name of the entity owner of the relationship: the source,<to entity>
is the name of the entity where the relationship goes to: the destination,<relationship name>
is the name of the field having the other end as type.
Here’s a simple example:
A Book has one Author, an Author has several Books.
entity Book
entity Author
relationship OneToMany {
Author{book} to Book{writer(name)}
}
Of course, in real cases, you’d have a lot of relationships and always writing the same three lines could be tedious. That’s why you can declare something like:
entity A
entity B
entity C
entity D
relationship OneToOne {
A{b} to B{a},
B{c} to C
}
relationship ManyToMany {
A{d} to D{a},
C{d} to D{c}
}
By default, the joining is done by the id
field… But if you want the joining to be done by another field, then you can do things like:
entity A {
name String required
}
entity B
relationship OneToOne {
A{b} to B{a(name)}
}
Enumerations
To make Enums with JDL just do as follows:
-
Declare an Enum where you want in the file:
enum Language { FRENCH, ENGLISH, SPANISH }
-
In an entity, add fields with the Enum as a type:
entity Book { title String required, description String, language Language }
Blob (byte[])
JHipster gives a great choice as one can choose between an image type or any binary type. JDL lets you do the same: just create a custom type (see DataType) with the editor, name it according to these conventions:
AnyBlob
or justBlob
to create a field of the “any” binary type;ImageBlob
to create a field meant to be an image.
And you can create as many DataTypes as you like.
Option declaration
In JHipster, you can specify options for your entities such as pagination or DTO. You can do the same with the JDL:
entity A {
name String required
}
entity B {}
entity C {}
dto A, B with mapstruct
paginate A, C with infinite-scroll
paginate B with pager
service A with serviceClass
service C with serviceImpl
The keywords dto
, paginate
, service
and with
were added to the grammar to support these changes.
If a wrong option is specified, JDL will inform you of that with a nice, red message and will just ignore it so as not to corrupt JHipster’s JSON files.
Service option
No services specified will create a resource class which will call the repository interface directly. This is the default and simplest option, see A. Service with serviceClass (see B) will make the resource call the service class which will call the repository interface. Service with serviceImpl (see C) will make a service interface which will be used by the resource class. The interface is implemented by an impl class which will call the repository interface.
Use no service if not sure it’s the simplest option and good for CRUD. Use service with a Class if you will have a lot of business logic which will use multple repository’s making it ideal for a service class. Jhipster’s are not a fan of unnecessary Interfaces but if you like them go for service with impl.
entity A {}
entity B {}
entity C {}
// no service for A
service B with serviceClass
service C with serviceImpl
JDL also supports mass-option setting. it is possible to do:
entity A
entity B
...
entity Z
dto * with mapstruct
service all with serviceImpl
paginate C, with pager
Note that *
and all
are equivalent.
Latest version introduces exclusions (which is quite a powerful option when setting options for every entity):
entity A
entity B
...
entity Z
dto * with mapstruct except A
service all with serviceImpl except A, B, C
paginate C, with pager
With JHipster, you can also tell whether you don’t want any client code, or server code. Even if you want to add a suffix to Angular-related files, you can do that in JHipster. In your JDL file, simply add these lines to do the same:
entity A
entity B
entity C
skipClient for A
skipServer for B
angularSuffix * with mySuperEntities
Finally, table names can also be specified (the entity’s name will be used by default):
entity A // A is the table's name here
entity B (the_best_entity) // the_best_entity is the table's name
Microservice-related options
As of JHipster v3, microservices can be created. You can specify some options to generate your entities in the JDL: the microservice’s name and the search engine.
Here is how you can specify your microservice’s name (the JHipster app’s name):
entity A
entity B
entity C
microservice * with mysuperjhipsterapp except C
microservice C with myotherjhipsterapp
search * with ElasticSearch except C
The first option is used to tell JHipster that you want your microservice to deal with your entities, whereas the second specifies how and if you want your entities searched.
Commenting & Javadoc
It is possible to add Javadoc & comments to JDL files.
Just like in Java, this example demonstrates how to add Javadoc comments:
/**
* Class comments.
* @author The JHipster team.
*/
entity MyEntity { // another form of comment
/** A required attribute */
myField String required,
mySecondField String // another form of comment
}
/**
* Second entity.
*/
entity MySecondEntity {}
relationship OneToMany {
/** This is possible too! */
MyEntity{mySecondEntity}
to
/**
* And this too!
*/
MySecondEntity{myEntity}
}
These comments will later be added as Javadoc comments by JHipster.
JDL possesses its own kind of comment:
// an ignored comment
/** not an ignored comment */
Therefore, anything that starts with //
is considered an internal comment for JDL, and will not be counted as Javadoc.
All the relationships
Explanation on how to create relationships with JDL.
One-to-One
A bidirectional relationship where the Car has a Driver, and the Driver has a Car.
entity Driver {}
entity Car {}
relationship OneToOne {
Car{driver} to Driver{car}
}
A Unidirectional example where a Citizen has a Passport, but the Passport has no access to sole its owner.
entity Citizen {}
entity Passport {}
relationship OneToOne {
Citizen{passport} to Passport
}
One-to-Many
A bidirectional relationship where the Owner has none, one or more Car objects, and the Car knows its owner.
entity Owner {}
entity Car {}
relationship OneToMany {
Owner{car} to Car{owner}
}
Unidirectional versions for this relationship are not supported by JHipster, but it would look like this:
entity Owner {}
entity Car {}
relationship OneToMany {
Owner{car} to Car
}
Many-to-One
The reciprocal version of One-to-Many relationships is the same as previously. The unidirectional version where the Car knows its owners:
entity Owner {}
entity Car {}
relationship ManyToOne {
Car{owner} to Owner
}
Many-to-Many
Finally, in this example we have the Car that knows of its drivers, and the Driver object can access its cars.
entity Driver {}
entity Car {}
relationship ManyToMany {
Car{driver} to Driver{car}
}
Please note that the owning side of the relationship has to be on the left side
Annexes
Here is the types supported by JDL:
SQL | MongoDB | Cassandra | Validations |
---|---|---|---|
String | String | String | required, minlength, maxlength, pattern |
Integer | Integer | Integer | required, min, max |
Long | Long | Long | required, min, max |
BigDecimal | BigDecimal | BigDecimal | required, min, max |
Float | Float | Float | required, min, max |
Double | Double | Double | required, min, max |
Enum | Enum | required | |
Boolean | Boolean | Boolean | required |
LocalDate | LocalDate | required | |
Date | required | ||
ZonedDateTime | ZonedDateTime | required | |
UUID | required | ||
Blob | Blob | required, minbytes, maxbytes | |
AnyBlob | AnyBlob | required, minbytes, maxbytes | |
ImageBlob | ImageBlob | required, minbytes, maxbytes |
Issues and bugs
JDL is available on GitHub, and follows the same contributing guidelines as JHipster.
Please use our project for submitting issues and Pull Requests concerning the library itself.
When submitting anything, you must be as precise as possible:
- One posted issue must only have one problem (or one demand/question);
- Pull requests are welcome, but the commits must be ‘atomic’ to really be understandable.