Mark Tripoli I am HP Nonstop developer, who develops train control systems. I love open source projects and information and attempting to teach others new tools. I am a blockchain junkie and love its tech!

Build an issue tracker with jHipster (part 1)

  Reading Time:

Introduction

In my previous post Introduction to jHipster (ReactJs Version)
, I gave a brief overview of jHipster, the Java Spring generator. I gave a brief but detail explanation of what jHipster is and how neat it is. In this page, I will now guide you through creating a simple issue tracker to show you how to use jHipster and how awesome it really is. This is something similar I built at work a few weeks back. It is basically a web app that displays all of our upcoming releases, open SPRs (change requests/issues), and all unreviewed SPRs.

Before going any further please be sure you have a basic understanding of the following as I will not go into great detail about the technologies:

  • Java
  • Spring Boot
  • ReactJS
  • HTML/CSS

If you are just starting to learn React, this project may be beneficial in your understanding.

This tutorial will be broken up into 3 segments:

  • Server-side development
  • Frontend development
  • Deployment

So with all that mess behind us, let's jump into it.

Installation

JHipster provides 4 different means of installation.

  • JHipster Online Creates a ZIP of the project
  • NPM
  • Yarn
  • Docker

For this tutorial, we will be using NPM.

To install jHipster we need to ensure we have the following:

  1. JDK 11+
  2. Node

The first thing we need to do is install the generator (You may need to user superuser).

npm install -g generator-jhipster

Create a directory named "IssueTracker"

mkdir IssueTracker

Enter the new directory.

cd Issue Tracker

Now we will generator our application with jHipster

jhipster

Screenshot-from-2019-06-03-07-51-43

Next, you will be presented with a few questions which will custom tailor the boilerplate application to suit your needs. Choose the following options. Feel free to use any theme you want.

Screen-Shot-2019-06-03-at-11.22.04-AM

This process may take a few minutes.

Upon completion, open the project in an editor of your choice. I will be using IntelliJ, where you need to import the project as a Maven project.

Screen-Shot-2019-06-03-at-11.31.46-AM

Screen-Shot-2019-06-03-at-11.32.35-AM

More detailed instructions on how to set up your environment can be found Here.

If you are using IntelliJ Ultimate, it should automatically set up your environment to handle this as a Spring Boot Project.

Screen-Shot-2019-06-03-at-11.37.29-AM

We will now want to install all of our dependencies. From within the root folder of the project, execute the following statement to install the frontend dependencies.

npm install

That's it! Now our boilerplate is ready to launch!

Run the application

I am sure after all of that, you want to see what jHipster provides you! Use the following commands in separate terminals to run the project. These two commands will ensure your project auto-updates the frontend assets. If you're using IntelliJ Ultimate, your configuration should be loaded, just go ahead and press the "play" button to launch the application (no hot reload).

./mvnw
npm start

Upon executing the ./mvnw script, your database versioning will update. Liquibase will look for any new configurations, it will automatically create, delete, or update your current schema.

Once your frontend has compiled, you will be brought to your beautiful home screen.

Screen-Shot-2019-06-03-at-11.49.57-AM

There you, you now have a running application generated by jHipster. Pretty sweet, right? Go ahead and explore a little bit. You will notice it isn't really doing anything. No worries, we will start the fun part of creating our backend next.

Entity Creation

Now that our application is running and operational, we need to start giving it some functionality. To do that we need to create our database schema for storing our issues. JHipster has automatically created our base schema for the database which already includes a few things such as our User table.

This is one area where jHipster really shines, especially for simple projects. The generator includes an entity creator. What does that mean? We can create our schema via the CLI, JSON styled file, or via UML-like editor.

It is a good idea to get comfortable with all of the tools offered. Personally, I enjoy designing schemas in the online editor JDL Studio, then importing the resulting file. I will briefly cover both methods to give you an idea.

JDL-Studio

The JDL-Studio is an online UML-like editor. You design your schema using the JDL language which jHipster nicely defines. This language is like a off-shoot of JSON and is very simple to understand and pick up quickly.

I have created a JDL for use within this application.
Screen-Shot-2019-06-03-at-2.02.15-PM


// The priority describes how urgent the issue is
enum Priority {
	SHOWSTOPPER,
    EMERGENCY,
    HIGH,
    LOW,
    ROUTINE,
    DEFER
}

// The resolution is the current status of the issue
enum Resolution {
	NEW,
    RELEASED,
    DUPLICATE,
    TESTED,
    FIXED,
    PARTIALLY_FIXED,
    REVIEWED,
    CANNOT_REPRODUCE
}

// This is the Issue table, which will be mapped to an object
entity Issue {
    number Integer required,
    description TextBlob,
    priority Priority,
    resolution Resolution,
    reviewerId Long,
    reportedDate Instant
}

// Comment for users to make
entity Comment {
	description TextBlob required,
    date Instant required
}

//
// DEFINE RELATIONSHIPS
//

// One issue may have many comments on it
relationship OneToMany {
	Issue{comment} to Comment
}

// One user can have multitple issues
// One user can make many comments
relationship ManyToOne {
	Issue{user(login)} to User,
    Comment{user(login)} to User
}

// Create a service class for all entities
service * with serviceClass

// Allow us to filter all the issues by their fields
filter Issue

With the schema defined and our JDL written we now need to load this file.

Note: If using the generator. You will normally want to commit and push all code prior to generating an entity. If you made a mistake in the schema, you will be unable to revert the changes.

  1. From the root folder of the application, execute the following statement to create a blank JDL file:
