Spring Boot 3.0 and PostgreSQL Java19 Using Record with PageResponse
Tags: springboot, postgres, recordjava, java19
Published: 2022-11-28 17:15:42

**Introduction**

Spring is one of the most widely used Java-based frameworks for enterprise application development.

The Spring Framework provides a broad and complete ecosystem of projects that encompasses several points that can help create applications, some of which are:

**Spring Data**: Simplifies access to relational data and NoSQL data stores

**Spring Batch**: Provides a powerful batch processing framework

**Spring Security**: Robust security framework to protect applications

**Spring Cloud**: Provides a set of tools for developers to implement common distributed system patterns such as Service Discovery, Configuration Management, Circuit Breaker, and more.

**Spring Integration**: An implementation of enterprise integration standards to facilitate integration with other enterprise applications using lightweight messaging and declarative adapters

**Spring Boot Actuator**: Getting the various details of an application running in production is crucial for many forms.

Spring is a very flexible and also customizable framework, having many ways to configure an application.

Although they have these facilities and many options, it can be a bit complex for developers who are in their first steps and who sometimes do not have specific skills in Object Oriented Programming.

Spring Boot comes to ease this problem of “Spring applications need complex configuration” that Spring Boot has powerful autoconfiguration mechanisms.

**In this Article we will use as Tools:**

- Java 19
- springboot
- maven
- docker-compose

**Maven Dependencies:**

- Lombok
- PostgreSQL Driver
- spring web
- Spring Data JPA
- Spring Configuration Processor

**Database server:**

- PostgreSQL v.15

**IDE:**

- IntelliJ IDEA

To start, we will use [https://start.spring.io/](https://start.spring.io/) to help you create the initial Project, below is an image of how the project will be started:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3pjj8wz02qxmz9pnuep.png)

**Java Release**

[https://www.oracle.com/br/news/announcement/oracle-releases-java-19-2022-09-20/](https://www.oracle.com/br/news/announcement/oracle-releases-java-19-2022-09-20/), (09-20-2022), Download [https://www. oracle.com/br/java/technologies/downloads/](https://www. oracle.com/br/java/technologies/downloads/).

In this new version, it offers seven proposals for improving the JDK to increase developer productivity, improve the Java language with performance, stability and platform security.

JDK 19 features language improvements from the OpenJDK Amber project (Record Patterns and Pattern Matching for Switch); library for interoperating with non-Java code (Foreign Function and Memory API) and boosting vector instructions (Vector API) from the OpenJDK Project Panama; and the first views of Project Loom (Virtual Threads and Structured Concurrency), which will dramatically reduce the effort required to write and maintain concurrent high-performance Java applications.

**Record type:**

This language feature first appeared in version 14 [https://openjdk.org/jeps/359](https://openjdk.org/jeps/359) as experimental and continued until version 15 [https://openjdk.org/jeps/384](https://openjdk.org/jeps/384).

Definitively released in Java 16 [https://openjdk.org/jeps/395](https://openjdk.org/jeps/395).

A Record is nothing more than a type of class that stores data. It's the same idea of construction similar to a JavaBean, it has a constructor, attributes and accessor methods. However, it makes it impossible to change the class because it is immutable. The Record Type has the equals, hashCode and toString() methods.

What about the equals, hashCode and toString methods, do I have to declare them? Methods in Records are automatically generated for us, so there is no need to use libraries that do this work, one of the most used being, for example, Lombok.

**However, the Record Type has some restrictions regarding this type of class:**

- A Record class does not have an extends clause
- A Record class cannot be abstract
- Attributes derived from the Record class are all final
- Cannot declare instance fields
- Cannot declare native methods
- Aside from the above restrictions, a registration class 

**behaves like a normal class:**

- An instance of Record is created with the expression new
- Can be declared as a generic type
- Can declare static methods, attributes, and initializers
- Can declare instance methods
- Can implement interfaces
- use annotations
- Can be serialized and deserialized

All classes of type Record extend from the abstract class java.lang.Record

Records are a concise representation of the immutable data class.

Before Records, this is how we usually created an immutable class.

**Using Records in SpringBoot 3**

[https://spring.io/blog/2022/11/24/spring-boot-3-0-goes-ga](https://spring.io/blog/2022/11/24/spring-boot-3-0-goes-ga),

Result of 12 months of work and more than 5700 commits from 151 different individuals. Where many contributed and to all early adopters who provided vital feedback on the milestones.

What is striking about this release is that it is part of a major overhaul of Spring Boot since version 2.0 was released 4.5 years ago. It is also the first Spring Boot GA release that provides support for Spring Framework 6.0 and GraalVM.

**Highlights of the new release include:**

- baselining for Java 17
- Support for native imaging with GraalVM, replacing the experimental Spring Native project
- Improved Observability with Micrometer and Micrometer Tracing
- Support for Jakarta EE 10 with an EE 9

But what was it like before the inclusion of Records in Java?


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/boo173lj4cds9x7w5ex6.png)

**Changing the code to use Records, just declare:**

```
public record User(String name, String password){}
```

Given the context of immutability, there is only one constructor with all attributes. There are also no setter methods.

```
User user = new User("root", "YzxNAws*");
```

Another difference between the first design and this one using records is that the accessor methods don't use the terminology with “get” just the attribute name itself, that is, instead of getName(), just name();

```
String name = user.name();
```

**Using Change in an Application:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l6cyagziiuv0zjutgvif.png)


**Changing the class to type Record:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lgosuml3b470gx949fy.png)

**Http Request/Response (Springboot3)**

We typically create DTO classes with setters and getters to bind the incoming HTTP request payload because frameworks need a way to bind the request payload to the properties of the class.

SpringBoot by default uses the Jackson library to convert request/response payloads to/from JSON and Jackson 2.12 introduced support for records. So we can use records to bind incoming request payloads and also return records as response.

Here is a record with bean validation restrictions applied:

**Using DTO(Data Transport Object):**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/el76pkx35cs43n9c07b0.png)


Http request/response fetching book by id and Return Using created DTO.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4stuz20se2oniz8r7ohl.png)


