Tag Archives: Spring Boot

Apache Camel OpenAPI Contract-First Example in SpringBoot

Contract-First means what the name implies that we write the contract between client and server first and implement the code for it after. This is a good way to break up the task of creating an API in smaller parts which can be handled over multiple professions. For example, the OpenAPI specification can be created by an IT-architect and the implementation can be done by a programmer, and lastly the API documentation can be carried out by an communications expert.

In this article I’m going to build a simple OpenAPI implementation in Apache Camel and it’s rest-openapi component in a SpringBoot application.

1. We start with the API Specification:

openapi: 3.0.3
info:
  title: Basic API
  version: "1.0"
paths:
  /test:
    get:
      operationId: test
      responses:
        200:
          description: Default response
  /user/{userId}:
    get:
      operationId: getUser
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Default response

A few things to note here:
/test – this is the url that the client will use
operationId for the test endpoint – is the route that will receive the call from url above
/user/{userId} – url with parameter that the client will use
operationId – here the operationId does not match the url, which is fine. The call will go to the route direct:getUser with the userId in a header on the message seen below

2. Implementation of the Camel solution

package com.example.contract_first_example;


import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;


/**
 * A Camel Java DSL Router for Contract First Example
 */
@Component
public class MyApp extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        rest().openApi().specification("hello-rest-service.yaml");

        from("direct://hello")
            .setBody().constant("Hello from Camel!");

        from("direct://getUser")
            .process(exchange -> {
                exchange.getMessage().setBody("Hello from user: " 
                             + exchange.getMessage().getHeader("userId"));
            });
    }
}

3. Now the implementation is done and we move on to testing:

PS C:\Users\niklas> curl -XGET localhost:8080/hello
Hello from Camel!
PS C:\Users\niklas> curl -XGET localhost:8080/user/11
Hello from user: 11

And that is all there is – pretty simple, like most things in the Camel world 😉

Tested on Java 17, OpenAPI 3.0, Apache Camel 4.9.0 and SpringBoot 3.3.4 in a Windows 10 environment

Spring Boot: Map JSON body with root node in @RequestBody

Say you have the following JSON:

{
  "rootNode": {
    "firstValue":"",
    "secondValue":""
  }
}

The class to use for this could look something like this:

public class MyValues {
  private String firstValue;
  private String secondValue;
  ...
}

This class will however not map directly to the JSON above via @RequestBody, and this is because the JSON contains a root node (“rootNode”)

The solution here is to wrap the MyValues class into a “root class” like this:

public class MyValuesWrapper {
  MyValues rootNode;
  ...
}

After this you should be able to parse the request body automatically with @ResponseBody like this:

 @PostMapping(value = "/myValues")
  public int postValues(@RequestBody MyValuesWrapper wrappedRequest) {
  
  // Optional: Unwrap for easier access
  MyValues request = wrappedRequest.getMyValues();
  ...

Hope this helps somebody (or me in the future 🙂 )

Tested on Spring Boot v2.3.8 and Java 11

Spring Boot: Create a “RunAllTests” test class with JUnit 5

I like having an easy way to run all tests in a specific package path. I will here show an example of how to create a “RunAllTests” class to use in Spring Boot 2 and JUnit 5 (Jupiter):

package com.niklasottosson.myapp;

import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.runner.RunWith;

/**
 * Test class to run all unit tests.
 */
@RunWith(JUnitPlatform.class)
@SelectPackages("com.niklasottosson.myapp.tests")
public class RunAllTests {
}

This will tell JUnit to search the files in the package described (and below) in the @SelectPackages annotation for tests to run

For Spring Boot 2.3.8 the normal “spring-boot-starter-test” dependency was not enough to get the JUnitPlatform into my app (for the @RunWith annotation), so I had to add the following dependency to my pom.xml:

        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <version>1.2.0</version>
            <scope>test</scope>
        </dependency>

After all is in place I can run the RunAllUnitTests class and all selected tests runs

Tested on Spring Boot v2.3.8, IntelliJ v2020.3 and JUnit v5 with JUnitPlattform v1.2.0