Programming with Java APIs, Part 1: OpenAPI and Swagger

Get started with API-driven development for cloud and microservices architectures

While you were getting your coffee, Java application development changed--again.

In a world driven by rapid change and innovation, it's ironic that APIs are making a comeback. Like the coding equivalent of New York City's subway system in the age of autonomous cars, APIs are old tech--ancient but indispensable. What's interesting is how this invisible, everyday IT architecture is being re-envisioned and used in current technology trends.

While APIs are everywhere, they've become especially prominent in their remote incarnation as RESTful services, which are the backbone of cloud deployments. Cloud services are public APIs, which are characterized by public-facing endpoints and published structures. Cloud-based apps are also trending toward microservices, which are independent but related deployments. All of these factors increase the prominence of APIs.

In this two-part article you'll learn how to put Java APIs at the heart of your design and development process, from concept to coding. Part 1 starts with an overview and introduces you to OpenAPI, also known as Swagger. We'll also start developing a simple BikeParts application, which we'll build out in Part 2.

What is a Java API?

APIs are so commonplace in software development that it's sometimes assumed that programmers simply know what they are. Rather than rely on osmosis, let's take a minute to unpack what we mean when we talk about APIs.

First, API stands for "application programming interface." An API's role is to specify how software components interact. If you're familiar with object-oriented programming, you know APIs in their incarnation as the interfaces and classes used to obtain access to underlying features of the language, or as the public face of third-party libraries and OS capabilities.

In general, we can say that APIs set and manage the boundaries between systems, as seen in Figure 1.

jw apidrivendev fig1 Matthew Tyson

Figure 1. The role of the API

So where does that leave us with API-driven development?

Java APIs for cloud computing, microservices, and REST

Programming with APIs comes to the fore with the modern web API: a network-exposed API (NEA), where the boundary between systems is "over the wire." These boundaries are already central to web apps, which are the common point of contact between front-end clients and back-end servers. The cloud revolution has exponentially increased the importance of Java APIs.

Any programming activity that requires consuming cloud services (which are basically public APIs) and deconstructing systems into smaller, independent but related deployments (also known as microservices), relies heavily on APIs. Network-exposed APIs are simply more universal, more easily obtained, and more readily modified and extended than traditional APIs. The current architectural trend is to capitalize on these features.

Microservices and public APIs are grown from the roots of service-oriented architecture (SOA) and software-as-a-service (SaaS). Although SOA has been a trend for many years, widespread adoption has been hamstrung by SOA's complexity and overhead. The industry has settled on RESTful APIs as the de facto standard, providing just enough structure and convention with more real-world flexibility. With REST as the backdrop, we can create formal API definitions that retain human readability. Developers create tooling around those definitions.

In general, REST is a convention for mapping resources to HTTP paths and their associated actions. You've likely seen these as HTTP GET and POST methods. What's key is to use HTTP itself as the standard, and layer conventional mappings on top of that for predictability.

Using Java APIs in design

You can see the importance of APIs, but how would you use them to your advantage?

Using Java API definitions to drive the design and development process is an efficient way to structure your thinking about IT systems. By using Java API definitions from the very beginning of the software development lifecycle (concept and requirements gathering) you will create a valuable technical artifact that is useful right up to deployment, as well as for ongoing maintenance.

Let's consider how Java API definitions bridge the conceptual and implementation stages of development.

Requirements gathering with Java APIs

On the conceptual-to-implementation spectrum, requirements gathering is way over on the concept side. But even in the conceptual stage of app dev, we can start thinking in terms of APIs.

Say your system-in-design is dealing with mountain bikes--construction, parts, and so forth. As an object-oriented developer, you'd start by talking to stakeholders about requirements. Pretty quickly after that, you would be thinking about an abstract BikePart class.

Next, you would think through the web application that would manage the various bike parts objects. Soon, you would arrive at common requirements to manage those bike parts. Here's a snapshot of the requirements phase of documentation for a bike parts app:

  • The application must be able to create a type of bike part (gear shifter, brake, etc.).
  • An authorized user must be able to list, create, and make a part type active.
  • An unauthorized user must be able to list active part types, and view lists of individual part-type instances in the system.

Already you can see the outlines of services taking shape. With eventual APIs in mind, you can begin sketching out those services. As an example, here's a partial listing of RESTful CRUD services for bike-part types:

  • Create bike part type: PUT /part-type/
  • Update bike part type: POST /part-type/
  • List part types: GET /part-type/
  • Get part type detail: GET /part-type/:id

