How to make a Java Spring Boot project?

This article is aimed at novice Back-end programmers, in particular Java, because here will go through the process of planning and programming a server in Java Spring Boot with PostgreSQL database

Code repository

The subject of analysis will be my team project work for the 2nd year of the university:

application for creating and watching art house movies

The application was taken over by my partner, so I had no choice but to watch films provide it with a server


Planning

Having selected the main functionality, an MVP is born, the purpose of which is to determine the interest of users in such films

To meet these requirements, we decided to show the user the following screens:

  • registration / login

  • account page

  • film catalog

  • movie page with player

  • chat for discussion

And provide for the following interaction: adding movies to favorites, comments and likes / dislikes in comments

Then, together with a partner, we discussed:

  1. movie and user entities

  2. required entity queries

  3. security

Having said all this, I was eager to start creating the database architecture. This only required knowledge about the types of relationships between entities. [1:1, 1:N, M:N]

At the forefront are entities that are overgrown with all sorts of details.
At the forefront are entities that are overgrown with all sorts of details.
Each user is assigned rights and a role in the chat.

Programming

I’ll go through my code in chronological order

Project structure

TangoApplication

The entry point to the application. At the beginning there is nothing here, however, it is worth noting 1 curious detail: a lot in Spring Boot is done through annotations

@SpringBootApplicaion – annotation that is generated automatically and configures default settings

In addition to the main method In this class, you can define a commandLineRunner to do any actions when the server starts, in this case, the starting values ​​are thrown into the base there

@Bean – instructs Spring to take this method into account under the hood

@Transactional


Controllers

This is the API that a front-end specialist will communicate to through requests. Its functionality was determined at the planning stage.

The controller in the picture is the most common class, with a special annotation @RestController(path="api/common")

Within this class, methods are defined that can be accessed for a specific purpose, in slang they are called “pens”. To define a handle, a number of annotations are used for different types of queries: @GetMapping,@PostMapping etc

To use them correctly, you should look at the following topics:

  • request types

  • accepting arguments and request parameters

  • getting request body

A simple controller to return the entire list of genres, or tags, or roles

It is worth remembering that the specialist from the Front-end has not received anything yet. And this is not surprising, neither the database nor the entity was created, however, to create the functionality on its part, real data is not required

Fake data in the correct format is called a Mock. You can return a pre-generated object or, if the answer is not large, then fields in a similar form:

Map<String, Object> response = new HashMap<>();
response.put("message", "Test data");
response.put("number", 1)
return ResponseEntity.ok(response);

It is not difficult to make such stubs for at least some part of the API. By deploying the server, the Back-end and Front-end will become less dependent on each other. Slang: deployment == deploy

Let the API be known, however, the frontend will not go into the server code to find out the question: “How to use it?” It was convenient for us to keep the API in Postman, where I created a collection that contained requests with all the arguments and their body

An example of an API response to a request defined above in the article, in commonController

Models

Let’s move on to the most important thing, entities and databases

First of all, we connect to the database. We define the required fields in application.properties and then, using the Database tab on the right in IntelliJ, to the database itself. In the community version of IntelliJ, you will have to resort to the help of other articles / videos to solve this problem.

Here is everything you need to connect the database

The picture below shows the user entity

Some of the annotations here are from the Lombok library, which is designed to shorten the object’s code, thereby making it more readable

@Data – defines getter and setter for each entity, adds toString, equals, hashcode methods

@NoArgsConstructor – creates a constructor with no arguments

Time to figure out what’s going on here
К сущности:
@Entity — обозначается сущность
@Table — таблица
@Data @NoArgsConstructor — аннотации Lombok. Реализуют некоторые методы
@JsonIncude(JsonInclude.NON_NULL) — при сериализации в JSON попадают все поля, которые не NULL

К полю:
@JsonProperty(value="название") — при сериализации будет указывать тебе определённое имя 
@Column(name = "колонка") — нужно, чтобы задать название для колонки в базе данных
@Transient — означает, что это поле будет вычисляться во время запроса

К ID:
@Id, @SequenceGenerator, @GeneratedValue — нужно для того, чтобы создать ID

Отношения между сущностями:
@OneToOne, @ManyToOne, @OneToMany, @ManyToMany, 
@JsonBackReference, @JsonManagedReference 

About@JoinTable and relationships between entities are best read at Baeldung


How to write queries to a PostgreSQL database without SQL?

→ The modern approach to building queries to the database in Spring Boot is implemented through special classes – repositories

@Repository – indicates that this is a repository

@JpaRepository<сущность, тип_её_ID> – includes all prepared queries to address a specific entity

To create author’s queries, you need to name functions in a special format, or using annotation @Query write SQL

To do pagination, you need to use Page<сущность> – container for multiple instances of the entity and add to function arguments Pageable pageable


DTO

→ Data Transfer Object – needed to transfer entities reduced by fields within the server: operate with them in requests / receive from the database, etc.

Their use is due to the fact that the language is typed and it is impossible to remove a property from objects on the fly.

// Пример DTO: Тело запроса на регистрацию
@Data
public class SignupRequestDTO {
    private String email;
    private String username;
    private String password;
    private LocalDate date_of_birth;
    private LocalDate sub_deadline;
    private Set<String> roles;
    private String avatar;

    public User fromWithoutRoles() {
        return new User(email, username, password, date_of_birth, sub_deadline);
    }
}

Services

It is too cumbersome to write logic in controllers, so it was thrown into special classes with annotation @Service and from there they call the required method for a specific request

It is considered good practice to make an interface with the necessary methods next to the entity, and then implement this interface with the Impl postfix

@Autowired – this is one of the key concepts of Spring “Dependency Injection”: all these dependencies are registered inside Spring and then they can be inserted somewhere via annotation

Services use repositories, or older variations of logic for queries to the database


Tests

At one point, I felt that there is functionality that I do not want to test through requests. This thought became the starting point for writing tests.


Security

The topic of security is incredibly extensive and it is worth starting with the question: “What are the general possibilities of authentication?”

The github repository contains my version of the implementation of working with JWT, based on adding MiddleWare for authorization

MiddleWare is a function that requests are sent to before they end up in controllers, so it is convenient to put a check for a JWT token there.


Utils

→ Logic that is used in different places, but not directly related to entities

In the project, I brought out the internal logic for encrypting / decrypting the JWT token, functions for uploading pictures to Imgur


Where to keep secrets?

→ In the file application.properties

Constants are defined there, which can then be accessed through the annotation. @Value

Moreover, the server can start with certain arguments, which include values ​​for these very constants.

// Где-либо
@Value("${jwt.jwtSecret}")
private String jwtSecret;

@Value("${jwt.jwtExpirationMs}")
private int jwtExpirationMs;

// В application.properties
jwt.jwtSecret=секрет
jwt.jwtExpirationMs=86400000

Conclusion

The github repository contains code for a number of unaffected topics:

  1. Building a Front-end chat site using JS, CSS and HTML

  2. Chat on WebSocket from the browser side, which is true, I don’t really like it right now

  3. Security with JWT

  4. Custom error class

This was a general view of creating a small project from the Back-end.

Similar Posts

Leave a Reply Cancel reply