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
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • The Pros and Cons of API-Led Connectivity
  • 3 Reasons for the Mounting Demand for Smart Cloud-Native Application Development
  • Manage Microservices With Docker Compose
  • Split the Monolith: What, When, How

Trending

  • LLM Integration in Enterprise Applications: A Practical Guide
  • Self-Hosted Inference Doesn’t Have to Be a Nightmare: How to Use GPUStack
  • 11 Agentic Testing Tools to Know in 2026
  • Scaling Cloud Data Automation: A Practical Guide to Open Table Formats
  1. DZone
  2. Data Engineering
  3. Databases
  4. Get More Transparency on Your Microservices API With OpenAPI

Get More Transparency on Your Microservices API With OpenAPI

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Aug. 03, 20 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
7.2K Views

Join the DZone community and get the full member experience.

Join For Free

Every Friday, Platform.sh has a nice tech discussion about several discussions, such as Jakarta EE, Payara, Quarkus, and so on (To check the calendar you can click here). On Episode number 15 there was a great discussion about Open API and Postman. That's worth watching if you don't yet.

First, let's start with Open API definition, from the website it says:

The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to RESTful APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.

Hello World Open API With Postman

To absorb that knowledge and practice what we learned from this episode, let's create a Hello world Open API and then test it with Postman. We'll create a small Java API that will handle all Deploy-Fridays episodes and store it on MongoDB. Why do we want to use MongoDB? Just because we're hipsters!!

We're going to be using Eclipse MicroProfile. This will make our life easier when we want to create a microservices application. In this tutorial, we'll use Helidon version 2.0. To integrate with a NoSQL database let's use Jakarta NoSQL.

Eclipse MicroProfile has a subproject to integrate with Open API that's annotation-driven.

Annotation

Description

@APIResponses

A container for multiple responses from an API operation. This annotation is optional, but it can be helpful to organize a method with multiple responses.

@APIResponse

Describes a single response from an API operation.

@Content

Provides a schema and examples for a particular media type.

@Schema

Defines the input and output data types.

@Operation

Describes a single API operation on a path.

@Parameter

Describes a single operation parameter.


Let's start with the entities; remember that those entities will also be the data inputs, so we'll define them as a schema.

As you can see in the code, beyond the Eclipse MicroProfile Open API annotations, there are also the Jakarta NoSQL entities annotations and JSON Binding to check the fields instead of methods.

Java
xxxxxxxxxx
1
53
 
1
import jakarta.nosql.mapping.Column;
2
import jakarta.nosql.mapping.Entity;
3
import jakarta.nosql.mapping.Id;
4
import org.eclipse.microprofile.openapi.annotations.media.Schema;
5
6
import javax.json.bind.annotation.JsonbVisibility;
7
import java.util.Set;
8
9
@Schema(name = "Episode", description = "The entity that represents Episode")
10
@Entity
11
@JsonbVisibility(FieldVisibility.class)
12
public class Episode {
13
14
    @Schema(required = true, name = "id", description = "The episode ID", example = "1")
15
    @Id
16
    private Long id;
17
18
    @Column
19
    @Schema(required = true, name = "url", description = "The episode URL", example = "https://www.youtube.com/playlist?list=PLn5EpEMtxTCmLsbLgaN3djvEkRdp-YmlE")
20
    private String url;
21
22
    @Schema(required = true, description = "the hosts")
23
    @Column
24
    private Set<String> hosts;
25
26
    @Schema(required = true, description = "the guests")
27
    @Column
28
    private Set<Guest> guests;
29
30
}
31
32
import jakarta.nosql.mapping.Column;
33
import jakarta.nosql.mapping.Entity;
34
import org.eclipse.microprofile.openapi.annotations.media.Schema;
35
36
import javax.json.bind.annotation.JsonbVisibility;
37
import java.util.Objects;
38
39
@Schema(name = "Guest", description = "The entity that represents Guest")
40
@Entity
41
@JsonbVisibility(FieldVisibility.class)
42
public class Guest {
43
44
    @Schema(required = true, description = "The guest name", example = "Ada Lovelace")
45
    @Column
46
    private String name;
47
48
    @Schema(required = true, description = "The guest twitter handle", example = "adalovelace")
49
    @Column
50
    private String twitter;
51
52
}
53


After creating the entity, the next step to create the resource. As the usual JAX-RS annotation to define the path and the HTTP verbs such as GET, POST, and DELETE, there are also the Open API annotations.

Java
xxxxxxxxxx
1
101
 
