Swagger vs Wrappers

Hello!

In this article I would like to talk about Swagger and Wrappers.

Swagger simplifies API development for users, teams, and enterprises with the Swagger open source and professional toolset. You can find more info here.

By wrappers I mean libraries which manipulate data by Rest Api in a more convenient for developers way.

For example, you can have a look at the following wrappers: jiraclient (a JavaScript Jira Rest Api Wrapper), Python Jira Client .

Why do we need the wrappers at all?

I will be talking about wrappers for Jira but the same idea can be applied to wrappers for any other application (Atlassian or not Atlassian).

Wrappers let us call Jira Rest API in an easy way. For example, let’s have a look at the jiraclient wrapper. We can find issues in Jira with the following code:

// With ES6
import JiraApi from 'jira-client';

// Initialize
var jira = new JiraApi({
  protocol: 'https',
  host: 'jira.somehost.com',
  username: 'username',
  password: 'password',
  apiVersion: '2',
  strictSSL: true
});

async function logIssueName() {
  try {
    const issue = await jira.findIssue(issueNumber);
    console.log(`Status: ${issue.fields.status.name}`);
  } catch (err) {
    console.error(err);
  }
}

You see, first we created a Jira object for our url, username and password and then we called jira.findIssue function instead of calling the issue Jira Rest API method directly. It lets us write less code and make our software less buggy, faster to develop and more understandable.

The same with the Python library:

jira = Jira(
    url='http://localhost:8080',
    username='admin',
    password='admin')
JQL = 'project = DEMO AND status IN ("To Do", "In Progress") ORDER BY issuekey'
data = jira.jql(JQL)
print(data)

Again we initialised our Jira connection and then got issues by a jql query with the jira.jql function. Very easy and clean code.

I believe now you have an idea, why to use the wrappers.

Then why Swagger?

And we had used wrappers before Swagger emerged. Swagger lets the developer of the Rest API to define all Rest API in a file of a certain format and then swagger clients can analyze this file and call Rest API functions based on the data provided by this file.

I will provide here a detailed example how it works.

I developed a plugin called jira-react-atlaskit in which I showed how to use React and AtlasKit in a Jira Server Plugin.

Now I will extend this plugin to get all projects from a Jira Cloud Server using swagger-js library.

In a real application I would call Jira Cloud API from my Java code in the backend using the swagger-codegen library instead, because it would make our application more secure.

But here I will get all projects from my JavaScript code.

Change backend

As I said before, if we want to use a swagger client we need REST API declaration in a file in a certain format. Atlassian did it for us. We can get REST API declaration for Jira Cloud from here.

You need to download this file and change the servers parameter:

"servers":[{"url":"https://your-domain.atlassian.com"}]

Change url to the url of your Jira Cloud.

Next we need to make this file available for our Jira Server app that is why I put this file into backend/src/main/resources/swagger folder. The name of the file is swagger.v3.json.

And now I need to add a reference to this file into my web-resource descriptor in the atlassian-plugin.xml file:

<resource type="download" name="swagger/" location="/swagger"/>

And I will also pass the url to this file as a parameter to my soy template. Later I can get this url in my JS code.

backend/src/main/java/ru/matveev/alexey/atlas/jira/servlet/FormServlet.java

 map.put("pathtoswaggerjson", "/jira/download/resources/ru.matveev.alexey.atlas.jira.backend:jira-react-atlaskit-resources/swagger/swagger.v3.json");

Now I will read this parameter in my soy template.

        <input class="text" type="text" id="pathtoswaggerjson" name="pathtoswaggerjson" value="{$pathtoswaggerjson}">

Done! Now we are ready to change our frontend.

Change frontend

First we need to add dependency to swagger-js library in frontend/package.json:

"swagger-client": "^3.11.0",

Then we need to add code to frontend/src/js/components/Form.js.

I imported the library:

import SwaggerClient from 'swagger-client';

And then I added code to the construcor.

I get the url to the swagger.v3.json file:

const pathtoswaggerjson = document.getElementById("pathtoswaggerjson").value

Now I can write code to get all projects:

new SwaggerClient(pathtoswaggerjson, {requestInterceptor: (req) => {
      req.headers.Authorization = 'Basic base64(user:token)';
      return req;
    }})
        .then(
          client => client.apis.Projects.getAllProjects()
        )
        .then(
          getAllProjectsResult => console.log(getAllProjectsResult.body),
        )

  }

That s it.

As I said in a real application this code must be executed in the backend, but I am executing this code right from the browser that is why I need to launch my browser with web security disabled.

open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security

Now if I open my Form I will see the following message in console:

You see I got all projects from my Jira Cloud instance.

We had to write just a couple of lines to make it work.

You can also see the whole list of available Rest API if you write a code like this:

new SwaggerClient(pathtoswaggerjson, {requestInterceptor: (req) => {
      req.headers.Authorization = 'Basic Basic base64(user:token)';
      return req;
    }})
        .then(
          client => console.log(client.apis)
        )

If you execute this code, you will see something like this:

It is a list of all available Rest API methods.

Conclusion

As you can see we write about the same amount of code with Swagger and Wrappers. Then why to use Swagger?

  1. Developers of products refresh their Rest API declaration fast. Developers of wrappers can not be as fast as developers of the products. Or someday the developers of wrappers can refuse to support their wrapper. What for to waste time on writing code if you can do the same without writing any wrapper code?
  2. If you use Swagger then you can use the same swagger client to work with any Rest API which is described in the Swagger notation. You do not need to look for wrappers for every product you are tying to access.

That is why I think that the need for wrappers has become much less. Yes, we would still need wrappers if these wrappers provide a more efficient code than the code which generated by swagger clients. But for the libraries I mentioned above it is not the case. As for the most of wrappers.

You can find the final code here.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Leave a Reply

%d bloggers like this:

Spelling error report

The following text will be sent to our editors: