DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How Spring Boot Starters Integrate With Your Project
  • Integrate Spring With Open AI
  • Spring Boot: User Login API Test Client Using Rest Assured
  • Spring Boot Delete User Details API Test Client Using Rest Assured | API Testing Using Rest Assured

Trending

  • *You* Can Shape Trend Reports: Join DZone's Software Supply Chain Security Research
  • Segmentation Violation and How Rust Helps Overcome It
  • Chaos Engineering for Microservices
  • Zero Trust for AWS NLBs: Why It Matters and How to Do It
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring Boot: API First Approach

Spring Boot: API First Approach

I describe how I created the API definition, then how I created the server and client code from the API definition. Then I will talk about some of the problems I faced.

By 
Amrut Prabhu user avatar
Amrut Prabhu
·
Mar. 21, 21 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
17.7K Views

Join the DZone community and get the full member experience.

Join For Free

In this blog, I take a practical approach to API first design with Open API 3 specification.

Firstly, I describe how I created the API definition, then how I created the server and the client code from the API definition. Then I will talk about some of the problems I faced.

Advantages of API First Approach

As we are adopting microservice-based architectures, API first approach has been gaining some traction. There are quite many advantages to using API first approach and I will discuss a few of them.

Clear Contract Definition

With API first approach, you can create a concrete contract with which you can set clear goals on what will be provided by your application. It also helps to decouple your implementation from the Interface you provide via the API.

Well Documented API

You follow well-structured documentation of the API you are providing and it helps stakeholders to have a clear understanding of the interface you are providing via your APIs in a human-readable format.

Promotes Development in Parallel

This is one of the advantages that I really love is that the producer and consumer of the API can work in parallel once you have the API definition in place. The Consumer can easily create mocks with the already agreed API contract and start their end of the development.

Let’s Get Started!

To start off, I went to https://editor.swagger.io/ and created my API definition. I used the Open API 3 specification to create the API definition. There are many other tools to create your API definition, but I choose this as I was familiar with creating Swagger API documentation in Java. I used this online editor as it provides an auto-complete feature (with ctrl + space) depending on the context you are in. This helped me a lot to create the API definition.

However, I am not a fluent API definition creator, So I learned the way to define the API using the petstore API definition example. 

To get started, I created a very minimal API definition in which I can create an account using a post request.

API Definition Code

Generating Code

With the API definition all set, let’s start with creating the server and client of the API. For this, I created a spring boot application which I created normally via https://start.spring.io. The only dependency I added here was spring-web .

Next, I used the Open API Generator Maven plugin to create the server and the client for me. Let’s see how to do that.

Server-side Code Generation

To create the server-side code from the API definition, I added the Open API generator plugin and provided it with the API definition file. Since I am creating a server based on spring, I provided a generation type spring, So that it knows it can use spring classes to create my server code. There are quite a few server code generators that you can find here. Now, let's look at what the plugin config looks like:

Server Plugin Config

Some of the customization options I used here were, which package name to use to create my API and model classes. There are quite a few other options you can specify. E.g., you can define what your model class names can be pre-appended with and you can find the various other options on their GitHub link.

Now, the code that gets generated from the plugin requires a few more dependencies for it to compile successfully. I exactly found the minimal set I needed and added the following dependencies.

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${springfox-version}</version>
</dependency>
<dependency>
    <groupId>org.openapitools</groupId>
    <artifactId>jackson-databind-nullable</artifactId>
    <version>${jackson-databind-nullable}</version>
</dependency>
<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>${swagger-annotations-version}</version>
</dependency>


Now comes the main part, i.e., generating the code. After building the code using mvn clean verify, there were a few classes that got generated.

Generated Classes

In the API package, there were two main interfaces, AccountApi and AccountApiDeligate . The AccountApi interface contains the actual definition of the API using @postmapping annotation and it also contains the required API documentation using spring swagger annotations. Its implementation class is AccountApiController which calls the delegated service.

The important interface for you is the AccountApiDelegate interface. This provides a delegate service pattern, which allows you to provide the implementation of what needs to be handled or done when the API is called. Here you put in your business logic that handles the request. Once you implement the service delegate, you are actually ready to serve requests.

That’s it, you are done with the server-side. Next, the Client.

Client Code Generation

For the client-side code generation, I use the same plugin, but this time with the generator name as java . 

Client Code Generation

I also provide some config properties, Like the library to use for making the rest client. Here I wanted it to use restemplate for making the calls to the server. There are quite a few options you can configure that you can find from their documentation here.

You would also require some more dependencies to help you compile the generated code. 

<dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>${gson.version}</version>
</dependency>
<dependency>
   <groupId>io.swagger.core.v3</groupId>
   <artifactId>swagger-annotations</artifactId>
   <version>${swagger-annotations-version}</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>${springfox-version}</version>
</dependency>
<dependency>
   <groupId>com.squareup.okhttp3</groupId>
   <artifactId>okhttp</artifactId>
   <version>${okhttp.version}</version>
</dependency>
<dependency>
   <groupId>com.google.code.findbugs</groupId>
   <artifactId>jsr305</artifactId>
   <version>${jsr305.version}</version>
</dependency>


Client Code Dependencies

After the code generation, You can find classes that provide you how to configure the client to talk to the server. It also provides some basic authentication, using bearer token or basic auth.

Now you need to create an instance/bean of the ApiClient . This contains the host config of the server you want to communicate. This is then used in the AccountApi class to help you make requests to the server. To make a request, you would only have to call the API function from the AccountApi class.

There we have it now. You have successfully generated the client code and you can now check the interaction between the client and the server.

Problems I Encountered

There are quite a few bugs in the latest version of the plugin that I was using (5.0.1).

  • For spring generator, there are some unused imports from spring data that get added by the generator while creating the controller. Hence you would have to add spring data dependency, Even if you not using a database with the service. This may not be a big problem, because mostly you would have a database that you connect to with your service. You can check the current open bug here.
  • Usually, you would define the schema for request and response in the components section of the API definition file and then use the reference to these schemas in the API using the $ref: property. This is currently not working as excepted. The way to get around it was to define the inline schema for each request and response. Hence the model names get generated with a prefix Inline* . You can track this bug here.

If you use the older version, i.e, 4.3.1 ; it's free from these bugs and the plugin works well as expected. 

As usual, I have uploaded the code to GitHub. Enjoy!!

API Spring Framework Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • How Spring Boot Starters Integrate With Your Project
  • Integrate Spring With Open AI
  • Spring Boot: User Login API Test Client Using Rest Assured
  • Spring Boot Delete User Details API Test Client Using Rest Assured | API Testing Using Rest Assured

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!