1
import org.eclipse.microprofile.openapi.annotations.Operation;
2
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
3
import org.eclipse.microprofile.openapi.annotations.media.Content;
4
import org.eclipse.microprofile.openapi.annotations.media.Schema;
5
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
6
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
7
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
8
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
9
10
import javax.enterprise.context.ApplicationScoped;
11
import javax.inject.Inject;
12
import javax.ws.rs.Consumes;
13
import javax.ws.rs.DELETE;
14
import javax.ws.rs.GET;
15
import javax.ws.rs.POST;
16
import javax.ws.rs.Path;
17
import javax.ws.rs.PathParam;
18
import javax.ws.rs.Produces;
19
import javax.ws.rs.WebApplicationException;
20
import javax.ws.rs.core.MediaType;
21
import javax.ws.rs.core.Response;
22
import java.util.Optional;
23
import java.util.logging.Logger;
24
25
@Path("episodes")
26
@ApplicationScoped
27
@Consumes(MediaType.APPLICATION_JSON)
28
@Produces(MediaType.APPLICATION_JSON)
29
public class EpisodeResource {
30
31
    private static final Logger LOGGER = Logger.getLogger(EpisodeResource.class.getName());
32
33
    @Inject
34
    private EpisodeRepository repository;
35
36
    @GET
37
    @Operation(summary = "Get all episodes", description = "Returns all available episodes")
38
    @APIResponse(responseCode = "500", description = "Server unavailable")
39
    @APIResponse(responseCode = "200", description = "The episodes")
40
    @Tag(name = "BETA", description = "This API is currently in beta state")
41
    @APIResponse(description = "The episodes",
42
            responseCode = "200",
43
            content = @Content(mediaType = MediaType.APPLICATION_JSON,
44
                    schema = @Schema(implementation = Episodes.class,
45
                            readOnly = true,
46
                            description = "the episodes",
47
                            required = true,
48
                            name = "Episodes")))
49
    public Episodes getAll() {
50
        return new Episodes(repository.findAll());
51
    }
52
53
    @GET
54
    @Path("{id}")
55
    @Operation(summary = "Find an episode by id", description = "Find an episode by id")
56
    @APIResponse(responseCode = "200", description = "The episodes")
57
    @APIResponse(responseCode = "404", description = "When the id does not exist")
58
    @APIResponse(responseCode = "500", description = "Server unavailable")
59
    @Tag(name = "BETA", description = "This API is currently in beta state")
60
    @APIResponse(description = "The episode",
61
            content = @Content(mediaType = MediaType.APPLICATION_JSON,
62
                    schema = @Schema(implementation = Episode.class)))
63
    public Episode findById(@Parameter(description = "The Episode ID", required = true,
64
            example = "1", schema = @Schema(type = SchemaType.INTEGER)) @PathParam("id") Long id) {
65
66
        LOGGER.info("Finds episode by id: " + id);
67
        final Optional<Episode> episode = repository.findById(id);
68
        return episode.orElseThrow(() -> new WebApplicationException(Response.Status.NOT_FOUND));
69
    }
70
71
72
    @POST
73
    @Operation(summary = "Insert an Episode", description = "Insert an Episode")
74
    @APIResponse(responseCode = "201", description = "When creates an episode")
75
    @APIResponse(responseCode = "500", description = "Server unavailable")
76
    @Tag(name = "BETA", description = "This API is currently in beta state")
77
    public void insert(@RequestBody(description = "Create a new Episode.",
78
            content = @Content(mediaType = "application/json",
79
                    schema = @Schema(implementation = Episode.class))) Episode episode) {
80
        LOGGER.info("Episode: " + episode);
81
        repository.save(episode);
82
    }
83
84
    @DELETE
85
    @Path("{id}")
86
    @Operation(summary = "Delete an episode by ID", description = "Delete an episode by ID")
87
    @APIResponse(responseCode = "200", description = "When deletes the episode")
88
    @APIResponse(responseCode = "404", description = "When the id does not exist")
89
    @APIResponse(responseCode = "500", description = "Server unavailable")
90
    @Tag(name = "BETA", description = "This API is currently in beta state")
91
    @APIResponse(description = "The episode",
92
            content = @Content(mediaType = MediaType.APPLICATION_JSON,
93
                    schema = @Schema(implementation = Episode.class)))
94
    public void delete(@Parameter(description = "The Episode ID", required = true,
95
            example = "1", schema = @Schema(type = SchemaType.INTEGER))
96
                       @PathParam("id") Long id) {
97
        LOGGER.info("Deletes episode by id: " + id);
98
        repository.deleteById(id);
99
    }
100
}
101


