J Hipster Tutorial
J Hipster Tutorial
4. Install JHipster:
npm install -g generator-jhipster
Creating a repository
To work with JHipster, we highly recommend you to use GitHub. If you are unfamiliar with how
versioning tools work, please head to the documentations.
Start by creating a folder that will contain your future application, in our case we will create an
application named BugTrackerJHipster so you can name your folder so.
mkdir ~/BugTrackerJHipster
If you're running these tutorials locally, we recommend you to use your usual workspace (and
therefore not use the absolute path to create and access your application folder).
If you're using Google Cloud Shell, please do set up your git like so :
git config --global user.name "John Doe";
Click on the Next button at the bottom right of this window to know how to generate an application
1. May JHipster anonymously report usage statistics to improve the tool over time?
This is a feature to help us track statistics so we can know on which technologies we have to focus
on developping. We highly recommend you to choose yes on this first question. Note that this
question will only be asked once.
• Microservice gateway: in a microservices architecture, this is an edge server that routes and
secures requests.
• JHipster UAA server: in a microservices architecture, this is an OAuth2 authentication
server that secures microservices. Refer to the Jhipster UAA documentation for more
information.
5. Do you want to use the JHipster Registry to configure, monitor and scale your application?
The JHipster registry is an Open Source tool used to manage your application at runtime. It is
required when using a microservices architecture (this is why this question is only asked when
generating a monolith, like in our case). Choose Yes at this question.
• Cassandra
• Couchbase
• MariaDB
• PostgreSQL
• Oracle (Please follow our documentation to use the Oracle proprietary driver)
• No cache, but be aware that when using a SQL database, this will disable the Hibernate 2nd
level cache.
Let's take ehcache for our BugTracker.
Also, this can have a very positive impact on your application's performance. Hence, it is a
recommended option.
11.Would you like to use Maven or Gradle for building the backend?
You can build your generated Java application with either Maven or Gradle. Maven is more stable
and more mature. Gradle is more flexible, easier to extend and more hype.
For this one, let's go with Maven.
• React
18.Besides JUnit and Jest, which testing frameworks would you like to use?
By default, JHipster provide Java Unit/integration testing (using Spring's JUnit support) and
JavaScript unit testing (using Jest). As an option, you can also add support for:
• Performance tests using Gatling
Later in the tutorial, we will learn how to test our application. For now, press A to select all of them
and press Enter.
19.Would you like to install other generators from the JHipster Marketplace?
The JHipster Marketplace is where you can install additional modules, written by third-party
developers, to add non-official features to your project.
We won't be using any of these in this tutorial, hence we will choose No.
JHipster should start generating the files: here are some tips in the meanwhile.
You can also use the Yeoman command-line options, like --force to automatically overwrite
existing files. So if you want to regenerate your whole application, including its entities, you can
run
jhipster --force --with-entities
02. Continuous Integration
Setting up Continuous Integration (CI) for a JHipster application is harder than for a classic typical
Spring MVC application because of the complexity associated with maintaining a build composed
of 2 software stacks:
• the Java back-end code with Maven or Gradle
Each stack comes with its own dependency management (Maven artifacts, NPM packages) with
potential conflicts to solve.
JHipster should support the following CI systems out of the box:
• Jenkins (Jenkins 1 and Jenkins 2)
• Travis
• GitLab CI
• Azure Pipelines
A more detailed guide for continuous integration is available on the official jhipster website.
In this tutorial we will focus on Travis CI.
• Azure Pipelines
• GitLab CI
• Travis CI
GitHub
In this section, we will show you how to configure a remote repository with git on GitHub.
1. Create an account or signin on GitHub
2. Create a new public repository named BugTrackerJHipster
Now, go on the BugTracker folder:
cd ~/BugTrackerJHipster
Now commit the file generated with the sub-generator for continuous integration:
git add .git commit -m "initial commit"
You can now push all the changes in the remote repository with the following command:
git push --set-upstream origin master
Travis CI
Travis CI is a service to build and test software hosted on GitHub. When activated on a particular
repository, any push or pull request will trigger the build and tests using the configuration file. This
is what we are going to do for the BugTracker project.
1. Sign in to Travis CI website with your GitHub account
2. Go to your repository list
3. Activate Travis CI for the BugTrackerJHipster repository
Travis CI is now installed on your BugTracker repository. You can commit and push a change to see
Travis build and run the tests.
03. JHipster App
Running the application
You have now a fully functional application built with JHipster. This tutorial will show you the
features offered by JHipster.
Once the application is generated, you can launch it with the following Maven command:
./mvnw
or on Windows :
mvnw.cmd
The application will be accessible locally on the port 8080. Luckily, Cloud Shell provides a web
preview functionality that allows you to run web applications on the virtual machine instance. Click
on icon and select the port 8080. You can check all the common ports available here.
File organization
Let's take a look at the project generated by JHipster. Below is a short description of its content.
Back-end
• The java code is located in src/main/java
Front-end
• The front-end is located in src/main/webapp
Security
To use Spring Security in a Single Web Page Application, like those generated by JHipster, you
need Ajax login/logout/error views. JHipster has already configured Spring Security in order to use
those views correctly.
By default, JHipster comes with 4 different users:
• "system": for automatic processes, mainly used for our audit logs
• "user": a basic user with the authorization "ROLE_USER". His default password is "admin"
• "admin": an admin user with the authorizations "ROLE_USER" and "ROLE_ADMIN". His
default password is "admin"
The two authorizations “ROLE_USER” and “ROLE_ADMIN” provide the same access to the
entities which means that a “user” is authorized to perform the same CRUD operations as an
“admin”. This behavior can be an issue when the application runs in production because a “user”
can for example delete any entities. See more here.
Metrics dashboard
The metrics dashboard uses Micrometer to give a detailed view of the application performance. It
gives metrics on:
• the JVM
• HTTP requests
• cache usage
By clicking on the Expand button next to the JVM thread metrics you will get a stacktrace of the
running application, which is very useful to find out blocked threads.
• A JPA Entity
• A Spring MVC REST Controller, which has the basic CRUD operations
• An HTML view
If you have several entities, you will likely want to have relationships between them. For this, you
will need:
• A database foreign key
Thankfully, the "entity" sub-generator will help you create all the required files, and provide a
CRUD front-end for each entity (see Angular project structure).
JDL Studio
You can use a graphical tool to create your entities. In this case, we advise you to use JDL Studio,
our online tool to create entities and relationships using our domain-specific language JDL.
After clicking on the first link, the JDL Studio opens on a window. You can now start writing your
first entity.
The entity declaration is done as follows:
entity <entity name> {
<field name> <type> [<validation> *]
}
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.
Regexes are a bit special as they are used like this (from v1.3.6):
entity A {
myString String required minlength(1) maxlength(42) pattern(/[A-Z]+/)
}
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 instead of entity A {}.
Note that JHipster adds a default id field so that you needn't worry about it.
Label
• has a label of type String that is at least 3 characters long
Ticket
• has a title of type String that is required
If you've declared them properly, you should see the graphical tool updating itself in real time while
you are done creating your entities. To know more about entity fields, click on the Next button
down there.
• You cannot use MySQL reserved keywords (as your database schema update will fail)
JHipster supports many field types. This support depends on your database backend, so we use Java
types to describe them; a Java String will be stored differently in Oracle or Cassandra, and it is
one of JHipster's strengths to generate database access code for you.
• String: A Java String. Its default size depends on the underlying backend (if you use JPA,
it's 255 by default), but you can change it using the validation rules (putting a max size of
1024, for example).
• Integer: A Java Integer.
• Enumeration: A Java Enumeration object. When this type is selected, the sub-generator
will ask you what values you want in your enumeration and it will create a specific enum
class to store them.
• Blob: A Blob object, used to store some binary data. When this type is selected, the sub-
generator will ask you if you want to store generic binary data, an image object, or a
CLOB(long text). Images will be handled specifically on the Angular side, so they can be
displayed to the end user.
Validation
Validation can be set up for each field. Depending on the field type, different validation options will
be available.
Validation will be automatically generated on:
• the HTML views, using the Angular or React validation mechanism
Bean validation will then be used to automatically validate domain objects when they are used in:
• Spring MVC/REST controllers (using the @Valid annotation)
Validation information will also be used to generate more precise database column metadata:
• Required fields will be marked non-nullable
• Fields which have a maximum length will have the same column length
Relationships
Now that you have created your initial entities, you will need to declare your relationships. Entity
relationships are only available for SQL databases. It is a fairly complex subject, which has its own
documentation page: Managing relationships. The relationships declaration is done as follows:
relationship (OneToMany | ManyToOne | OneToOne | ManyToMany) {
<from entity>[{<relationship name>[(<display field>)]}] to <to
entity>[{<relationship name>[(<display field>)]}]
}
• <to entity> is the name of the entity where the relationship goes: the destination
• <relationship name> is the name of the field having the other end as type
• <display field> is the name of the field that should show up in select boxes (default:
id)
relationship ManyToOne {
Ticket{project(name)} to Project,
Ticket{assignedTo(login)} to User{ticket}
}
• A ticket is attached to a single project but a project can be attached to many tickets
• A ticket is assigned to a single user, referred to as his login, but a user can be attached to
many tickets
Finally, let's add a pagination for our tickets, add this to your file:
paginate Ticket with pagination
Please note that pagination is not available if you created your application with Cassandra. Of
course, this will be added in a future release.
Pagination uses the Link Header, as in the GitHub API, JHipster provides a custom implementation
of this specification on both the server (Spring MVC REST) and the client (Angular in our case)
sides.
If you look in the res folder, you will see a file named jhipster-jdl.jh that is the .jh file that should
be exported when you click on the top right button "Download text file of this JDL". If you open it,
you will see that it is what you've written before.
Launch the application (for example with mvn), log in and click on "Entities" in the menu. You
should see the entities you have created with the JDL Studio.
05. Updating your back-end
Ordered tickets
Right now, our tickets are not ordered, unless you click on the column header to sort them manually.
We want to change that as we want to have the most urgent tickets on top of the list.
First, head to the TicketRepository.java file in the back end part of your application and add the
following method:
Page<Ticket> findAllByOrderByDueDateAsc(Pageable pageable);
Spring Data JPA will deduce its associated query by parsing the method name, so that you do not
have to implement anything else.
Now, head to the file TicketResource.java and change the function getAllTickets to use our
new function instead.
@GetMapping("/tickets")
public ResponseEntity<List<Ticket>> getAllTickets(Pageable pageable,
@RequestParam MultiValueMap<String, String> queryParams,
UriComponentsBuilder uriBuilder, @RequestParam(required = false,
defaultValue = "false") boolean eagerload) {
log.debug("REST request to get a page of Tickets");
Page<Ticket> page;
if (eagerload) {
page = ticketRepository.findAllWithEagerRelationships(pageable);
} else {
//page = ticketRepository.findAll(pageable);
page = ticketRepository.findAllByOrderByDueDateAsc(pageable);
}
HttpHeaders headers =
PaginationUtil.generatePaginationHttpHeaders(uriBuilder.queryParams(queryP
arams), page);
return ResponseEntity.ok().headers(headers).body(page.getContent());
}
If you start your server again, you should see that the tickets are automatically ordered by the due
date.
Assigned tickets
Let's now add up a new API to our server: you want to show your end users only their assigned
tickets. For that, let's start by creating a new mapping, add this to the file TicketResource.java:
@GetMapping("/tickets/self")
public ResponseEntity<List<Ticket>> getAllSelfTickets(@ApiParam Pageable
pageable, @RequestParam(required = false, defaultValue = "false") boolean
eagerload){
log.debug("REST request to get a page of user's Tickets");
Page<Ticket> page;
if (eagerload) {
page = ticketRepository.findAllWithEagerRelationships(pageable);
} else {
page = new
PageImpl<>(ticketRepository.findByAssignedToIsCurrentUser());
}
HttpHeaders headers =
PaginationUtil.generatePaginationHttpHeaders(uriBuilder.queryParams(queryP
arams), page);
return ResponseEntity.ok().headers(headers).body(page.getContent());
}
If you check the file TicketRepository.java, you will see that the method has been already
implemented, that is why this time you don't need to modify anything.
With the previous code added, we've supplemented our API with a new mapping: to see if the
endpoint works as intended, start up your application and log in as an admin.
Click on the Administration menu and then API. Show the Ticket Resource API and you should
see that a GET /api/tickets/self has been added on the list.
Show the hidden contents by clicking on it and click on the Try it out! button. You will see that the
server works fine and answers with a JSON.
If you're using the google cloud shell to edit files, remember to add the import:
import org.springframework.security.access.annotation.Secured;
import com.mycompany.bugtracker.security.AuthoritiesConstants;
import io.swagger.annotations.ApiParam;
import org.springframework.data.domain.PageImpl;
Tooling
Angular is using TypeScript instead of JavaScript, and as a result a specific tooling is necessary to
work efficiently with it. Our development workflow for an Angular application is as below:
1. When you generate an application, the files are created and then the command npm install
is executed.
2. Once the previous command is completed, the script postinstall in package.json is executed
triggering the task webpack:build.
3. Now you should have all the files generated and compiled into the folder www inside the
target or build folder based on the build tool (Maven or Gradle) selected.
4. Now run ./mvnw to launch the application server and it should be available at
localhost:8080. This will also serve the client side code compiled from the above steps.
./mvnw
or on Windows :
mvnw.cmd
5. Now run npm start in a new terminal to launch the Webpack dev-server with BrowserSync.
This will automatically compile your TypeScript code and reload your browser on change.
npm start
6. Click on and watch the port 9000. Now any change on your front end will be reflected
here.
If you start making changes to the client side code without having npm start running, nothing will
be reflected as the changes are not compiled. So you need to either run npm run webpack:build
manually after changes or have npm start running.
More at the JHipster website.
Editing the front end (Angular)
In this guide, we will make our own Angular component in order to display the logged user's
tickets.
Tooling
Angular is using TypeScript instead of JavaScript, and as a result a specific tooling is necessary to
work efficiently with it. Our development workflow for an Angular application is as below:
1. When you generate an application, the files are created and then the command npm install
is executed.
2. Once the previous command is completed, the script postinstall in package.json is executed
triggering the task webpack:build.
3. Now you should have all the files generated and compiled into the folder www inside the
target or build folder based on the build tool (Maven or Gradle) selected.
4. Now run ./mvnw to launch the application server and it should be available at
localhost:8080. This will also serve the client side code compiled from the above steps.
./mvnw
or on Windows :
mvnw.cmd
5. Now run npm start in a new terminal to launch the Webpack dev-server with BrowserSync.
This will automatically compile your TypeScript code and reload your browser on change.
npm start
6. Click on and watch the port 9000. Now any change on your front end will be reflected
here.
If you start making changes to the client side code without having npm start running, nothing will
be reflected as the changes are not compiled. So you need to either run npm run webpack:build
manually after changes or have npm start running.
More at the JHipster website.
Calling queryMyTickets() will send a HTTP request to the Rest Controller and will return all
the tickets associated to the connected user.
jhiTranslate="bugTrackerJHipsterApp.ticket.project">Project</span>
<fa-icon [icon]="'sort'"></fa-icon>
</th>
<th jhiSortBy="assignedTo.login"><span
jhiTranslate="bugTrackerJHipsterApp.ticket.assignedTo">Assigned To</span>
<fa-icon [icon]="'sort'"></fa-icon>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let ticket of tickets">
<td><a [routerLink]="['/ticket', ticket.id,
'view' ]">{{ticket.id}}</a></td>
<td>{{ticket.title}}</td>
<td>{{ticket.description}}</td>
<td>{{ticket.dueDate | date:'mediumDate'}}</td>
<td>{{ticket.done}}</td>
<td>
<div *ngIf="ticket.project">
<a [routerLink]="['../project', ticket.project?.id,
'view' ]">{{ticket.project?.name}}</a>
</div>
</td>
<td>
{{ticket.assignedTo?.login}}
</td>
<td class="text-right">
<div class="btn-group flex-btn-group-container">
<button type="submit"
[routerLink]="['/ticket', ticket.id, 'view' ]"
class="btn btn-info btn-sm">
<fa-icon [icon]="'eye'"></fa-icon>
<span class="d-none d-md-inline"
jhiTranslate="entity.action.view">View</span>
</button>
<button type="submit"
[routerLink]="['/ticket', ticket.id, 'edit']"
class="btn btn-primary btn-sm">
<fa-icon [icon]="'pencil-alt'"></fa-icon>
<span class="d-none d-md-inline"
jhiTranslate="entity.action.edit">Edit</span>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
Integration tests
Integration tests are done with the Spring Test Context framework, and are located in the folder
src/test/java. JHipster will launch a specific Spring test context, which will be re-used along
all tests, as:
• Your Spring beans should be stateless and thread-safe, and thus can be re-used across your
different tests suites.
• Launching just one Spring context for all the tests if a lot faster than launching a new Spring
context for each test.
This Spring test context will use a specific test database for the execution of the tests:
• If you use a SQL database, JHipster will launch an in-memory H2 instance in order to use a
temporary database for its integration tests. Liquibase will be run automatically, and will
generate the database schema.
• If you use Cassandra, JHipster will launch an in-memory Cassandra instance using
CassandraUnit.
• If you use MongoDB, JHipster will launch an in-memory MongoDB instance using
de.flapdoodle.embed.mongo.
• If you use Elasticsearch, JHipster will launch an in-memory Elasticsearch instance using
Spring Data Elasticsearch.
• If you use Couchbase, JHipster will launch a containerized version of Couchbase with
Docker using Couchbase TestContainers.
Those tests can be run directly in your IDE, by right-clicking on each test class, or by running
./mvnw clean test (or ./gradlew test if you run Gradle).
In our case and especially if you are using Google Cloud Shell, run the command in your
application folder:
./mvnw clean test
Limitations: if the generated entities have some validations, JHipster will not be able to generate
the correct values depending on the validation rules because the rules can be complex (i.e. regex
pattern). In this case, the tests will fail and you will have to change the values manually to make the
tests pass.
Note that the Behaviour-driven development (BDD) is available using Cucumber, with its JVM
implementation. Gherkin features will have to be written in your src/test/features
directory.
That means Cucumber, being a JUnit extension, will be ran along your ./mvnw clean test
command.
Performance tests
Performance tests are done with Gatling, and are located in the folder src/test/gatling. They
are generated for each entity, and allows to test each of them with a lot of concurrent user requests.
To run Gatling tests, you must first install Gatling: please go to the Gatling download page and
follow the instructions there. Please note we do not allow to run Gatling from Maven or Gradle, as
it causes some classpath issues with other plugins (mainly because of the use of Scala).
NOTE We currently support Gatling 2.x only. You can download the latest 2.x version directly from
maven central.
Warning! At the moment, those tests do not take into account the validation rules you may have
enforced on your entities. Also tests for creating entities that have a required relationship with
another entity will fail out of the box. You will anyway need to change those tests, according to
your business rules, so here are few tips to improve your tests:
• On your running application, go to the Administration > Logs screen, and put
org.springframework in debug mode. You will see the validation errors, for
example.
• Use the application normally and open the Chrome console log: you will be able to see
the REST requests with all their parameters, including the HTTP headers.
For running Gatling tests on a microservice application, you have to:
• Run a registry
• Run a gateway
In this tutorial, we've given you an installation script for Gatling. Run the following command to
install it:
~/jhipster-guides/utils/install-gatling.sh
and run:
~/jhipster-guides/gatling/bin/gatling.sh
Let's stress test our Project API, so choose 1. You don't especially need to give a simulation id nor a
description so you can just skip these parts.
When the test ends, gatling generates an html file that allows you to check the results: feel free to
visit the html page!
UI tests
UI tests come in two flavors with JHipster: unit tests with Jest, and integration tests with Protractor.
Only Jest is provided by default, but if you want to have a good test coverage of your application,
we recommend that you use both tools together.
Jest
UI unit tests are located in the folder src/test/javascript/spec. They use Jest.
Those tests will mock up the access to the application's REST endpoints, so you can test your UI
layer without having to launch the Java back-end.
• Those tests can be run using npm test.
• Tip: if you want to focus on a single test then change the module description from
describe('...', function() { to fdescribe('...', function() { and
Jest will run this test only.
cd ~/BugTrackerJHipster;npm test
Protractor
UI integration tests are done with Protractor, and are located in the folder
src/test/javascript/e2e.
Those tests will launch a Web browser and use the application like a real user would do, so you
need to have a real application running, with its database set-up.
Those tests can be run using npm run e2e.
Please note that Protractor test needs a browser to run the protractor tests. If you are using Google
Cloud Shell, you will not be able to run Protractor test. If you have set up a repository for your
project, you can run them locally after cloning it on your computer.
08. Deploying your app
Testing a production package
This allows to test a production build from Maven, without building a real package. To use JHipster
in “production” mode, use the pre-configured prod profile. With Maven, please run:
./mvnw -Pprod
This profile will compile, test and package your application with all productions settings.
If you want more information on the available profiles, please go the section titled Development
and Production profiles.
Next we will deploy our application using Docker, however if you want to build and execute WAR
file, you can check it out on JHipster website.
• Several Docker Compose configurations to help you run your application with third-party
services, for example a database
Those files are located in the folder src/main/docker/.
Prerequisites
You have to install :
• Docker
• Docker Compose
Luckily, you do not need to install it with Google Cloud Shell.
Build and running a Docker image of your application
To create a Docker image of your application, and push it into your Docker registry:
./mvnw package -Pprod verify jib:dockerBuild
This process takes some time to complete (about 15 minutes with the boost mode on).
To run this image, use the Docker Compose configuration located in the src/main/docker folder of
your application:
docker-compose -f src/main/docker/app.yml up