Tag Archives: spring-boot

Using Java Flight Recorder to Profile Spring Boot applications

Few months back I had to do performance optimisation of a low latency application. The tool that helped me a lot was Java Flight Recorder. Today, I had to do some similar work and I completely forgot how I was able to launch flight recorder GUI. In this short post, I will show you the process that I followed to create flight recorder recordings.

From the official documentation,

Java Flight Recorder (JFR) is a tool for collecting diagnostic and profiling data about a running Java application. It is integrated into the Java Virtual Machine (JVM) and causes almost no performance overhead, so it can be used even in heavily loaded production environments. When default settings are used, both internal testing and customer feedback indicate that performance impact is less than one percent. For some applications, it can be significantly lower. However, for short-running applications (which are not the kind of applications running in production environments), relative startup and warmup times can be larger, which might impact the performance by more than one percent. JFR collects data about the JVM as well as the Java application running on it.

Continue reading

The Ultimate Dockerfile for Spring Boot Maven and Gradle applications

For Maven users, the ultimate Dockerfile is below.

FROM openjdk:8-jdk-alpine as build
WORKDIR /workspace/app

COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
RUN ./mvnw dependency:go-offline

COPY src src
RUN ./mvnw package -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","FULL_NAME_OF_SPRING_BOOT_MAIN_CLASS"]

Please make sure to update FULL_NAME_OF_SPRING_BOOT_MAIN_CLASS with Spring Boot application main class.

For Gradle users, the ultimate Dockerfile is below.

FROM openjdk:8-jdk-alpine as build
WORKDIR /workspace/app

COPY gradlew .
COPY gradle gradle
COPY build.gradle .
RUN ./gradlew dependencies

COPY src src
RUN ./gradlew build unpack -x test
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)

FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","FULL_NAME_OF_SPRING_BOOT_MAIN_CLASS"]

Please make sure to update FULL_NAME_OF_SPRING_BOOT_MAIN_CLASS with Spring Boot application main class.

You can watch this video to learn more about optimizing docker images for Spring Boot applications.

Solution: ORA-12514, TNS:listener does not currently know of service requested in connect descriptor

Today, one of the teams was facing the issue ORA-12514, TNS:listener does not currently know of service requested in connect descriptor. They were trying to connect to Oracle using Spring Boot JPA application and getting the exception at application boot up.

Team was able to successfully connect to Oracle using SQLDeveloper. But, when connecting to Oracle using Spring Boot JPA application it was failing to boot up.

Like most developers, we googled around to find the answers. The popular answer that you will get is as mentioned in this stackoverflow question. The answer suggests that you have to update tnsnames.ora file and add your service to it.

I knew it is not the right answer as we are able to connect using SQL Developer.

So, I started looking into the Spring Data JPA configuration of the application. The configuration that was giving error is shown below.

spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@//myhost:1521/efsdev
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect

In the above configuration, there is only one configuration property that could be possibly wrong — spring.datasource.url.

So, I googled around to find the correct way to specify JDBC url for Oracle.

I learned that there are two ways you can specify JDBC string URL. The two ways are:

1) jdbc:oracle:thin:@[HOST][:PORT]:SID

2) jdbc:oracle:thin:@//[HOST][:PORT]/SERVICE

As you can see above, we are using the second way to specify the URL. According to second URL syntax, efsdev is the service name.

Developers mentioned that efsdev is the SID. So, we need to use the first URL.

After changing the configuration to the one mentioned below, application was successfully able to connect with Oracle.

spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@myhost:1521:efsdev
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect

That’s it for this post. I hope this saves someone’s day.

Enabling Https for local Spring Boot development with mkcert

Today, I discovered mkcert – a tool that generates valid TLS certificate. It works for any hostname or IP, including localhost. In this post, I will show you how to generate a valid PKCS12 format certificate using mkcert. Then, we will use that certificate in a Spring boot application.

We will start by installing mkcert on our local machine. If you are using Mac then we can use brew package manager. For installation instructions specific to your OS you can refer to the documentation.

brew install mkcert

Once mkcert is installed, you can use its CLI to create and install a CA. To do that, run the following command.

mkcert -install

Continue reading

Getting started with Apache Dubbo and Spring Boot

This week I decided to play with Apache Dubbo. I follow Github trending repositories daily and for many weeks and months Apache Dubbo is one of their popular Github Java repository. It has more than 20,000 stars. So, I decided to give it a shot. One of the reasons for Dubbo popularity is that it is created by software engineers at Alibaba. Alibaba is a Chinese multinational conglomerate specializing in e-commerce, retail, Internet, AI and technology.

From its website, Apache Dubbo is

A high-performance, light weight, java based RPC framework. Dubbo offers three key functionalities:

  1. Interface based remote call
  2. Fault tolerance and load balancing

  3. Automatic service registration & discovery

Continue reading

Configuring Spring Cache Manager with AWS ElastiCache Redis (cluster mode disabled) and Lettuce

We have Spring Boot 2 application that uses Redis as the cache manager. We deploy our application on Amazon AWS where we use AWS ElastiCache Redis service in cluster mode disabled. Our setup includes a Redis master with two Redis slaves. The default Java client for Redis with spring-boot-starter-data-redis dependency is lettuce-core. When you are working with single Redis node with no slaves, using AWS Elastic Cache Redis is as simple as providing the spring.redis.url with the value of AWS ElastiCache Redis instance URL. This was the set up that we were using till a month back. As the load on the system increased we decided to use ElastiCache Redis in replicated setup to scale our reads. In AWS, Redis implements replication in two ways:

  1. With a single shard that contains all of the cluster’s data in each node – Redis (cluster mode disabled)
  2. With data partitioned across up to 15 shards — Redis (cluster mode enabled)

In our case, cached data is less than 1 GB so it fits in RAM of single node. This made us choose cluster mode disabled setup.

Continue reading

TIL #3: Exclude null fields in Spring Boot REST JSON API, Serializing Enum value with Jackson, and Change remote for a branch in Git

The three things that I learned today are mentioned below.

Learning 1: Exclude null fields in Spring Boot REST JSON API response

Spring Boot uses Jackson to convert to JSON. Spring Boot allows you to configure through a configuration property whether you want to include null values or not. By default, serialised JSON will include null values as well. To remove null values, you should use following property add it to your application.properties.

spring.jackson.default-property-inclusion=NON_NULL

If you are using Java 8 or Google’s Gauva and want to exclude Optional type as well then you should use NON_ABSENT value.

spring.jackson.default-property-inclusion=NON_ABSENT

To learn about all the values, you should look at Jackson’s com.fasterxml.jackson.annotation.JsonInclude.Include enumeration.

Learning 2: Serializing Enum value with Jackson

The second learning that I had today was around how to properly serialize enum values in Jackson. I had enum shown below

public enum Status {
    SUCCESS("success"), ERROR("error");

    private final String status;

    Status(String status) {
        this.status = status;
    }
}

I wanted my JSON structure to be as shown below.

{
  "status": "success"
}

To achieve that you have to Jackson’s @JsonCreator and @JsonValue annotation as shown below.

public enum Status {
    SUCCESS("success"), ERROR("error");

    private final String status;

    @JsonCreator
    Status(String status) {
        this.status = status;
    }

    @JsonValue
    public String getStatus() {
        return this.status;
    }
}

Learning 3: Change remote of a branch in Git

$ git branch develop --set-upstream-to=upstream/develop

You can view remote tracked by local branch using the following command.

$ git branch -lvv