OpenLiberty / guide-rest-client-java

A guide on how to consume a REST service in Java: https://openliberty.io/guides/rest-client-java.html
Other
9 stars 24 forks source link

// Copyright (c) 2017, 2023 IBM Corporation and others. // Licensed under Creative Commons Attribution-NoDerivatives // 4.0 International (CC BY-ND 4.0) // https://creativecommons.org/licenses/by-nd/4.0/ // // Contributors: // IBM Corporation :projectid: rest-client-java :page-layout: guide-multipane :page-duration: 25 minutes :page-releasedate: 2018-07-02 :page-guide-category: microprofile :page-essential: false :page-description: Explore how to access a simple RESTful web service and consume its resources in Java using JSON-B and JSON-P. :page-tags: ['MicroProfile', 'Jakarta EE'] :page-related-guides: ['rest-intro', 'rest-client-angularjs'] :page-permalink: /guides/{projectid} :common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod :source-highlighter: prettify :page-seo-title: Consuming a RESTful Java web service :page-seo-description: A getting started tutorial with examples on how to access a RESTful Java microservice and consume its resources using the Java API for JSON Binding (JSON-B) and the Java API for JSON Processing (JSON-P). :guide-author: Open Liberty = Consuming a RESTful web service

[.hidden] NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website].

Explore how to access a simple RESTful web service and consume its resources in Java using JSON-B and JSON-P.

// ================================================================================================= // Introduction // =================================================================================================

== What you'll learn artists.json [source, json, linenums, role='code_column']

include::finish/src/resources/artists.json[]

You will learn how to access a REST service, serialize a Java object that contains a list of artists and their albums, and use two different approaches to deserialize the returned JSON resources. The first approach consists of using the Java API for JSON Binding (JSON-B) to directly convert JSON messages into Java objects. The second approach consists of using the Java API for JSON Processing (JSON-P) to process the JSON.

The REST service that provides the artists and albums resources is already written for you. When the Liberty is running, this service is accessible at the \http://localhost:9080/artists endpoint, which responds with the [hotspot]artists.json file.

You will implement the following two endpoints using the two deserialization approaches:

If you are interested in learning more about REST services and how you can write them, read https://openliberty.io/guides/rest-intro.html[Creating a RESTful web service^].

// ================================================================================================= // Getting Started // ================================================================================================= [role=command] include::{common-includes}/gitclone.adoc[]

[role='command'] include::{common-includes}/twyb-intro.adoc[]

// static guide instructions: ifndef::cloud-hosted[] You can find your service at the http://localhost:9080/artists[http://localhost:9080/artists^] endpoint.

Now, you can access the endpoint at http://localhost:9080/artists/total[http://localhost:9080/artists/total^] to see the total number of artists, and you can access the endpoint at \http://localhost:9080/artists/total/<artist> to see a particular artist’s total number of albums.

endif::[]

// cloud-hosted guide instructions: ifdef::cloud-hosted[] Open another command-line session by selecting Terminal > New Terminal from the menu of the IDE.

You can find your service at the http://localhost:9080/artists endpoint by running the following curl command:

curl -s http://localhost:9080/artists | jq

Run the following curl command to retrieve the total number of artists:

curl http://localhost:9080/artists/total

You can access the endpoint at http://localhost:9080/artists/total/ to see a particular artist’s total number of albums. Run the following curl command to retrieve the artist bar's total number of albums:

curl http://localhost:9080/artists/total/bar

endif::[]

[role='command'] include::{common-includes}/twyb-end.adoc[]

// ================================================================================================= // Starting the service // =================================================================================================

== Starting the service

// static guide instructions: ifndef::cloud-hosted[] Navigate to the start directory to begin. endif::[]

// cloud-hosted guide instructions: ifdef::cloud-hosted[] To begin, run the following command to navigate to the start directory:

cd /home/project/guide-rest-client-java/start

endif::[]

[role=command] include::{common-includes}/devmode-lmp33-start.adoc[]

// static guide instructions: ifndef::cloud-hosted[] The application that you'll build upon was created for you. After your Liberty instance is ready, you can access the service at the http://localhost:9080/artists[http://localhost:9080/artists^] URL. endif::[]

// cloud-hosted guide instructions: ifdef::cloud-hosted[] The application that you'll build upon was created for you. After your Liberty instance is ready, run the following curl command to access the service:

curl -s http://localhost:9080/artists | jq

endif::[]

// ================================================================================================= // Guide // ================================================================================================= == Creating POJOs

Artist.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/model/Artist.java[]

Album.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/model/Album.java[]

