Interacting with Blockchain REST APIs in Cloud-Native Java
REST APIs are a common way of programmatically interacting with other services. They are typically well documented in a human readable way, and tell you what parameters they accept and how the results are formatted such as through JSON. However, if they are also described with an OpenAPI definition, they be easily consumed in your application without needing you to read the documentation and without having to write a ton of code to handle the formatting.
In this post, I show an example of how a REST API can be used in a cloud-native Java application to interact with a blockchain, including how all of the different parts fit together. You will see how the actual amount of code that needs to be written for such a scenario is minimal, and the rest (no pun intended) is generated for you through various open source tools. These include Java interfaces and models that you can call directly, which represent and invoke the underlying REST APIs.
The scenario is to write a Java servlet that predicts Ethereum transaction metrics in terms of recommended gas prices and corresponding transaction confirmation times using Amberdata’s Web3api.
While predicting transaction metrics is just one simple use case that will be covered here, this concept itself can be useful in situations where your application needs to invoke a smart contract and therefore programmatically determine the optimal amount of fees to pay for the desired transaction speed.
Web3api provides a lot of different REST APIs for interacting with various public blockchains such as Bitcoin and Ethereum. Its API documentation provides detailed information on its usage and functionality. In addition to transaction metrics, it can provide access to other data such as blockchain address information and market metrics.
However, I could not find any OpenAPI definition that describes its REST APIs. As suggested earlier, having such a document available would be incredibly useful to allow developers to generate client code for the language and programming model that they are using.
To get around this, I wrote an initial OpenAPI definition for the Transaction Gas Predictions API. This involved reading the API documentation, its fields and returned JSON format, and manually translating this information into a YAML file that describes this API for programmatic consumption. It would be much easier if Web3api provided such a document for all of their REST APIs.
In general, all REST service providers should look into providing an OpenAPI definition of their API. Some frameworks can even create it automatically!
This example is implemented as a cloud-native Java application using the MicroProfile programming model, deployed on an Open Liberty server. An OpenAPI definition was written for the REST API as mentioned above, which is used to generate the Java interfaces and models which conform to the MicroProfile Rest Client specification. These are then injected into the servlet’s code through dependency injection.
Trying out the completed example
Try out the example project by running following:
git clone https://github.com/ericglau/restclient-web3api
Go to http://localhost:9080/gas to run the servlet.
At this point you can look around the code and experiment with changes, which will be automatically reflected in the running server.
If you want to learn how to build this for yourself from scratch, follow along in the steps below.
Initial project setup
- Start VS Code and install the MicroProfile Extension Pack.
View -> Command Palette…, search for
MicroProfile: Generate a new MicroProfile starter project
Open Libertyas the server, leave the specifications empty for MicroProfile, then generate the project into an empty folder. When prompted, click
Open in new window.
Configuring security settings
The Java runtime requires the SSL certificate for the REST API’s server to be trusted, which can be done as follows:
- Download the SSL certificate for the REST API’s server URL that you will be using. In our example, it is
- Import the certificate into the
src/main/liberty/config/public.jksfile using password
atbashsince this is the default keystore and password defined in
Download the OpenAPI definition
- Go to the OpenAPI definition for the REST API.
Export -> Download API -> YAML Resolved
- Unzip the downloaded file and locate the
openapi.yamlfile. This file will be used in the next section.
Generating the REST client
Here’s the interesting part. From the OpenAPI definition file, you simply generate a REST client including Java interfaces and models that you can use directly in your code.
- On the Explorer pane of VS Code, right-click the
Generate a MicroProfile REST client.
- Select the
openapi.yamlfile that you downloaded, then generate the REST client into the current package.
Notice the generated content that has appeared in your workspace. The
api folder contains the REST client Java interfaces, and the
models folder has the Java models. The
src/main/java/com/example/demo/api/Web3Api.java file is the interface that you can call from application code.
(Some compile errors may occur because of missing dependencies. Add them to
pom.xml as seen here.)
Configuring the REST server URI
The main interface for the REST client was generated as shown above. However, the REST API server’s base URI must be configured so that MicroProfile can map the interface path.
src/main/resources/META-INF/microprofile-config.properties and add the following line:
Starting the application
On the side pane, find the Liberty Dev Dashboard, right click the
demo project and choose Start. This starts the application on Open Liberty using development mode and you can monitor its console output in the terminal window within VS Code.
Using the REST client
Create a new file
src/main/java/com/example/demo/GasServlet.java with the content from the completed servlet. If there are compile errors, ensure you have the
javax.servlet-api dependency in your pom.xml.
The servlet code is shown above. Notice that you don’t need to care about JSON formats or HTTP methods for the REST API, since those low level details are abstracted away by the programming model. Simply inject the REST client and use its Java interface and models as normal Java code.
Finally, go to http://localhost:9080/gas to run the servlet and see the results in your browser.
As mentioned earlier, this is just one simple use case of a blockchain REST API. You could extend the project further to invoke smart contracts and use the predicted transaction metrics to determine how much fees your application should pay. There are also plenty of other APIs available that can cover countless other scenarios!
What you’ve learned here is not limited to blockchains either. You can use any REST API in cloud-native Java applications by following the example above to make use of OpenAPI and the MicroProfile programming model.