The code is ready, to run locally let's use Docker with the command below:

Shell
xxxxxxxxxx
1
 
1
docker run -d --name mongodb-instance -p 27017:27017 mongo


The application is ready, and with MongoDB instance running, you can execute the application:

Shell
xxxxxxxxxx
1
 
1
mvn clean package
2
java -jar target/deploy-friday-ep15.jar


When the application is running, you can access the URL http://localhost:8080/openapi/ to get the open API result.

Let's go to the Postman to test your API; the first step is to import the API from the URL that we already showed.

Let's go to the Postman to test your API. The first step is to install the application itself where it has support for Linux, Windows or Mac OS. When we installed the Postman application, the next step is to import the API from the Open API URL.

It works like magic, don't forget to set the variables inside Postman.

Cloud: To Infinity and Beyond With Platform.sh

The application is ready to go, and you can run the application.  The next step is to move to the cloud with Platform.sh.

 To move your application to the cloud, briefly, you need three files:

 One to define the routes: 

YAML
xxxxxxxxxx
1
 
1
"https://{default}/":
2
  type: upstream
3
  upstream: "app:http"
4
5
"https://www.{default}/":
6
  type: redirect
7
  to: "https://{default}/"


One file to define the services that you need in your application.

To point out, you don't need to worry to handle it. Platform.sh will be the infrastructure for you.

YAML
 




xxxxxxxxxx
1


 
1
mongodb:
2
  type: mongodb:3.6
3
  disk: 1024



The last file is to configure the application, basically, you'll teach how to build and execute your application to Platform.sh. In this sample, we'll create a Java 11 container,  build with a maven command, and start the application from an uberjar.

YAML
xxxxxxxxxx
1
10
 
1
name: app
2
type: "java:11"
3
disk: 1024
4
hooks:
5
  build: mvn clean package
6
relationships:
7
  mongodb: 'mongodb:mongodb'
8
web:
9
  commands:
10
    start: java -jar $JAVA_OPTS $CREDENTIAL -Dserver.port=$PORT target/deploy-friday-ep15.jar


As you can see, we set the CREDENTIAL environment. The goal is to overwrite the database credentials on the cloud, so we can have a configuration to run locally and another one to run in the cloud with Platform.sh.

Shell
xxxxxxxxxx
1
 
1
export MONGO_PORT=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".mongodb[0].port"`
2
export MONGO_HOST=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".mongodb[0].host"`
3
export MONGO_ADDRESS="${MONGO_HOST}:${MONGO_PORT}"
4
export MONGO_PASSWORD=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".mongodb[0].password"`
5
export MONGO_USER=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".mongodb[0].username"`
6
export MONGO_DATABASE=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".mongodb[0].path"`
7
export JAVA_MEMORY=-Xmx$(jq .info.limits.memory /run/config.json)m
8
export JAVA_OPTS="$JAVA_MEMORY -XX:+ExitOnOutOfMemoryError"
9
export CREDENTIAL="-Ddocument.settings.jakarta.nosql.host=$MONGO_ADDRESS -Ddocument.database=$MONGO_DATABASE -Ddocument.settings.jakarta.nosql.user=$MONGO_USER -Ddocument.settings.jakarta.nosql.password=$MONGO_PASSWORD -Ddocument.settings.mongodb.authentication.source=$MONGO_DATABASE"


The application is now ready, so it’s time to move it to the cloud with Platform.sh using the following steps:

  • Create a new free trial account.

  • Sign up with a new user and password, or login using a current GitHub, Bitbucket, or Google account. If you use a third-party login, you’ll be able to set a password for your Platform.sh account later.

  • Select the region of the world where your site should live.

  • Select the blank template.

You have the option to either integrate to GitHub, GitLab, or Platform.sh will provide it to you. Finally, push to the remote repository.

The example is ready and in a GitHub repository.

That is it; we finished a tutorial about how to integrate and connect a Java application with Open API and test with Postman. Stay tuned to the next Deploy Friday episodes.

API application microservice

Opinions expressed by DZone contributors are their own.

Related

  • The Pros and Cons of API-Led Connectivity
  • 3 Reasons for the Mounting Demand for Smart Cloud-Native Application Development
  • Manage Microservices With Docker Compose
  • Split the Monolith: What, When, How

Partner Resources

×

Comments

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

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

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 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook