Skip to content
This repository has been archived by the owner on Oct 28, 2019. It is now read-only.
Mathieu ABOU-AICHI edited this page Jun 3, 2015 · 51 revisions

This side-project gives you an alternative when creating entities for JHipster: the choice to use a UML editor instead of answering the usual questions.

Note: this project may not ready for production yet, and the information in this page may change during development.

Here's what's covered in this page:

  1. Introduction

  2. Installation

  3. How to use JHipster-UML

3.1. The UML file

    3.1.1. Entities

    3.1.2. Relationships

        3.1.2.1. One-to-One

        3.1.2.2. One-to-Many

        3.1.2.3. Many-to-Many

    3.1.3. A complete example

3.2. Use JHipster-UML

3.3. What's generated

  1. Examples

4.1. Modelio

4.2. UML Designer

  1. Testing

  2. Contributing: issues and enhancements

6.1. Parser modifications

    6.1.1. Adding a parser

        6.1.1.1. Parser implementation

        6.1.1.2. Editor detection

        6.1.1.3. Testing

  1. Annexes

Introduction

JHipster-UML is an alternative to the usual Q&A as it offers you the possibility to use a UML editor to create a diagram that will be parsed by JHipster-UML.

Here is a list of the editors we want to support:

Installation

To install JHipster-uml simply use the command

npm install -g jhipster-uml

How to use it

JHipster-UML is quite easy to use, you need a class diagram exported in XMI and JHipster-UML will parse it to create your entities.

The UML file

The class diagram should modelize the entities of your JHipster application domain, thus you have restrictions, you have to follow the methodology.

Entities

Each entity is represented by a class, its fields are the class' attributes. An attribute must have a JHipster supported type, otherwise it wont work. To have JHipster supported types like “BigDecimal”, “LocalDate”..., you can create a DateType for it. You can look at the tables with all the types supported by JHipster and the validations you can use for each here.

Book Entity

Here is an example of a properly created class for JHipster. We have the attributes publicationDate and price set with the types BigDecimal and LocalDate we created as DataType.

Relationships

The relationship between two entities is represented in the class diagram by an aggregation between two classes.

One-to-One

One-to-One

Here, we have a one-to-one relationship between Customer and Address, with Customer as the owner of the relationship.

One-to-Many

One-to-Many

Here, Author has a one-to-many relationship with Book, and Book has a many-to-one relationship with Author.

Many-to-Many

Many-to-Many

Here, we have a many-to-many relationship between Order and Product, with Order as the owner of the relationship.

A complete example

We use a diagram from the Oracle HR example available here.

Here's a screenshot of such a diagram (from Modelio): HR UML diagram

As you can see, we changed it as to make it a bit more interesting. JHipster can generate entities and associations between them (one-to-one, one-to-many, etc.), and in this example we added every type of association (even the reflexive and the inheritance). JHipster doesn't support inheritance yet (but reflexivity is supported by JHipster, with a warning), but we decided to include it in the example so as to have a solid base to work with.

Use JHipster-uml

Once you have your JHipster application setup and your class diagram in a UML editor, follow those steps:

  • step 1 - export your class diagram to the XMI file format
  • step 2 - in your JHipster application root folder, execute the command

jhipster-uml <your_file.xmi> (sql | mongodb | cassandra)

Note that you don't need to supply the database type (sql, mongodb, or cassandra), as JHipster-UML detects the type for you (from the .yo-rc.json file).

  • step 3 - that's it!

What's generated

After executing JHipster-UML, the .jhipster folder will be created (if it didn't exist before) and filled with the entities present in the XMI file in the JSON format.

Please note that one entity may, at least, not be generated: the User entity. It is actually scaffolded by JHipster when creating a new app (and a warning message is displayed by JHipster-UML).

Next, it's pretty straightforward: just run your app!

Examples

Each editor, except GenMyModel, will be discussed here, so that you know how to get a good XMI file. The reason GenMyModel won't be treated is because of its limited free plan (which limits to 20 the number of objects a model can have), apart from that it's almost the same as UML Designer.

Note 1: In every editor: bi-directionality is not allowed, partly because it can lead to wrong diagrams, and partly because JHipster perfectly manages bi-directionality.

Note 2: JHipster-UML can detect faulty XMI files, it will display the first error it finds, and exists right away (fail-fast behavior).

Modelio

Note for Mac users: Modelio is behaving weirdly on Mac (the GUI), it may be caused by the graphics and window manager on Mac, as it has not been diagnosed on Linux Ubuntu. It works, but the interaction may not be pleasant.

Modelio can be downloaded for free here. Make sure you have Java 8 if you're downloading any of the 3.3+ versions (it won't work otherwise). Once launched, create a project and you'll be seeing this view:

Empty Modelio project

Notice the left panel entitled 'Class Model'. You only need the 'Class', 'Attributes', 'Aggregation', 'Composition' and 'Data Type' objects. You can already guess why you need the first 2. The 'Aggregation' object is used to defined aggregations: B is aggregated to A means that A has 0, 1 or more (n) instances of B. A doesn't create (and destroy) B instances. Composition means that if A is composed of B (0, 1, or n instances), then it creates, manages and destroys B instances.

You can use either of them, the parser will just see the two as associations anyway.

In both situations, cardinalities and association names are important.

Finally, 'Data Types' objects enables you to create custom types (types that are not proposed by Modelio), like BigDecimal, or LocalDate.

In this example, we'll explain how to connect two classes:

Modelio composition example