touch app.jdl
  1. Paste in the code we generated.
  2. Load the file by executing
jhipster import-jdl app.jdl

JHipster will parse the file and create all the backend files, frontend files, liquibase change files, etc and then compile the frontend. Upon completion, you should have the following.
Screen-Shot-2019-06-03-at-2.07.23-PM

To see your changes, restart the backend (CTRL+C then type ./mvnw), head over to the webpage, ensure you are logged in, and go to "Entities". You should now notice the entities you have created are now on the menu.

Screen-Shot-2019-06-03-at-2.12.40-PM

Click on "Issues". You will notice there is a table filled with random data.
Screen-Shot-2019-06-03-at-2.15.38-PM

JHipster will automatically generate a file(s) for your entities and fill it with random data. So when the database is synced with the changes, it will give you some dummy data. If you do not want this data to load every time or you want to create your own data, delete or change the information for the appropriate files at:

/IssueTracker/src/main/resources/config/liquibase/data

For now, leave all of the pre-generated items. We will come back and delete them later on in this tutorial. It's time to move onto our CRUD operations.

Updating our Repository

Now that we have our freshly generated database, classes, frontend, and API. We now want to modify our application to actually do something useful, other than just displaying all the data in bulk. We want to be able to display our issues in a certain way. Such as creating a page where we can view all opened issues. To do that, we need to modify our repository logic to perform specific queries.

Go back to your editor and go to the repository direction

IssueTracker/src/main/java/com/triippztech/repository

All of our repositories for our entities will be located here. Find and open the "IssueRepository.java" file. We want to make queries to find all open Issues and all reviewed Issues. Add the following code to the file.

List<Issue> findAllByResolution(Resolution resolution);

This will allow us to query both things we want to do. Next, we will need to write our services to perform these new queries.

Services
So to perform these specific queries, we need to add some stuff to our services. This will enable our REST portion of our application to communicate with and query the database. Under the service directory, open the "IssueService.java" file and add the following code.

@Transactional(readOnly = true)
public List<Issue> findAllOpenIssues()
{
    log.debug("Request to find all open Issues");
    return issueRepository.findAllByResolution(Resolution.NEW);
}

@Transactional(readOnly = true)
public List<Issue> findAllReviewedIssues()    
{
    log.debug("Request to find all reviewed Issues");
    return issueRepository.findAllByResolution(Resolution.REVIEWED);
}

Now we are able to access and retrieve all of our open and reviewed issues. Next, we want to modify our REST calls.

Resource (REST)

For our React app to be able to utilize our new specified data, we need the means of disseminating that information to it. To do that, we need to create some new REST endpoints for the React app to access. These endpoints, when accessed, will send a response filled with our open and reviewed issues. Let's go ahead and make those changes.

Open the "IssueTracker/src/main/java/com/triippztech/web/rest/IssueResource.java" file and add the following code.

    @GetMapping("/openissues")
    public ResponseEntity<List<Issue>> getOpenIssues() {
        log.debug("REST request to get all open Issues");
        List<Issue> entityList = issueService.findAllOpenIssues();
        return ResponseEntity.ok().body(entityList);
    }

    @GetMapping("/reviewedissues")
    public ResponseEntity<List<Issue>> getReviewedIssues() {
        log.debug("REST request to get all open Issues");
        List<Issue> entityList = issueService.findAllReviewedIssues();
        return ResponseEntity.ok().body(entityList);
    }

As you can see we added 2 new enpoints

/openissues

and

/reviewedissues

We will come back to these two endpoints more in the next post.

Next, we need to make a change to our model classes.

Cascading Deletes

One thing you will want to keep in mind when dealing with relationships in jHipster is what you want to do when you delete related child tables. In our tutorial here we have the following relationship.

Issue       1-many        Comment

In other words, each issue can have many comments, but each comment can only belong to ONE issue. This allows us to have a bunch of comments on each of our issues. There is one issue though, what happens if we delete an issue? Will those comments persist in the database even with no parent Issue? The answer is yes. JHipster does not infer what we want to do with data, which is good, so we need to add some logic to handle deleting comments when an issue is deleted.

Head over to "IssueTracker/src/main/java/com/triippztech/domain/Issue.java". Jump down to

    @OneToMany(mappedBy = "issue")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<Comment> comments = new HashSet<>();

There is where the relationship is defined. We need to add some parameters to the relationship Tag to tell our app what to do when an Issue is deleted. Add the following to the @OneToMany tag.

    @OneToMany(mappedBy = "issue", CascadeType.REMOVE)

Unit Testing

JHipster provides us with a full set of basic unit tests for our Java and React apps for all entities, endpoints, etc. added through the jHipster generator. Since your services will need to be explicitly defined code, you must also create your own tests for your services. Also, if we create our own endpoints, as we have here, we will need to add our own tests. If you are unfamiliar with JUnit, its quite simple and I recommend you use it for all of your projects if you have not already.


Conclusion

Now that we have our backend setup, we now want to get our visual dopamine hit from our UI. In our next tutorial, I will cover the basics of how to get our React App synced up with our backend with some added customizations.

If you have any questions or comments, please feel free to drop a comment or join our Discord.

Stay tuned for Part 2!

Introduction to jHipster (ReactJs Version)

IntroductionIf you're like me and many others, you hate the tedious hassle of creating projects from scratch. It takes so much time and effort just to...

Build an issue tracker with jHipster (part 2)

Introduction Welcome back! This is the second part of our JHipster tutorial. We will be working on our frontend portion of our PWA. We will be...

Triippz Tech   Never miss a story from Triippz Tech, get updates in your inbox.