In this blog, you will learn more about JHipster and how it can help you with developing modern web applications. Enjoy!

1. Introduction

JHipster is a development platform which helps you to quickly set up an application. It goes beyond setting up a project structure: JHipster will generate code, database tables, CRUD (Create, Read, Update, Delete) webpages, unit and integration tests, etc.

You are not bound to a specific framework or technology. Many options are available for the server side technologies (Spring Boot, Micronaut, Quarkus, etc), databases (MySQL, MariaDB, PostgreSQL, MongoDB, etc), build tooling (Maven, Gradle, Jenkins, GitLab CI, etc), client side technologies (Angular, React, Vue, etc) and deployment (Docker, Kubernetes, AWS, GCP, etc). The complete list can be found at the JHipster website. The list is huge and impressive.

JHipster exists since 2013, so it is definitely not a new kid on the block. Enough for the introduction, let’s get started in order to see how it works and how it looks like!

The sources used in this blog are available at GitHub.

2. Prerequisites

It is very useful when you have basic knowledge of how applications are built with Spring Boot, Vue.js, PostgreSQL, Liquibase, Maven. If you do not have knowledge of these technologies, JHipster can be a stepping stone for you to see how such an application looks like.

The installation instructions for JHipster are executed based on the instructions provided on the JHipster website. It is good to check the official instructions in addition to the ones mentioned below.

Installation of JHipster requires Java (in this blog Java 17 is used, you can use SDKMAN to install Java), Git and Node.js (Node.js v18.15.0 is used in this blog). See the respective websites for installation instructions.

Install JHipster:

$ sudo npm install -g generator-jhipster

Create a new directory myjhipsterplanet and navigate into the directory:

$ mkdir myjhipsterplanet
$ cd myjhipsterplanet

3. Create JHipster Application

Creating a JHipster application requires to answer some questions after running the jhipster command. However, at the time of writing, executing the jhipster command resulted in an error.

$ jhipster 
INFO! Using bundled JHipster
node:internal/modules/cjs/loader:571
      throw e;
      ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/util/namespace' is not defined by "exports" in /usr/lib/node_modules/generator-jhipster/node_modules/yeoman-environment/package.json
    at new NodeError (node:internal/errors:399:5)
    at exportsNotFound (node:internal/modules/esm/resolve:361:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:697:9)
    at resolveExports (node:internal/modules/cjs/loader:565:36)
    at Module._findPath (node:internal/modules/cjs/loader:634:31)
    at Module._resolveFilename (node:internal/modules/cjs/loader:1061:27)
    at Module._load (node:internal/modules/cjs/loader:920:27)
    at Module.require (node:internal/modules/cjs/loader:1141:19)
    at require (node:internal/modules/cjs/helpers:110:18)
    at Object.<anonymous> (/usr/lib/node_modules/generator-jhipster/utils/blueprint.js:19:25) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

An issue exists for this problem and a workaround is provided.

Open the package.json file with a text editor.

$ sudo vi /usr/lib/node_modules/generator-jhipster/node_modules/yeoman-environment/package.json

Add the following line to the exports section:

"exports": {
    ...,
    "./lib/util/namespace": "./lib/util/namespace.js"
}

