I recently looked for a solution on how to prototype a customer project in a short time and came across JHipster. The target architecture used Spring Boot in the backend and an Angular frontend. JHipster can scaffold this in its simplest variant as a monolithic project. But JHipster can do even more: it generates microservice architectures with all the associated state-of-the-art tooling that you need to deploy and run professional microservice projects.
I have always been a friend of avoiding boilerplate coding and have enjoyed using Xtext DSL in my projects to generate applications. In addition to the interactive interview mode, JHipster also provides a descriptive language for project creation called JDL. This blog post explains this quick, repeatable and easily understandable approach.
What is JHipster?
JHipster is an open source development platform to generate, develop, test and deploy web applications and microservice architectures.
For the frontend there are 3 different flavors: Angular , React and Vue . It includes Bootstrap and HTML5 Boilerplate , NPM , I18N support, Jest , Cucumber and Protractor , so there is nothing missing for a professional frontend developer.
In the backend, JHipster relies on Spring Boot but is not limited to it. It heavily exploits Spring additions like Security , MVC Rest , Data JPA and Websocket . The most common SQL and NoSQL databases are supported for the persistence layer. With Elasticsearch you get search capabilities on top of your database. Most interesting for me for high-availability microservice architectures: Kafka as messaging system. The biggest sticking point in a heavy loaded system is the buffering of messages in a queue in order not to lose any customer requests.
To set up microservices cleanly, routing and service discovery are carried out with Zuul and Eureka from Netflix, but Traefik and Consul could also be your choice. Runtime monitoring is done with the ELK stack.
Security is provided with 4 different mechanisms: JWT, session-based authentication, OAuth2 and OIDC, or JHipster project UAA which is dedicated to microservices using the OAuth2 authorization protocol. Using the OAuth2/OIDC option enables your application to work directly with Keycloak .
Finally, JHipster also supports the deployment for all major cloud providers: AWS , Cloud Foundry , GCP , Heroku , Kubernetes , OpenShift , Azure , Docker .
JHipster will generate a basic CRUD application running out-of-the-box according to your choices for all the mentioned features which is a perfect starting point for your further development.
JHipster can be found at https://www.jhipster.tech/ or in an online variant at https://start.jhipster.tech/ . Since JHipster has been in development since 2013, it is a mature tool with a vivid community and available on Github and Gitter.im. Fun fact: They award a price for fixing bugs, called “bug-bounty” which can be between $100 and $500 depending on the difficulty to solve it.
What this blog post is about
At the time of writing this blog I worked with version 6.8.0 of JHipster. I want to show you how to set-up a simple microservice architecture as a scaffold for an e-commerce platform with JDL. As a first try, the application is deployed to docker. Later in the post you’ll find the deployment to Kubernetes and Heroku. The initial setup for JHipster can also be achieved with an interactive approach. But for all of these methods there is the need to install some software first.
Prerequisites
Recommended is an AdoptOpenJDK Java 11 (LTS) build. Also install Node.js in a LTS version (for now it is 12.16.3). To globally install JHipster enter:
npm install -g generator-jhipster
You can also use Yarn :
yarn global add generator-jhipster
JHipster will automatically install a wrapper for Maven or Gradle so it is not necessary to install them. If Git is installed, JHipster will try to commit the project to Git. For this example you also need Docker installed. For the moment I have Docker version 19.03.8 installed.
On your marks…
Open https://start.jhipster.tech/ in your browser, sign in and navigate to “Design Entities” and press “Create a new JDL Model”
Figure 1: Design Entities online
Figure 2: New JDL Model
If you open the JDL designer for the first time, a sample entity model appears combined with the according diagram. Just select all and delete all to get an empty workspace.
Define applications and entities with JDL
For microservice architectures JHipster knows two application types: gateways and microservices.
- A gateway handles web traffic and serves the frontend application. You can follow the Backends for Frontends pattern with this approach and build a gateway for every frontend technology that you want to serve.
- Microservices handle the frontend requests as backend services, are stateless and several instances can be launched in parallel to cope with high traffic.
The first app we define is the frontend gateway using some defaults like Angular etc. Find the complete documentation for applications here. The next two apps are the microservices split in a service serving the product master-data and the other one serving the orders. The gateway uses all entities and all services use Kafka for messaging. Deployment is defined for using Docker.
The special case in this entity model is the user entity that is actually hidden by JHipster, which is expanded in a one-to-one relationship with necessary attributes for the customer. This only works if OAuth2 is specified as authenticationType. Only in this case a copy of the user record is copied from the authentication provider to the database when logging in.
Data transfer object can be used to enforce strong decoupling from the JPA-managed entities of an EntityManager. This makes it easier to implement additional business logic in the service classes.
Finally, meta information for the scrolling functionality of the product list is specified. It should be loaded lazily and can be browsed page by page. The microservice instruction specifies from which services entities can be obtained.
Here is the complete listing of the apps and entity definition:
application {
config {
baseName webStore
applicationType gateway
serverPort 9042
authenticationType oauth2
packageName com.mycompany.store.web
searchEngine elasticsearch
serviceDiscoveryType eureka
testFrameworks [protractor]
languages [en, de]
nativeLanguage en
messageBroker kafka
}
entities *
}
application {
config {
baseName storeService
applicationType microservice
serverPort 8083
authenticationType oauth2
packageName com.mycompany.storeservice
searchEngine elasticsearch
serviceDiscoveryType eureka
languages [en, de]
nativeLanguage en
messageBroker kafka
}
entities Product, Photo
}
application {
config {
baseName orderService
applicationType microservice
serverPort 8084
authenticationType oauth2
packageName com.mycompany.order
searchEngine elasticsearch
serviceDiscoveryType eureka
languages [en, de]
nativeLanguage en
messageBroker kafka
}
entities SalesOrder, SalesOrderItem
}
deployment {
deploymentType docker-compose
appsFolders [storeService, orderService, webStore]
dockerRepositoryName "joergriegel"
}
enum Gender {
FEMALE, MALE, DIVERSE
}
entity Customer {
name String required minlength(2)
phoneNumber String
gender Gender
addressLine1 String
addressLine2 String
addressLine3 String
addressLine4 String
townCity String
county String
zip String
}
enum SalesOrderStatus {
PENDING, CANCELLED, SHIPPED, COMPLETED
}
entity SalesOrder {
salesOrderNumber String
customerId String
placed Instant
cancelled Instant
shipped Instant
completed Instant
status SalesOrderStatus
}
enum SalesOrderItemStatus {
PENDING, DELIVERED, OUTOFSTOCK, COMPLAINED
}
entity SalesOrderItem {
name String
sku String
taxable Boolean
grosWeight Double
shipped LocalDate
delivered LocalDate
status SalesOrderItemStatus
quantity BigDecimal
unitPrice BigDecimal
amount BigDecimal
}
enum ProductStatus {
ONSALE, LOCKED, OOUTOFSTOCK, INREPLENISHMENT
}
enum UnitOfMeasurement {
PIECE, KILOGRAM, GRAM, LITER
}
entity Product {
name String required minlength(2)
sku String required minlength(6)
description String
srp BigDecimal
taxable Boolean
salesUnit UnitOfMeasurement
salesQuantity BigDecimal
status ProductStatus
grosWeight Double
netWeight Double
length Double
width Double
height Double
}
entity Photo {
photo ImageBlob
}
relationship ManyToOne {
Customer{user(login)} to User
}
relationship OneToMany {
SalesOrder{orderItems} to
SalesOrderItem{salesOrder(salesOrderNumber)}
Product{photos} to Photo{product(name)}
}
// Use Data Transfer Objects (DTO)
dto * with mapstruct
// Set service options to all
service all with serviceClass
paginate Product with infinite-scroll
microservice Product, Photo with storeService
microservice SalesOrder, SalesOrderItem with orderService
This is the diagram for the resulting entity model:
Figure 4: Entity Model
Generate the code
Either you use the JDL Studio to edit the above JDL and press “Download text file of this JDL” or you copy the JDL into a file with the extension “jh”. If you press download the name of the file in your download directory will be “jhipster-jdl.jh”.
Figure 5: Download JDL
JHipster internally uses Yeoman to generate code. In order to use the JDL generator just type in a terminal:
jhipster import-jdl
The generators are smart so that you can change models over and over again – no problem. Changing the database schema is no drama. They put Liquibase inside doing all the changesets necessary to bring schema changes from the sandbox to production.
After generating one of the apps, the gateway “webStore” with Angular 9 code has a nice Readme, a lot of docker-compose yml files and looks like this:
Figure 6: Intellij Idea
Two profiles “dev” and “prod” were generated. Now navigate to each directory of the apps and build production-ready code deployed on Docker:
./mvnw -ntp -Pprod verify jib:dockerBuild
Get set…
As you can see JHipster uses the Jib maven-plugin to build an image for each app. After you completed this three apps, you navigate to the directory “docker-compose” and start docker by typing:
docker-compose up -d
Make sure that you allow docker enough memory to cope with the size of the images. For me 10GB worked for this example.
Figure 7: Docker Settings
docker ps
should show 13 containers started:
Figure 8: Docker ps
…Go
Open your browser on localhost:8080
and voilà. Your first JHipster microservice is up:
Figure 9: The Application
As you defined 2 possible languages, there is a drop down where you can choose another language.
Figure 10: Language Selection
Figure 11: Localized Application
Login
Important: before you can use Keycloak, you have to add an entry in your etc/hosts:
127.0.0.1 keycloak
or else the redirection will not work for you. The reason for this is that Docker will use service names to reach services internally.
Login with admin/admin via Keycloak started in a container because you chose “oauth2” in the application definition.
Figure 12: Login
Once you signed in, Keycloak will provide you with SSO and handles all the token logic. For a production grade you still must modify the docker-compose to have it more robust and secure. The other predefined user is “user/user”. The only difference is that this user is not allowed to see or start administrative tasks from the menu. Keycloak makes it easy to fine-grain this role-based access control. If you need deeper knowledge or training on Keycloak don’t hesitate to contact us .
All the defined entities are shown in the menu and you first get the list and then can decide to create new entries in a form generated for the entity.
Figure 13: CRUD the Entities
Relations are selectable using a combo-box. If you used a hint in the JDL what to display from the opposite entity like this: Customer{user(login)} to User
, the combo will display the field “login” instead of the meaningless id.
Figure 14: Edit Customer
The list will look like the following figure with some entries. Don’t forget that this is only scaffolding, there is still a lot of work to do to get a nice-looking UI. But by then it is already a huge time advantage thanks to the use of JHipster.
Figure 15: Customer List
Under the hood
What drives microservices developers the most is statistics about how the services behave, how healthy they are, and how one can easily implement malfunction analysis. With JHipster you are not left alone. The administrative menu shows some functions that must not be missing in any professional system. But in case your application won’t start would you lose this information? No – you have JHipster-Registry (already started with Docker) which provides the same information in an independent service. The default port for the registry is 8761.
Figure 16: Administration
Gateway
Figure 17: Gateway Routes
Have a look at the routes and see what services on which servers are up and how they were built.
Metrics
Figure 18: Metrics
Have all parameters under control:
- the JVM
- HTTP requests
- Endpoint requests
- Cache statistics
Health
Figure 19: Health
See different aspects of your services and drill-down some health checks to detail level.
Configuration
Figure 20: Configuration
Look at all configuration properties and use a filter to find the desired setting.
Audits
Figure 21: Audits
Find out who had a session against your system and when.
Logs
Figure 22: Logs
Track down the source of problems in your applications by adjusting the granularity of logging.
API
Figure 23: Swagger Web
Figure 24: Swagger OrderService
Study the whole Swagger documentation of your microservice architecture.
Eureka
In JHipster Registry even more information can be seen:
Figure 25: Instances
Figure 26: Instance History
More Metrics
In complex environments you also have the possibility to find out more about the health of your system with the JHipster Console. The applications can be configured to forward their metrics to an external monitoring system where they can be graphed over time and analyzed. You can profit from the ELK stack to create dashboards and alerts. Just clone JHipster Console from Github, and from the bootstrap directory run docker-compose up
. In every application-prod.yml or if you wish application-dev.yml in src/main/resources/config change the “enabled” values to true:
Figure 27: JHipster Properties
HTTP Routing
Figure 28: Routing Architecture
This is how the routing looks like in this setup: the gateway handles frontend requests on 8080 and is securing all services with Keycloak and its tokens. Microservices handle the backend tasks and take care of the database operations. The registry discovers all services and collects information about them.The console provides deeper insight about inner behavior of the services.
Deployment
Kubernetes
As you learned from the previous steps you can deploy JHipster microservices in a docker environment. But you can also deploy on Kubernetes. First you have to install Kubernetes on your local machine if you want to try it out locally. Follow the guide here and install Minikube too. Start your Minikube by typing in a terminal window:
minikube start
in a terminal window enter the docker-compose directory, create a sub-directory (e.g. k8s) and navigate to it. To create all the necessary files to deploy on Kubernetes there is a generator available, just type:
jhipster kubernetes
and answer the questions like this:
Figure 29: Kubernetes Generator
Follow the instructions, issue the commands and check your pods afterwards:
kubectl get pods
Heroku
Heroku is a cloud platform as a service supporting several programming languages. We can use it to deploy our little microservice architecture to the cloud. At first we have to install the Heroku CLI from here . When this is done, you have to create a free account . Once your e-mail address is confirmed, you can login from a terminal window with:
heroku login
As we need the service discovery in the cloud for microservices, we first must deploy a version of JHipster Registry to Heroku.
After successful deployment of the Registry, you can run the JHipster generator for Heroku in each directory (storeService, orderService and webStore) of our system:
jhipster heroku
Important: The deployment type for our apps must be “jar” not “git”.
Conclusion
JHipster creates a uniform application framework that can be expanded into a larger application. All activities that would otherwise take up a lot of valuable time. With JHipster the entry hurdles are lowered and the options are increased. JHipster unlocks the advantages of Spring Boot. With Docker support and AWS Elastic Beanstalk, it has become easy to develop cloud-native applications. JHipster is very mature. This allows you to optimally combine the strengths of Java and JavaScript in the development of web applications, so that the path to cloud-native applications is less rocky.
More articles
fromJörg Riegel
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Jörg Riegel
Senior IT Consultant
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.