To deserialize a JSON message, start with creating Plain Old Java Objects (POJOs) that represent what is in the JSON and whose instance members map to the keys in the JSON.

For the purpose of this guide, you are given two POJOs. The [hotspot=Artist file=0]Artist object has two instance members [hotspot=name file=0]name and [hotspot=Albums file=0]albums, which map to the artist name and the collection of the albums they have written. The [hotspot=Album file=1]Album object represents a single object within the album collection, and contains three instance members [hotspot=title file=1]title, [hotspot=artistName file=1]artistName, and [hotspot=totalTracks file=1]totalTracks, which map to the album title, the artist who wrote the album, and the number of tracks the album contains.

== Introducing JSON-B and JSON-P

JSON-B is a feature introduced with Java EE 8 and strengthens Java support for JSON. With JSON-B you directly serialize and deserialize POJOs. This API gives you a variety of options for working with JSON resources.

In contrast, you need to use helper methods with JSON-P to process a JSON response. This tactic is more straightforward, but it can be cumbersome with more complex classes.

JSON-B is built on top of the existing JSON-P API. JSON-B can do everything that JSON-P can do and allows for more customization for serializing and deserializing.

=== Using JSON-B Artist.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/model/Artist.java[]

JSON-B requires a POJO to have a public default no-argument constructor for deserialization and binding to work properly.

The JSON-B engine includes a set of default mapping rules, which can be run without any customization annotations or custom configuration. In some instances, you might find it useful to deserialize a JSON message with only certain fields, specific field names, or classes with custom constructors. In these cases, annotations are necessary and recommended:

For more information on customization with JSON-B, see the https://javaee.github.io/jsonb-spec[official JSON-B site^].

// ================================================================================================= // Consuming REST resource // =================================================================================================

== Consuming the REST resource

Artist.java [source, java, linenums, role='code_column hide_tags=comment,copyright']

include::finish/src/main/java/io/openliberty/guides/consumingrest/model/Artist.java[]

Album.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/model/Album.java[]

The [hotspot=Artist file=0]Artist and [hotspot=Album file=1]Album POJOs are ready for deserialization. Next, we'll learn to consume the JSON response from your REST service.

[role="code_command hotspot file=2" subs="quotes"]

Create the Consumer class.

src/main/java/io/openliberty/guides/consumingrest/Consumer.java

Consumer.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/Consumer.java[]

=== Processing JSON using JSON-B Consumer.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/Consumer.java[]

pom.xml [source, xml, linenums, role='code_column hide_tags=comment']

include::finish/pom.xml[]

JSON-B is a Java API that is used to serialize Java objects to JSON messages and vice versa.

Open Liberty's JSON-B feature on Maven Central includes the JSON-B provider through transitive dependencies. The JSON-B APIs are provided by the MicroProfile dependency in your [hotspot file=1]pom.xml file. Look for the dependency with the [hotspot=microprofile file=1]microprofile artifact ID.

The [hotspot=consumeWithJsonb file=0]consumeWithJsonb() method in the [hotspot=Consumer file=0]Consumer class makes a [hotspot=get-1 file=0]GET request to the running artist service and retrieves the JSON. To bind the JSON into an Artist array, use the [hotspot=readEntity file=0]Artist[] entity type in the [hotspot=readEntity file=0]readEntity call.

=== Processing JSON using JSON-P Consumer.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/Consumer.java[]

The [hotspot=consumeWithJsonp]consumeWithJsonp() method in the [hotspot=Consumer]Consumer class makes a [hotspot=get-2]GET request to the running artist service and retrieves the JSON. This method then uses the [hotspot=collectArtists]collectArtists and [hotspot=collectAlbums]collectAlbums helper methods. These helper methods will parse the JSON and collect its objects into individual POJOs. Notice that you can use the custom constructors to create instances of Artist and Album.

== Creating additional REST resources Consumer.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/Consumer.java[]

Now that you can consume a JSON resource you can put that data to use.

[role="code_command hotspot file=1", subs="quotes"]

Replace the ArtistResource class.

src/main/java/io/openliberty/guides/consumingrest/service/ArtistResource.java

ArtistResource.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/main/java/io/openliberty/guides/consumingrest/service/ArtistResource.java[]

The methods that you wrote in the [hotspot=Consumer file=0]Consumer class could be written directly in the [hotspot=ArtistResource file=1]ArtistResource class. However, if you are consuming a REST resource from a third party service, you should separate your GET/POST requests from your data consumption.

// ================================================================================================= // Running the application // =================================================================================================

== Running the application

The Open Liberty was started in dev mode at the beginning of the guide and all the changes were automatically picked up.

