Skip to content

Development Guide Backend

Simon edited this page Jun 10, 2019 · 1 revision

The backend is a Java Spring Boot Application and makes use of MongoDB for persistence and Docker.

Setting up your development environment

To start developing you need to install the following applications:

  1. Git
  2. Docker
  3. Java Development Kit 8+ (Oracle or OpenJDK is recommended)
  4. Apache Maven

It is also recommended to use one of the following IDEs:

  1. IntelliJ IDEA (I use the Ultimate version for better Spring support, but the free Community version should be fine)
  2. Visual Studio Code (I recommend reading this guide and installing Spring Tools for VSCode)
  3. Eclipse (I recommend installing Spring Tools 4 for Eclipse

Use whatever works best for you, as far as I'm concerned you can use Notepad and javac as long as you write good code :) However since I use IntelliJ IDEA Ultimate the following explanations may not be suitable for your needs. Most of the functionality should be in the other IDEs, however if that's not the case just give me a heads up so we can complete this guide together.

Once you installed the necessary applications and the IDE of your choice it's time to set up my source code.

Use git to pull the latest version of my source code:

git pull https://github.com/grimsi/accservermanager.git

or use your IDE:

Once you cloned the repository, open the project in your IDE. You should see a directory tree similiar to this:

We will discuss the names of the folders and the location of the files later. Let's set up our IDE so you can run and debug my application:

Setting up Java and Maven

Since we will use Java to write this application we need to tell our IDE that it should use the correct JDK. Go to "File" -> "Project Structure" and select "Project" on the lefthand side. If your JDK is detected correctly it should look like this:

To test if Maven works just enter the following command into the Terminal (make sure your current working directory is the root directory of the project):

mvn clean install

This may take a while but it should finish with "BUILD SUCCESS." and create a new directory "target" in the project root directory.

Creating Run and Debug configurations

The best way to start the application is by using a so called "Run configuration". Create a new Run Configuration of the type "Spring Boot" and enter the following values:

Main class: grimsi.accservermanager.backend.ACCServerManager

Environment variables:

The important options here are "folder-path" (which you have to set to your value, not mine) and "active-profile" (you can make a second Run configuration without this property to test how the application works in a production environment)

Save this configuration. You can now start the application by selecting the Run configuration and clicking the "Start" or "Debug" button. Setting the active Spring profile to "dev" makes the application use an embedded MongoDB instance instead of a full installation. This is very useful for developing since no values are persisted between restarts and you dont need to install MongoDB just to write code. However if you want to perform integration tests you have remove the "active-profile" parameter from the Run configuration or create a second Run configuration without this parameter.

Source code

Here I want to explain where certain classes are located and how the code works in general.

Misc

Please use a code formatting plugin like "Save Actions" (for IntelliJ IDEA). New code should always follow the Google Guidelines for Java Code. Please comment code wherever necessaty (more often is better than not often enough). Please write unit tests for new code (I'm currently working on writing unit tests for my old code) since I will check the code with SONAR cloud before every release. Use JUnit for unit tests.

Basic structure

The source code is located under "src/main/java/grimsi.accservermanager.backend" while the source code for tests is located under "src/test/java/grimsi.accservermanager.backend".

Resources

In the main and test source code directory you will also find a subdirectory called "resources". This folder contains configuration files for the application (all files that end with ".properties"). The resource files are in "key=value" format.

The main resource directory also contains a "public" folder. In this folder you can find the compiled frontend which will be delivered to the clients webbrowser. So when you build a new frontend version and want to include it in the server manager, this is the place to move it to.

Java Source Code

Main class

The main class is "ACCServerManager.class". It only contains minimal code needed to start the application, so this file should never be modified (except if there is a valid reason). Most of the logic is contained in the @SpringBootApplication and @EnableConfigurationProperties annotations, the rest is just executing the startup service and initialising the application.

Package "annotations"

Here you will find the classes used to define custom annotations, mostly custom validation used in the DTOs. The annotations are interfaces that are implemented by the classes in the "validators" package (more on that later).

Package "api"

This package contains classes related to the structure of the REST-API. Each REST-Endpoint has its own interface in there. If you create a new endpoint, make sure you annotate the interface with @Requestmapping('/v1/<endpoint_name_here>') and every method with either @DeleteMapping, @PutMapping, @PostMapping or @GetMapping depending on the allowed HTTP-method.

Package "configuration"

This package contains classes related to the configuration of the application.

Class Function
ApplicationConfiguration Contains parameters accessible in the 'application.properties' file. If you add new parameters to the property file, make sure to also add them to this class.
ErrorResponseConfiguration Responsible for the structure of error messages delivered to the client. This makes sure that no sensible information (e.g. logs or stack traces) are sent to the client by accident.
FrontendConfiguration Tells the backend which files belong to the frontend. Is responsible to redirect all unknown paths to the frontend main page.
RFC3339DateFormat Contains the date format used by the backend. Automatically generated by swagger.

Package "controller"

This package contains all classes that implement the interfaces from the "api" package. Make sure to annotate new classes with @Controller so Spring knows to load them into the application. Also try to keep the classes as short as possible and move the business logic into the "service" package so it is easier to find and reuse. Ideally each method should only contain one method call to a service class and a return statement.

Package "dto"

This package contains all data transfer objects. Make sure that new DTO classes don't contain any business logic. This application uses Lombok so instead of writing all getters/setters or the constructor you just annotate the class with

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor

and Lombok will take care of generating the boilerplate code at compile time. This makes the code easier to maintain and read. Please make sure that all properties are validated using the correct annotations. Take a look at the classes to view how I did it.

Package "entity"

This package contains all entities that are stored in the database. Usually they contain the exact same properties as the corresponding DTOs although that may not be the case for all of them. Again, just use the Lombok annotations here, it saves you work and makes the code cleaner. Please don't include validation here, it's enough when the DTOs are validated. Use @DBRef when you want to link entities from different documents (mongo is not a relational database) and Spring will take care of it when serializing/deserializing the instances.

Package "enums"

This package contains all enums. Try to create a enum class whenever possible even if it's more work than just using primitives. It will make the code easier to understand and more maintainable. You can even use more complex enums like I did with the "CarModel".

Package "error"

Currently only contains the class that defines the format for errors returned to the clients.

Package "exception"

Contains custom exceptions. Needs a refactor since I created too many different exceptions. I want to group the exceptions by HTTP response status instead of reason (since many of them share the same response status just with different payload which adds a lot of boilerplate code).

Package "filter"

Currently only contains the class that sets the correct CORS headers. Automatically generated by swagger.

Package "repository"

This is where Spring Data comes into play. This package contains one repository class for each document in the database (comparable to a table in SQL). The methods are automatically generated by Spring according to their names so you dont need to implement any logic here. If you create a new repository make sure the corresponding entity class is annotated with @Document("<document_name_here>'). More info here.

Package "security"

This package contains classes related to the security of the application. Most of them make use of Spring Security. The JWT classes implement the JSON Web Token funcionality while the SecurityConfiguration manages which URL paths are only available after a successful login. UserPrincipal currently contains a basic implementation of a permission system but it will be extended later on.

Package "service"

This is probably the most important package since it contains most of the business logic. Each service only has one task, but the classes can still get pretty big.

Class Function
ContainerService Contains funcionality to manage the docker containers with the ACC server instances.
EntryListService Contains logic related to persisting and retreiving the EntryLists.
EventService Contains logic related to persisting and retreiving the Events.
FileSystemService Contains logic related to the filesystem (creating and deleting folders and files related to instances).
InfoService Contains logic related to system information retrieval.
InstanceService Contains logic related to persisting, managing and retrieving instances.
JsonSchemaService Contains logic related to generating the JSON schemas.
StartUp Service Handles the application start (pulls docker images, restores deleted containers and folders if necessary).
UserService Contains logic related to users and authentication.
UtilityService Contains helper methods that can be used in all other classes but dont really fit in a specific class.

Package "validators"

This package contains the implementations for the custom annotations. Each annotation should have one validation class that implements it.