Setting up Swagger with Quarkus and React

Dmytro Chaban
Quarkify
Published in
7 min readJun 1, 2020

Initialize a full-stack app is an easy task. Connect two seamlessly is a bit trickier. You can call /hello endpoint without any Swagger or other libraries. But when you have, say, 20 endpoints to work with, it's good to standardize your API calls.

This article covers:

  1. More complex than /hello REST API on Quarkus that will be used by our frontend
  2. Setup Swagger both on Quarkus and React
  3. Create Networking React class that will be used to fetch our data

Other articles of this Series:

  1. Build, run and deploy React app with Quarkus
  2. This article
  3. Handle Security with Swagger(Upcoming)

For better experience, please open this article on Quarkify

Initial setup

We gonna use same project that we created in previous article called quarkus-react

git clone https://github.com/quarkifynet/quarkus-react.git && cd quarkus-react

If you want to see final version, use next command

git clone --single-branch --branch feature/swagger-complete https://github.com/quarkifynet/quarkus-react.git && cd quarkus-react

Create REST API to use later

We gonna need some API to work with. If you cloned the repo, you should already have them at your disposal.

Alternatively you can come up with your own logic and follow this guide along the way. Or, if you already have a project, just skip to next part.

We gonna create ‘Downwork’, a competitor for well-known freelancing portal. So our basic schema looks like this:

You might see that user is super empty, that’s fine for now, we gonna fill it up in next part with adding JWT Security, for now, let’s declare entity objects

Now, let’s create a resource for us as well. So Idea is that user can register and log in(not in this section), submit jobs and proposals for them. We’ll need only JobPostResource for now, this resource will hold all the logic for job posts and proposals.

operationId

One thing to mention here is @Operation(operationId = "getPosts"). This annotation helps us to name method call that will be used from React, instead of calling get__posts, you gonna call getPosts. It doesn't look like much, but when you look at getJobProposals, without this annotation you'll have to call get_posts__id__proposals, which is hard to memorize. I left both options so you can compare how you want to call them, but you should know that you can call endpoint without operationId if needed(e.g external api)

We also need to define database. In this article, we gonna use H2. This database requires no additional setup except few lines in application.properties

quarkus.datasource.url=jdbc:h2:file:./test
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=test
quarkus.datasource.password=test
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.dialect=org.hibernate.dialect.H2Dialect

quarkus.http.cors=true

You can see that we also added quarkus.http.cors=true. This is required for React application to communicate from other port or even host. And last thing, let's add src/main/resources/import.sql

insert into jobpost values(1,'You will be entitled to work on Quarkus project', 'JavaEE Quarkus Developer', null);
insert into jobpost values(2,'You will work with nodejs and React', 'React Developer', null);

For now, we will omit User entity until next article about security

Setting up OpenAPI

Best thing about Quarkus is that whole Swagger setup will take only one command:

./mvnw quarkus:add-extensions -Dextension="openapi"

That’s it. Now if you run the app with ./mvnw quarkus:dev you can find OpenAPI schema at http://localhost:8080/openapi

There’s also Swagger UI which is super handy to look at all available API, it’s located at http://localhost:8080/swagger-ui/#/, let’s open it up and look at current swagger schema

You can see that Quarkus magically transformed all the returned objects into Schemas and all the annotated methods into endpoints.

React Swagger setup

Now let’s consume this data from React. The greatest part of Javascript, specifically, in this case, is that you don’t need to build anything for it to work. If you take Android development, you need to generate code via Swagger codegen, verify if all dependencies satisfy your build and import generated module into the android project itself. In Javascript, you only need to create a new object with the OpenAPI URL.

Firstly, we need to add single additional dependency:

yarn add swagger-client

Now, let’s create additional Networking.js file with the following content

We gonna look at exec method in a second, I firstly wanna talk about client object.

Using vanilla SwaggerClient

To use the Swagger library, the only requirement is to import swagger-client and initialize a new variable from it. Next you can execute any endpoint by next template:

this.client.then(
client => client.apis.default.getPosts(),
error => console.error('Failed to load the spec: ', error)
).then(
result => doStuff(result.body),
error => console.error('Failure on api call: ', error)
)

I made a handy method called exec, you're not obligated to use it, but it will save you few lines of code for each place where you'll call API once we'll introduce security. What's going on here? Well, firstly, you should know that Javascript's functions are first-class citizens, which means that you can put them in any place you want. In our case, we put them into the method's default value for parameters. We can rewrite code above to something like this:

static exec = function (endpoint, object, success, failure, security) {
if(failure == null) {
failure = res => console.log('failed on api call: ' + res)
}
...
}

Execute Quarkus endpoints from React

Now that we have our network stuff managed, let’s finally use some of our API.

I wanted to do something more interesting than Todo app that does every second guide, but this had its own drawbacks with the creation of a second file. Our final UI has a list of job posts, and when you click on one, you see a list of proposals. Everything is visible to everyone, we’ll change it once we introduce security.

Let’s firstly modify main screen, here’s full code for App.js

If you’re not a JavaScript developer, useState(default) basically declares variable and setter for this screen. useEffect(func, [conditions]) declares a function that will be executed only if conditions change. Don't try to put networking directly into App function, because every time screen changes it will execute code(and if this call changes UI you'll get endless loop)

Basically our main App screen is a container for a list of job posts. This is not a good practice but for simplicity of this article I had to do it, otherwise, we’ll end up with 5–8 additional code samples. When we load the screen, GET /posts executed and we set jobs variable via setJobs()

We also have an input view, which will set newJobConent via setNewJobContent() when the input changes itself.

We declared a job view as <Job job={it}/>, but we haven't created this class yet. Let's add Job.js with the following content:

Here’s additional styles that you can put into App.css if you want your ui to match mine.

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: start;
justify-content: start;

font-size: calc(10px + 2vmin);
color: white;
}

.job-container {
margin: 5vh;
margin-bottom: 1vh;
display: flex;
flex-direction: column;
align-items: start;
}

.job-desc {
font-size: calc(10px);
}

Verify if it’s working

Now, let’s start dev environment with ./mvnw quarkus:dev in java root folder and npm start in other window

./mvnw quarkus:dev 
# Other terminal
cd ./src/main/webapp && npm start

Go to http://localhost:3000/ and look at the available list of jobs:

Write something in a input below, (e.g Fullstack developer) and click Submit job. You'll see a new job created

Click expand on a job, and do the same actions: fill in input with some data, click Submit Offer and you'll see offer created

You can reload the page and see that everything is saved on the backend

In conclusion

Even though Javascript is really flexible language and you can write your own networking class, Swagger can still help you by managing some of the handy logic(e.g having operationId)

A large portion of the article was dedicated to React itself, mostly because Quarkus setup requires one additional extension, but it doesn’t mean that there’s nothing to modify, in the next article we gonna see how to manage security and authentication(JWT and basic) between Quarkus and React.

Originally published at https://quarkify.net on June 1, 2020.

--

--

Dmytro Chaban
Quarkify

Software Engineer, addicted to productivity and automatization