Notice how the CRUD services begin to hint at the shape of various service boundaries. If you're building in a microservices style, you can already see three microservices emerging from the design:

  • A bike-part service
  • A bike part-type service
  • An authentication/authorization service

Because I think of APIs as boundaries of related entities, I consider the microservices from this list to be API surfaces. Together, they offer a big-picture view of the application architecture. Details of the services themselves are also described in a fashion that you will use for the technical specification, which is the next phase of the software development lifecycle.

Technical specification with Java APIs

If you've included the API focus as part of requirements gathering, then you already have a good framework for technical specification. The next stage is selecting the technology stack you will use to implement the specification.

With so much focus on building RESTful APIs, developers have an embarrassment of riches when it comes to implementation. Regardless of the stack you choose, fleshing out the API even further at this stage will increase your understanding of the app's architectural needs. Options might include a VM (virtual machine) to host the application, a database capable of managing the volume and type of data you're serving, and a cloud platform in the case of IaaS or PaaS deployment.

You can use the API to drive "downward" toward schemas (or document structures n NoSQL), or "upward" toward UI elements. As you develop the API specification, you will likely notice an interplay between these concerns. This is all good and part of the process. The API becomes a central, living place to capture these changes.

Another concern to keep in mind is which public APIs your system will expose. Give extra thought and care to these. Along with assisting in the development effort, public APIs serve as the published contract that external systems use to interface with yours.

Documenting the Java API

At this stage, you will want to start capturing your APIs in formal syntax. I've listed a few prominent API standards in Table 1.

Virtually any format you choose for documenting your API should be okay. Just look for a format that is structured, has a formal spec and good tooling around it, and looks like it will be actively maintained long term. Both RAML and OpenAPI fit that bill. Another neat project is API Blueprint, which uses markdown syntax. For examples in this article we're going to use OpenAPI and Swagger.

Introducing OpenAPI

OpenAPI is currently the most common choice for creating RESTful definitions. A compelling alternative is RAML (RESTful API Markup Language), which is based on YAML. Personally, I've found the tooling in Swagger (especially the visual designer) more polished and error-free than in RAML.

OpenAPI uses JSON syntax, which is familiar to most developers. If you'd rather not strain your eyes parsing JSON, there are UIs to make working with it easier. Part 2 introduces UIs for RESTful definitions.

Listing 1 is a sample of OpenAPI's JSON syntax.

Listing 1. OpenAPI definition for a simple BikePart



"paths": {
    "/part-type": {
      "get": {
        "description": "Gets all the part-types available in the system",
        "operationId": "getPartTypes",
         "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "Gets the BikeParts",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/BikePart"
              }
            }
          }
        }
      }
    }
}

This definition is so concise it is practically Spartan, which is fine for now. There's plenty of room to increase the detail and complexity of the API definition going forward. I'll show you a more detailed iteration of this definition shortly.

Coding from the Java API

Requirements gathering is done and the basic app has been spec'd out, which means you're ready for the fun part---coding! Having a formal Java API definition gives you some distinct advantages. For one thing, you know what endpoints the back-end and front-end developers need to create and code against, respectively. Even if you are a team of one, you'll quickly see the value of an API-driven approach when you begin coding.

As you build out the application, you'll also see the value of using APIs to capture the back-and-forth negotiation between development and business. Using API tools will speed up both applying and documenting code changes.

More granular specs and actual coding may require greater detail than the terse definition in Listing 1. Additionally, larger and more complex systems could merit capabilities that will scale, like document references. Listing 2 shows a more fleshed out example of the BikePart API.

Listing 2. Adding detail to the BikePart API definition


  "paths": {
    "/part-type": {
      "get": {
        "description": "Gets all the part-types available in the system",
        "operationId": "getPartTypes",
        "produces": [
          "application/json"
        ],
       "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "maximum number of results to return",
            "required": false,
            "type": "integer",
            "format": "int32"
          }
        ],
        "responses": {
          "200": {
            "description": "part-type listing",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/PartType"
              }
            }
          },
          "default": {
            "description": "unexpected error",
            "schema": {
              "$ref": "#/definitions/Error"
            }
          }
        }
}
1 2 Page 1
Page 1 of 2