Consuming RESTful webservices published to OpenShift

As an example of consuming RESTful webservices that have been deployed to Red Hat OpenShift, JBoss Developer published the following video to Vimeo.  The purpose of this article is to provide a step-by-step synopsis of what is presented in the video.

 

 

The video provides an example of how to deploy a RESTful web service on Red Hat OpenShift.  The focus of this video is to provide a very simple example that introduces the user to JAX-RS technology and the basics of deploying it to OpenShift.  Specifically, the video is based on the helloworld-rs quickstart which ships with the JBoss AS7 quickstart project.  The quickstart and the associated video provide an excellent place to start when learning JAX-RS. 

 

To begin, this article assumes that you have registered and set up an account on Red Hat OpenShift.  If you have not, it is a very simple process requiring your email address and setting up a password credential.  Additionally, OpenShift makes use of SSH so you will need to make sure you have followed the instructions on OpenShift for properly setting up your SSH keys.  Furthermore, all of the JBoss AS7 quickstarts make use of Maven and Git so it is important to have these client tools set up on your workstation prior to going through the steps for this example.  Finally, be sure to install the rhc client tools for a command line interface to Red Hat OpenShift.  Once these items have been taken care of, you can proceed with following the steps outlined below.

 

  1. Clone the JBoss AS7 quickstarts.  This can be done by running the following command:
    $ git clone https://github.com/jbossas/quickstart.git

    This will pull down the JBoss AS 7 quickstarts to your local workstation.

  2. Now, cd into helloworld-rs.  Notice that this is a Maven project.  Once inside the helloworld-rs directory, we will create an application on OpenShift with an AS7 cartridge by running the following command:
    $ rhc app create -a helloworldrs -t jbossas-7
    It could take a few minutes for this command to complete as the domain name is being propagated around the globe.

  3. The above command will actually create a sub-directory.  Now, cd into that new directory, helloworldrs.

  4. We will now remove a directory and a file within the newly created directory.  Remember, we are using Git so we need to indicate a change so that we can later push this to OpenShift.  Run the following command from within the new directory:
    $ git rm -r src/ pom.xml


  5. Now, copy the original pom.xml to this new directory:
    $ cp -r ../pom.xml .
    
  6. Now, copy the original src to this new directory:
    $ cp -r ../src .
  7. Now, we will add the newly copied file and directory to our git repository.
    $ git add src pom.xml
  8. With these files added to our git repository, we will commit the changes with the following command:
    $ git commit -m 'helloworld-rs quickstart on OpenShift'
  9. Finally, the following command will push our respository to OpenShift.  Once deployed to OpenShift, a Maven build will be executed.  Within the pom.xml, there is an OpenShift profile which kicks off when this application is deployed.
    $ git push
  10. The quickstart helloworld-rs has now been successfully deployed.  Now with it deployed to OpenShift, we should do a quick smoke test.  URLs on OpenShift are of the format of <application name>-<domain or namespace>.rhcloud.com.  In my case, my domain is simply my initials, rbm.  This can be easily setup via a browser on OpenShift.  With the application deployed, we can do a quick smoke test for both XML and JSON output from our RESTful web service.  Try the following URL in a browser and keep in mind that your domain will be different from mine: 
    http://helloworldrs-rbm.rhcloud.com/xml .  This URL will supply the XML output as indicated below:
    <xml>
        <result>Hello World!</result>
    </xml>



  11. Now, try the URL for JSON output.  Again, this URL will depend on your own domain or namespace on OpenShift.  So, the URL should be along the lines of http://helloworldrs-rbm.openshift.com/json .  The output should be the following:
    {"result":"Hello World!"}
  12. With the successful deployment and smoke test of our RESTful Web Service, we can now move on to the JaxRsClient.  Change directories now to the quickstart directory indicated in Step 1 of this page.  From there, change directories into jax-rs-client.  This project is also a Maven-based project.  The primary class is a test class that is executed during the test phase of the Maven build.  To inspect the class, change directories to src/test/java/org/jboss/as/quickstarts/jaxrsclient.  The test class is JaxRsClientTest.java .  The contents of the source file have been pasted  below for further inspection.
    package org.jboss.as.quickstarts.jaxrsclient;
    /**
     * This example demonstrates the use an external JAX-RS RestEasy client
     * which interacts with a JAX-RS Web service that uses CDI 1.0 and JAX-RS 
     * in JBoss AS 7.  Specifically, this client "calls" the HelloWorld JAX-RS
     * Web Service created in quickstart helloworld-rs.  Please refer to the helloworld-rs
     * README.md for instructions on how to build and deploy helloworld-rs.
     */
    import static org.junit.Assert.*;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    import javax.ws.rs.core.MediaType;
    
    import org.apache.http.client.ClientProtocolException;
    import org.jboss.resteasy.client.ClientRequest;
    import org.jboss.resteasy.client.ClientResponse;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    
    /**
     * JUnit4 Test class which makes a request to the RESTful
     * helloworld-rs web service.
     * 
     * @author bmincey (Blaine Mincey)
     *
     */
    public class JaxRsClientTest
    {
        /** 
         * Request URLs pulled from system properties in pom.xml
         */
        private static String XML_URL;
        private static String JSON_URL;
    
        /**
         * Property names used to pull values from system properties in pom.xml
         */
        private static final String XML_PROPERTY = "xmlUrl";
        private static final String JSON_PROPERTY = "jsonUrl";
    
        /**
         * Responses of the RESTful web service
         */
        private static final String XML_RESPONSE = "<xml><result>Hello World!</result></xml>";
        private static final String JSON_RESPONSE = "{\"result\":\"Hello World!\"}";
    
    
        /**
         * Method executes BEFORE the test method.  Values are read from system
         * properties that can be modified in the pom.xml.
         */ 
        @BeforeClass
        public static void beforeClass()
        {
            JaxRsClientTest.XML_URL = System.getProperty(JaxRsClientTest.XML_PROPERTY);
            JaxRsClientTest.JSON_URL = System.getProperty(JaxRsClientTest.JSON_PROPERTY);
        }
    
        /**
         * Test method which executes the runRequest method that calls the RESTful 
         * helloworld-rs web service.
         */
        @Test
        public void test()
        {
            assertEquals("XML Response", JaxRsClientTest.XML_RESPONSE, 
                    this.runRequest(JaxRsClientTest.XML_URL, MediaType.APPLICATION_XML_TYPE));
    
            assertEquals("JSON Response", JaxRsClientTest.JSON_RESPONSE, 
                    this.runRequest(JaxRsClientTest.JSON_URL, MediaType.APPLICATION_JSON_TYPE));
        }
    
        /**
         * The purpose of this method is to run the external REST request.
         * @param url The url of the RESTful service
         * @param mediaType The mediatype of the RESTful service
         */
        private String runRequest(String url, MediaType mediaType)
        {
            String result = null;
    
            System.out.println("===============================================");
            System.out.println("URL: " + url);
            System.out.println("MediaType: " + mediaType.toString());
    
            try
            {
                // Using the RESTEasy libraries, initiate a client request 
                // using the url as a parameter
                ClientRequest request = new ClientRequest(url);
    
                // Be sure to set the mediatype of the request
                request.accept(mediaType);
    
                // Request has been made, now let's get the response
                ClientResponse<String> response = request.get(String.class);
    
                // Check the HTTP status of the request
                // HTTP 200 indicates the request is OK
                if (response.getStatus() != 200)
                {
                    throw new RuntimeException("Failed request with HTTP status: "
                            + response.getStatus());
                }
    
                // We have a good response, let's now read it
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        new ByteArrayInputStream(response.getEntity().getBytes())));
    
                // Loop over the br in order to print out the contents
                System.out.println("\n*** Response from Server ***\n");
                String output = null;
                while ((output = br.readLine()) != null)
                {
                    System.out.println(output);
                    result = output;
                }
            }
            catch (ClientProtocolException cpe)
            {
                System.err.println(cpe);
            }
            catch (IOException ioe)
            {
                System.err.println(ioe);
            }
            catch (Exception e)
            {
                System.err.println(e);
            }
    
            System.out.println("\n===============================================");
    
            return result;
        }
    
    }
    
    
  13. There is nothing within the test class that needs to be modified.  Take note of the @BeforeClass annotation.  This method executes before the test is actually run.  It is within this method that properties are pulled from pom.xml for the XML and JSON URLs.  Due to the unique domain or namespace for each user on OpenShift, these URLs will need to be modified accordingly.  Take note of the maven-surefire-plugin configuration.  2 specific properties will need to be modified to match your application deployed to OpenShift.  Specifically, these properties are xmlUrl and jsonUrl.  The values for these properties should equal the values that were used to test the RESTful service on OpenShift via browser.
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.jboss.as.quickstarts</groupId>
        <artifactId>jax-rs-client</artifactId>
        <version>1.0</version>
        <name>JBoss AS Quickstarts:  jax-rs-client</name>
    
        <url>http://jboss.org/jbossas</url>
    
        <properties>
            <!-- Explicitly declaring the source encoding eliminates the following 
                message: -->
            <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered 
                resources, i.e. build is platform dependent! -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxrs</artifactId>
                <version>2.2.2.GA</version>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpcore</artifactId>
                <version>4.1.4</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!-- Maven compiler plugin -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.4.3</version>
                    <configuration>
                        <systemProperties>
                            <property>
                                <name>xmlUrl</name>
                                <value>http://localhost:8080/jboss-as-helloworld-rs/xml</value>
                            </property>
                            <property>
                                 <name>jsonUrl</name>
                                 <value>http://localhost:8080/jboss-as-helloworld-rs/json</value>
                            </property>
                        </systemProperties>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
  14. From within the base directory for the jax-rs-client, the following Maven command should be run:
    $ mvn test
  15. A successful run will output the values for "Hello World!" from both an XML and JSON URL within the console.