As you can see, employee has a job (but also can have no job at all). The parser will notice a few things:

  • Two classes (Employee and Job);

  • Two fields (email and title), their type, which class they belong (each class contains its fields). Their visibility is not taken into account;

  • The association linking them and the direction of the association (it matters!);

  • The cardinalities (1 and 0..1) mean that an employee can have a job (0 or 1), and a job isn't shared by two employees (only one, for this example's sake);

  • There is one injected field: job, in employee.

This association is called a one-to-one. Go back a few sections to see the other types of associations.

Finally, once your diagram is finished, you just have to export it.

Export to XMI Modelio

Check the Model perspective, once you locate your project, get down one level and right click the last element (you lower-cased project's name), XMI, Export XMI. A window should pop up, select the output path, select the compatibility to OMG UML2.4.1, leave the extension to XMI and you're ready to go.

UML Designer

UML Designer can be downloaded here. It works the same way as Eclipse. To create an empty project, just click on File -> New -> Modeling Project. Enter the name, and validate. If no file.uml is created, right-click on your project, and New -> Other -> UML Designer -> UML Model, and enter any name you want.

You'll then be presented by a view like this one:

UML Designer, dashboard

Double-click on 'Class diagram' under 'Design' category. You can now see on the right the 'Palette'. You only need these objects: 'Class', 'PrimitiveType', 'DataType' (both under 'Enumeration'), 'Composition' and 'Aggregation' (both under 'Association').

As mentioned with Modelio, our parser system doesn't care if you use an aggregation or a composition. You can use whatever you want.

With UML Designer, you can create custom types by either using a DataType or a PrimitiveType (the parser recognizes both).

Here is an example using this editor:

Employee and Job with UML Designer

To create attributes, just double-click on the class, and add your attribute. You can import types by right-clicking somewhere on the diagram (in the white-space), then import Primitive Types, then select UML and Java. This will spare you the chore of creating types manually (with DataTypes or PrimitiveTypes).

One of the nice things UML Designer provides is that you don't need to export to XMI, just go to your workspace, and you'll see that the saved project is already in the right format, so that's pretty cool.

Testing JHipster-UML

The tests are available in the test folder and can be run via npm test. We use Mocha for testing (along with expect, chai, and other niceties).

Contributing: issues and enhancements

Because our tool isn't perfect (yet), you may notice some irregularities. Github provides a pretty nice issue tracker so that everyone can post about an issue. We follow the same guidelines as JHipster, with a few additions:

  • Bugs found internally (by the JHipster-UML team) will not be posted in the issue tracker, except for bugs regarding the supported UML editors.
  • The same goes for enhancements.

Parser modifications

The 1.0.0 release will bring a new parser system making any change (parser creation, update, deletion) ultra-easy.

Adding a parser

Parser implementation

Adding a parser is quite easy. If your a Java dev, you're probably quite familiar with OOP principles (we hope so anyway). When developing Jhipster-UML, we thought of its architecture as we'd normally do in Java.

You just have to "extend" our abstract parser (AbstractParser), or implement our interface (Parser) to add your concrete implementation of a parser.

You should notice that some methods of the Parser interface throw an UnimplementedOperationException. This idea is obviously taken from Java, and you can implement this methods in your concrete parser.

Just like in Java, you can override any method you want, and create your own. You're not limited (except if you want to overload).

The AbstractParser class provides some fields, a default constructor and some methods so that you don't have to create or implement them later.

Obviously, you should implement each of these methods (or override the #parse or #findElements methods).

The getters are not mandatory, but serve as a way of getting some important fields and provide a way to modify them before sending those fields.

Editor detection

When you're done creating your shiny new parser, you should add it to the "list" of available editors:

  • Require it first just like here;

  • Make it available just like here;

  • Add it to the list just like here.

However, a few guidelines must be respected:

  • Your parser's name must be <editor_parser>;

  • The editor's JS file must not be upper-cased, and must not contain any whitespace, (Modelio -> modelio_parser.js, UML Designer -> umldesigner_parser.js);

  • The editor's class name must be capitalized (Modelio -> ModelioParser, UML Designer -> UMLDesignerParser).

You also must add your editor to the EditorDetector, so that the XMI's editor can be detected. See this example to know more about it.

Testing

Finally, the next thing you'll need to do before committing your super parser is testing it. Because we believe in testing, but really like good testing (with BDD), our tests are done with Mocha and chai. If you don't know what it's all about yet, we recommend you visit the ChaiJS page, and see one of our test file to get acquainted with it.

You should probably wonder what form of testing you should use. The answer is pretty simple: it's up to you! Whether it's should, or expect (à la RSpec), we don't enforce any special rule here.

We just want you to test everything that is 'test-worthy':

  • The interface's methods (the public methods);

  • You're not obliged to test the other methods (private ones, because they are supposed to be safe and ever-changing in the long term), but as visibility is not implemented in JS (to our knowledge), you may want to test them (it's up to you).

The general guidelines for names and files:

  • Your test file's name should respect the same rules as previously mentioned. For instance, if your parser's name is "Modelio", then your test file should be modelio_parser_test.js.

  • The same goes for XMI files used for testing. If your parser's name is UMLDesigner, then one of your test XMI file's name can be umldesigner_parser_problem_test.[...] (the file extension is not static).

Annexes

Here is the type table (from types.js):

SQL MongoDB Cassandra Validations
String String String required, minlength, maxlength, pattern
Integer Integer Integer required, minlength, maxlength
Long Long Long required, minlength, maxlength
BigDecimal BigDecimal BigDecimal required, minlength, maxlength
Boolean Boolean Boolean
LocalDate LocalDate required
Date
DateTime DateTime required
UUID required
TimeUUID required
Clone this wiki locally