Executing the jhipster command will be successful now. A list of questions will be asked in order for you to choose the technologies you want to use in the application. In bold the answers are provided that are used for this blog.

  • May JHipster anonymously report usage statistics to improve the tool over time? n
  • Which type of application would you like to create? Monolithic application
  • What is the base name of your application? (myjhipsterplanet)
  • Do you want to make it reactive with Spring WebFlux? n
  • What is your default Java package name? com.mydeveloperplanet.myjhipsterplanet
  • Which type of authentication would you like to use? HTTP Session Authentication (stateful, default Spring Security mechanism)
  • Which type of database would you like to use? SQL (H2, PostgreSQL, MySQL, MariaDB, Oracle, MSSQL)
  • Which production database would you like to use? PostgreSQL
  • Which development database would you like to use? H2 with disk-based persistence
  • Which cache do you want to use? (Spring cache abstraction) No cache – Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!
  • Would you like to use Maven or Gradle for building the backend? Maven
  • Do you want to use the JHipster Registry to configure, monitor and scale your application? Yes
  • Which other technologies would you like to use? API first development using OpenAPI-generator
  • Which Framework would you like to use for the client? Vue
  • Do you want to generate the admin UI? Yes
  • Would you like to use a Bootswatch theme (https://bootswatch.com/)? Default JHipster
  • Would you like to enable internationalization support? No
  • Please choose the native language of the application English
  • Besides JUnit and Jest, which testing frameworks would you like to use? Do not choose any
  • Would you like to install other generators from the JHipster Marketplace? No

At the end, the application is generated after a few minutes and the changes are committed in Git.

$ git log
commit f03bf340c15315ffbeb59c56eec2b4da777f4e53
Author: mydeveloperplanet <gunter@mydeveloperplanet.com>
Date:   Sun Mar 19 13:53:18 2023 +0100

    Initial version of myjhipsterplanet generated by generator-jhipster@7.9.3

Build the project.

$ ./mvnw clean verify

Run the application.

$ java -jar target/myjhipsterplanet-0.0.1-SNAPSHOT.jar
...
----------------------------------------------------------
        Application 'myjhipsterplanet' is running! Access URLs:
        Local:          http://localhost:8080/
        External:       http://127.0.1.1:8080/
        Profile(s):     [dev, api-docs]
---------------------------------------------------------- 

4. Create Entities

The above generated application is quite empty because it contains no domain entities. JHipster provides the JDL-Studio for creating the domain entities. There are also IDE plugins available for JDL-Studio. JDL stands for JHipster Domain Language and it is quite intuitive how to model your domain. In the example application, the domain consists out of a Company with a Location. A Company has one or more Customers, and a Customer also has an Address.

The JDL for this domain is the following. As you can see, it is not very complicated.

entity Company {
	companyName String required
}

entity Location {
	streetAddress String,
	postalCode String,
	city String
}

entity Customer {
	customerName String required
}

entity Address {
	streetAddress String,
	postalCode String,
	city String
}

relationship OneToOne {
	Location{company} to Company
}

relationship OneToMany {
	Company to Customer{company}
}

relationship OneToOne {
	Address{customer} to Customer
}

Add the customer.jdl file to the root of the repository and generate the code with JHipster. During generating the files, you will be asked to overwrite some files, you can answer these questions with yes every time.

$ jhipster jdl customer.jdl

As a result, a .jhipster directory is created containing json files for the domain entities.

.jhipster/
├── Address.json
├── Company.json
├── Customer.json
└── Location.json

Besides that, quite some code is generated.

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .yo-rc.json
	modified:   src/main/resources/config/liquibase/master.xml
	modified:   src/main/webapp/app/entities/entities-menu.vue
	modified:   src/main/webapp/app/entities/entities.component.ts
	modified:   src/main/webapp/app/router/entities.ts

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.jhipster/
	customer.jdl
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/domain/Address.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/domain/Company.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/domain/Customer.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/domain/Location.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/repository/AddressRepository.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/repository/CompanyRepository.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/repository/CustomerRepository.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/repository/LocationRepository.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/AddressResource.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/CompanyResource.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/CustomerResource.java
	src/main/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/LocationResource.java
	src/main/resources/config/liquibase/changelog/20230319134139_added_entity_Company.xml
	src/main/resources/config/liquibase/changelog/20230319134140_added_entity_Location.xml
	src/main/resources/config/liquibase/changelog/20230319134140_added_entity_constraints_Location.xml
	src/main/resources/config/liquibase/changelog/20230319134141_added_entity_Customer.xml
	src/main/resources/config/liquibase/changelog/20230319134141_added_entity_constraints_Customer.xml
	src/main/resources/config/liquibase/changelog/20230319134142_added_entity_Address.xml
	src/main/resources/config/liquibase/changelog/20230319134142_added_entity_constraints_Address.xml
	src/main/resources/config/liquibase/fake-data/
	src/main/webapp/app/entities/address/
	src/main/webapp/app/entities/company/
	src/main/webapp/app/entities/customer/
	src/main/webapp/app/entities/location/
	src/main/webapp/app/shared/model/address.model.ts
	src/main/webapp/app/shared/model/company.model.ts
	src/main/webapp/app/shared/model/customer.model.ts
	src/main/webapp/app/shared/model/location.model.ts
	src/test/java/com/mydeveloperplanet/myjhipsterplanet/domain/
	src/test/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/AddressResourceIT.java
	src/test/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/CompanyResourceIT.java
	src/test/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/CustomerResourceIT.java
	src/test/java/com/mydeveloperplanet/myjhipsterplanet/web/rest/LocationResourceIT.java
	src/test/javascript/spec/app/entities/

What has been generated/updated?

  • Liquibase database migration scripts including fake testdata;
  • Domain objects for the entities;
  • Repositories for the domain objects;
  • REST end points for the entities;
  • Entities and pages for the frontend;
  • Integration tests for the REST endpoints;
  • Test for the frontend pages.

5. Generated Application

You have generated an application with JHipster based on a basic domain model. How does this look like? Build and run the application with the above generated code and open the application at http://localhost:8080/. A welcome page is shown.

Click at the right top bottom and choose Sign In. Sign in with user admin and password admin. In the menu at the top, you choose Entities and you will see items for each entity you created. Select Companies. A page is shown with the fake data and as you can see, CRUD operations are available.

Navigate to the Customer entity and edit a Customer. An edit screen is shown. A Customer belongs to a Company. However, the generated code lets you select the Company based on the database identifier. This is not very user friendly of course, so you will need to change that.

Because you are logged in as an administrator user, you also have the Administration pages. Let’s take a look at the different Adminstration pages.

User Management is used for managing the users in the application.

Metrics shows all kinds of metrics like for example the counts for each request.

Health gives information about the state of the application.

Configuration shows information how the application is configured, basically the application properties.

Logs provides easy access to the logs and their respective log levels.

API shows the Swagger documentation of the API.

Database provides access to the database. In this application, you do not need to provide any credentials, just click the Connect button.

And now you can browse the database.

The Administration pages provide quite some information out-of-the-box, you did not need to develop anything for this.

6. Sonar Analysis

Sonar analysis is also provided. Therefore, you need to start a local Sonar server.

$ docker compose -f src/main/docker/sonar.yml up -d

And run the Sonar analysis.

$ ./mvnw -Pprod clean verify sonar:sonar

As a result, you can browse the Sonar results. As you can see, the result for the overall code is quite good and there is a test coverage of 72.9%. That’s not bad at all.

7. Update Dependencies

The generated JHipster code used Java 11 and some older dependencies. The versions are listed in the pom file.

<properties>
    <!-- Build properties -->
    <maven.version>3.2.5</maven.version>
    <java.version>11</java.version>
    <node.version>v16.17.0</node.version>
    <npm.version>8.19.1</npm.version>
    ...
</properties>

Change these to a more recent version.

<properties>
    <!-- Build properties -->
    <maven.version>3.8.7</maven.version>
    <java.version>17</java.version>
    <node.version>v18.5.0</node.version>
    <npm.version>8.19.4</npm.version>
    ...
</properties>

Build and run the application (a local Maven installation was used for this instead of the Maven wrapper). Everything still worked fine after this update.

8. Conclusion

In this blog you learned how to create a basic application generated with JHipster. Quite some code and functionality is generated which gives you a good start for changing the application in order that it fits your needs. You only scratched the surface of JHipster in this blog, so do read the official documentation in order to get more acquainted with JHipster.