// static guide instructions: ifndef::cloud-hosted[] You can find your service at http://localhost:9080/artists[http://localhost:9080/artists^].

Now, you can access the endpoint at http://localhost:9080/artists/total[http://localhost:9080/artists/total^] to see the total number of artists, and you can access the endpoint at \http://localhost:9080/artists/total/<artist> to see a particular artist's total number of albums. endif::[]

// cloud-hosted guide instructions: ifdef::cloud-hosted[] You can find your service at the http://localhost:9080/artists endpoint by running the following curl command:

curl -s http://localhost:9080/artists | jq

Run the following curl command to retrieve the total number of artists:

curl http://localhost:9080/artists/total

You can access the endpoint at http://localhost:9080/artists/total/ to see a particular artist’s total number of albums. Run the following curl command to retrieve the artist bar's total number of albums:

curl http://localhost:9080/artists/total/bar

endif::[]

// ================================================================================================= // Testing deserialization // =================================================================================================

== Testing deserialization

[role="code_command hotspot", subs="quotes"]

Create the ConsumingRestIT class.

src/test/java/it/io/openliberty/guides/consumingrest/ConsumingRestIT.java

ConsumingRestIT.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/test/java/it/io/openliberty/guides/consumingrest/ConsumingRestIT.java[]

Maven finds and executes all tests under the src/test/java/it/ directory, and each test method must be marked with the [hotspot=test-1 hotspot=test-2 hotspot=test-3 hotspot=test-4]@Test annotation.

You can use the [hotspot=BeforeAll]@BeforeAll and @AfterAll annotations to perform any one-time setup and teardown tasks before and after all of your tests run. You can also use the [hotspot=BeforeEach]@BeforeEach and [hotspot=AfterEach]@AfterEach annotations to perform setup and teardown tasks for individual test cases.

=== Testing the binding process ConsumingRestIT.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/test/java/it/io/openliberty/guides/consumingrest/ConsumingRestIT.java[]

pom.xml [source, xml, linenums, role='code_column hide_tags=copyright,comment']

include::finish/pom.xml[]

The [hotspot=Yasson file=1]yasson dependency was added in your [hotspot file=1]pom.xml file so that your test classes have access to JSON-B.

The [hotspot=testArtistDeserialization file=0]testArtistDeserialization test case checks that Artist instances created from the REST data and those that are hardcoded perform the same.

The [hotspot=assertResponse file=0]assertResponse helper method ensures that the response code you receive is valid (200).

=== Processing with JSON-B test ConsumingRestIT.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/test/java/it/io/openliberty/guides/consumingrest/ConsumingRestIT.java[]

The [hotspot=testJsonBAlbumCount]testJsonBAlbumCount and [hotspot=testJsonBAlbumCountForUnknownArtist]testJsonBAlbumCountForUnknownArtist tests both use the total/{artist} endpoint which invokes JSON-B.

The [hotspot=testJsonBAlbumCount]testJsonBAlbumCount test case checks that deserialization with JSON-B was done correctly and that the correct number of albums is returned for each artist in the JSON.

The [hotspot=testJsonBAlbumCountForUnknownArtist]testJsonBAlbumCountForUnknownArtist test case is similar to [hotspot=testJsonBAlbumCount]testJsonBAlbumCount but instead checks an artist that does not exist in the JSON and ensures that a value of -1 is returned.

=== Processing with JSON-P test ConsumingRestIT.java [source, java, linenums, role='code_column hide_tags=copyright,comment']

include::finish/src/test/java/it/io/openliberty/guides/consumingrest/ConsumingRestIT.java[]

The [hotspot=testJsonPArtistCount]testJsonPArtistCount test uses the total endpoint which invokes JSON-P. This test checks that deserialization with JSON-P was done correctly and that the correct number of artists is returned.

// ================================================================================================= // Running the Tests // =================================================================================================

=== Running the tests

Becayse you started Open Liberty in dev mode at the start of the guide, press the enter/return key to run the tests.

If the tests pass, you see a similar output to the following example:

[source, role="no_copy"]


T E S T S

Running it.io.openliberty.guides.consumingrest.ConsumingRestIT Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.59 sec - in it.io.openliberty.guides.consumingrest.ConsumingRestIT

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0


When you are done checking out the service, exit dev mode by pressing CTRL+C in the command-line session where you ran Liberty.

== Building the application

If you are satisfied with your application, run the Maven package goal to build the WAR file in the target directory:

[role=command]

mvn package

== Great work! You're done!

You just accessed a simple RESTful web service and consumed its resources by using JSON-B and JSON-P in Open Liberty.

include::{common-includes}/attribution.adoc[subs="attributes"]