New Book Day: Modern API Development with Spring 6 and Spring Boot 3

The holiday season is close and it is time to resume and enhance my reading backlog. I wanted to get a break from infrastructure related topics and revisit some of my Spring REST API days.
I picked this book and it is a real treat. It focuses mainly on REST APIs but includes GRPC as well as GraphQL.
Obviously APIs are not anymore a hot topic but an essential topic. Unless you live under a rock, your daily work includes integrating with an API or involves something that integrates with an API.
You start with designing a REST API using the OpenAPI specification and then work towards the implementation of the REST API.
Then the book proceeds smoothly on consuming the API by implementing a front-end application, testing the API, containerising it, deploying it as well as monitoring it. This gives an end-to-end experience on implementing REST APIs with Spring.

As expected the essential topics such as security, JWT, HateOAS, database integrations, REST API best practices, testing and deploying to prod are covered. While going through the topics, I liked the opportunities the author gave to get back to the basics. There is a focus on designing REST APIs but for each technical aspect involved there is a deep dive like learning more on Spring, IoC containers, annotations, configuration modularisation, JPA as well as key components of Spring that help towards a REST API implementation.
Apart from that the book does not stick only to REST API implementation thus GraphQL and gRPC are also included.

For me a winner is the extras that come with the book
For example you get to use project Reactor and Webflux. Flyway for DB migrations is also included. Monitoring using the ELK stack is also included. Let alone that you get to integrate with Kubernetes using minikube.
Overall this book is complete and whether you are a seasoned professional or you get started with APIs in Spring, it’s a solid source of information.

In the next version it would be awesome to see topics such as rate limiting, mTLS, rest client implementation practises and a TDD approach on the examples.

Shoutout to Sourabh Sharma. Thank you for this book!

Aspect Oriented Programming with Spring Boot

On a previous post I provided a simple example on how to achieve aspect orientation in spring by using a ProxyFactoryBean and implementing the MethodBeforeAdvice interface.

On this example we will learn how to achieve aspect orientation by using Spring boot and Aspect4j annotations.

Let’s start with our gradle file.

group 'com.gkatzioura'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'

sourceCompatibility = 1.8

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-jetty")
    compile("org.slf4j:slf4j-api:1.6.6")
    compile("ch.qos.logback:logback-classic:1.0.13")
    compile("org.aspectj:aspectjweaver:1.8.8")
    testCompile("junit:junit:4.11")
}

Apart from the spring boot plugins we have to include the aspectjweaver package.

The application class

package com.gkatzioura.spring.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

/**
 * Created by gkatzioura on 5/28/16.
 */
@SpringBootApplication
public class Application {

    public static void main(String[] args) {

        SpringApplication springApplication = new SpringApplication();
        ApplicationContext applicationContext = springApplication.run(Application.class,args);
    }
}

We will implement a service the will fetch a sample for the name specified.

The sample model would be a simple pojo

package com.gkatzioura.spring.aop.model;

/**
 * Created by gkatzioura on 5/28/16.
 */
public class Sample {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

The service will create a sample object.

package com.gkatzioura.spring.aop.service;

import com.gkatzioura.spring.aop.model.Sample;
import org.springframework.stereotype.Service;

/**
 * Created by gkatzioura on 5/28/16.
 */
@Service
public class SampleService {

    public Sample createSample(String sampleName) {

        Sample sample = new Sample();
        sample.setName(sampleName);

        return sample;
    }
}

So far so good.
Suppose that we want to do some actions before and after creating a sample. AOP in spring can help us to do so.
The createSample function is a JoinPoint
The main concept is to work with Advices. From the documentation advice is an action taken by an aspect at a particular join point.

In our case we want to do some extra logging before the sample gets created.
Therefore we will use the Before advice type.

package com.gkatzioura.spring.aop.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * Created by gkatzioura on 5/28/16.
 */
@Aspect
@Component
public class SampleServiceAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(SampleServiceAspect.class);

    @Before("execution(* com.gkatzioura.spring.aop.service.SampleService.createSample (java.lang.String)) && args(sampleName)")
    public void beforeSampleCreation(String sampleName) {

        LOGGER.info("A request was issued for a sample name: "+sampleName);
    }

}

We implemented a function with the @Before annotation. The argument that we provide to the annotation is a pointcut expression. Pointcut expressions assist us in defining the function, that will trigger our advice and the function arguments that should be used.

Therefore before the method createSample gets executed a log message should be displayed on our screen.

Suppose that we want to have more action before and after the method gets executed, or even change the outcome of the createSample function, we can use an @Around Advice.

package com.gkatzioura.spring.aop.aspect;

import com.gkatzioura.spring.aop.model.Sample;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * Created by gkatzioura on 5/28/16.
 */
@Aspect
@Component
public class SampleServiceAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(SampleServiceAspect.class);

    @Before("execution(* com.gkatzioura.spring.aop.service.SampleService.createSample (java.lang.String)) && args(sampleName)")
    public void beforeSampleCreation(String sampleName) {

        LOGGER.info("A request was issued for a sample name: "+sampleName);
    }

    @Around("execution(* com.gkatzioura.spring.aop.service.SampleService.createSample (java.lang.String)) && args(sampleName)")
    public Object aroundSampleCreation(ProceedingJoinPoint proceedingJoinPoint,String sampleName) throws Throwable {

        LOGGER.info("A request was issued for a sample name: "+sampleName);

        sampleName = sampleName+"!";

        Sample sample = (Sample) proceedingJoinPoint.proceed(new Object[] {sampleName});
        sample.setName(sample.getName().toUpperCase());

        return sample;
    }

}

As we can see the aroundSampleCreation Advice, changes the input and also changes the outcome.
You can find the source code on github