The application can be found on github [model project](https://github.com/weder96/spring-boot-jpa-demo-java19)

**How to run code from Github?**

Download the Project, open it in your preferred IDE.

The project is configured to create the data in a Postgres database, which has been configured to push using docker-compose

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2yms5o2flwyli6vabqr.png)

```
 docker-compose -f docker-compose.yml up

```

**With the database created:**

```
mvn spring-boot:run
```

In the document folder, the json with all the calls via postman:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i7ek9yqlhwuvhl9ph12o.png)

**Conclusion**

If we analyze that the Record type, has a simpler syntax due to the code generated, they can be useful in projects that are not using lombok, however if we analyze the OOP (Object Oriented Programming) issues coldly, the restrictions that can generate a discomfort for those who like to use OOP and restrictions deeply, leaves a gap in this context.

When I model objects that hold immutable data, the very concise syntax helps, however, in the general context, I didn't find an element that I liked, because there will be cases in which a regular class will be much more effective compared to Type Records.

**References:**

[https://openjdk.java.net/jeps/395](https://openjdk.java.net/jeps/395)

[https://www.baeldung.com/java-record-keyword](https://www.baeldung.com/java-record-keyword)

[https://angiejones.tech/deserializing-api-responses-into-java-records/](https://angiejones.tech/deserializing-api-responses-into-java-records/)

[https://medium.com/@gaozhixiang/records-vs-lombok-in-java-15-193306340ca0](https://medium.com/@gaozhixiang/records-vs-lombok-in-java-15-193306340ca0)

[https://softwaregarden.dev/en/posts/new-java/records/vs-lombok/](https://softwaregarden.dev/en/posts/new-java/records/vs-lombok/)

[https://docs.oracle.com/en/java/javase/14/language/records.html](https://docs.oracle.com/en/java/javase/14/language/records.html)

[https://www.sivalabs.in/using-java-records-with-spring-boot-3/](https://www.sivalabs.in/using-java-records-with-spring-boot-3/)

[https://www.infoq.com/br/articles/records-no-java-14/](https://www.infoq.com/br/articles/records-no-java-14/)

[https://en.wikipedia.org/wiki/Plain_old_Java_object](https://en.wikipedia.org/wiki/Plain_old_Java_object)

[https://pt.wikipedia.org/wiki/Plain_Old_Java_Objects](https://pt.wikipedia.org/wiki/Plain_Old_Java_Objects)

[https://www.baeldung.com/java-dto-pattern](https://www.baeldung.com/java-dto-pattern)