Apache CXF with POJO


Advertisements

In this chapter, you will learn how to develop a simple web application that sends a greetings message to the user. A web service project uses WSDL model. The CXF allows you to hide this WSDL model by providing a simple frontend to map Apache CXF APIs to the underlying WSDL.

In this simplest project, the interface of the web service will be directly exposed to the client and the client would use native Apache CXF APIs to call the web service.

First, we will create a web service. Every service has an interface that is exposed to the client. We may write this interface as a simple Apache CXF interface or as a WSDL document. In this Apache CXF-First approach, we will expose our service through a Apache CXF interface.

Developing Web Service

The service that we are going to create on the web will have a single web method called greetings. The method takes a string type argument in which we will send the user's name. The service will send back a greetings message to the caller with the received user name included in the message.

Web Service Interface

To expose the interface of our web service, we will create a Apache CXF interface as follows −

//HelloWorld.java
package com.howcodex.cxf.pojo;
public interface HelloWorld {
   String greetings(String text);
}

The interface has only one method called greetings. The server will implement this interface. In our trivial application, this interface is directly exposed to the client. Typically, in a web service application, you use WSDL to describe the web service interface. In this simple application, we will provide this direct interface to the client developer. The client would then call the greetings message on the server object. So first let us create the web service.

Web Service Implementation

The HelloWorld interface is implemented in the HelloWorldImpl Apache CXF class as shown below −

//HelloWorldImpl.java
package com.howcodex.cxf.pojo;
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String greetings(String text) {
      return "Hi " + text;
   }
}

The greetings method receives a parameter of string type, appends it to a greeting message and returns the resultant string to the caller.

Next, we write the server application to host the HelloWorld service.

Creating Server

The server application consists of two parts −

  • The first part creates a factory for our web service, and

  • The second part writes a main method for instantiating it.

The server uses ServerFactoryBean class provided by CXF libraries to expose our HelloWorld interface to remote clients. Thus, we first instantiate the ServerFactoryBean class and then set its various properties −

ServerFactoryBean factory = new ServerFactoryBean();

We set the service class to be called by calling the setServiceClass method on the factory object −

factory.setServiceClass(HelloWorld.class);

We set the URL for calling our service by calling the factory's setAddress method. Note that the service will be published at this URL.

factory.setAddress("http://localhost:5000/Hello");

In this case, the service is deployed on the embedded server and will be listening to port 5000. You may opt for any port number of your choice.

Before creating the factory, you need to tell the factory about our service implementation class. This is done by calling the setServiceBean method on the factory object as shown here −

factory.setServiceBean(new HelloWorldImpl());

The service bean is set to the instance of our service implementation class. Finally, we create the factory by calling its create method −

factory.create();

Now, as we have developed the factory to run our web service, we will next write a main method to instantiate it and keep it running for some time.

Now, write a main method to instantiate the HelloServer class as follows −

public static void main(String[] args) throws Exception {
   new HelloServer();
   System.out.println("Listening on port 5000 ...");
}

Once instantiated, the HelloServer class will keep running indefinitely. For production deployments, you will definitely keep your server running forever. In the current situation, we would terminate the server after a predetermined time as follows −

Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);

The entire code for the HelloServer class is given below −

//HelloServer.java
//HelloServer.java
package com.howcodex.cxf.pojo;
import org.apache.cxf.frontend.ServerFactoryBean;
public class HelloServer {
   protected HelloServer() throws Exception {
      ServerFactoryBean factory = new ServerFactoryBean();
      factory.setServiceClass(HelloWorld.class);
      factory.setAddress("http://localhost:5000/Hello");
      factory.setServiceBean(new HelloWorldImpl());
      factory.create();
   }
   public static void main(String[] args) throws Exception {
      new HelloServer();
      System.out.println("Listening on port 5000 ...");
      Thread.sleep(5 * 60 * 1000);
      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

The server application that we have created uses ServerFactoryBean class from CXF libraries. We must now include these libraries in our project to successfully compile the HelloServer class. We will use Maven to set up the project dependencies.

Setting up Maven Project

To create a Maven project, type the following command in your command-line window. Note that we have tested this on a Mac machine. For Windows and Linux installations, the instructions may differ at few places.

mvn archetype:generate

When asked for the properties, input the following values −

Define value for property 'groupId': : com.howcodex
Define value for property 'artifactId': : cxf-pojo
Define value for property 'version': 1.0-SNAPSHOT: : 1.0
Define value for property 'package': com.howcodex: : com.howcodex.cxf.pojo

On the completion of the maven command, you will find the appropriate folder structure created in your current folder along with pom.xml file.

The generated directory structure is shown here −

Directory Structure

You will add the CXF dependencies in the pom.xml and also copy the above created Apache CXF files into the appropriate folder of the maven created structure. For your ready reference, we have given below the pom.xml file for the project that we created on our machine.

<?xml version = "1.0" encoding = "UTF-8"?>
<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>com.howcodex</groupId>
   <artifactId>cxf-pojo</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.howcodex.cxf.pojo.HelloServer
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
      
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                           com.howcodex.cxf.pojo.HelloClient
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>

   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
         <type>jar</type>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-simple</artifactId>
         <version>3.3.0</version>
         <type>jar</type>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>
      <!-- Jetty is needed if you're using the CXFServlet -->
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
</project>

The above pom.xml may include additional dependencies which are irrelevant to this project, but are required for our next project in this tutorial. Anyway, there is no harm as such in including additional dependencies.

Project Folder Structure

The project folder structure on my machine after placing the server and client Apache CXF files is shown below for your quick reference −

Project Folder Structure

Running Server

To build the project, use the following command in your command-line window −

mvn clean install

You can start the server using the following command −

mvn -Pserver

This will start the server and you will see the following prompt on the console −

INFO: Creating Service {http://pojo.cxf.howcodex.com/}HelloWorld from class com.howcodex.cxf.pojo.HelloWorld
INFO: Setting the server's publish address to be http://localhost:5000/Hello
Listening on port 5000 ...

Now, in your browser window specify the URL of our published service. You will see the following output −

Output Document Tree

This confirms that our service is running at the specified port on a localhost. Since we did not specify the greetings message in our call, a SOAP fault message is returned to the browser.

You may further test your web service using a SOAP client of your choice. Here we have used Postman to test our server.

The output is as shown here −

Running Server Output

Observe that SOAP Request was hand-coded. After posting the request, the server sent a SOAP Response message, which is seen in the bottom portion of the screen shot.

From this, you can understand that CXF maintains the use of SOAP protocols for both request and response while providing you a unified view to a variety of web technologies that do exist in today's world. This greatly simplifies the web application development.

Our next task is to create a client that will consume the web service that you have created.

Creating Client

In the server application HelloWorld is the interface that exposes our web service. The web service itself just provides a plain greeting message to the client. Usually, the web service interface is exposed to the outside world using WSDL (Web Services Description Language). In this trivial application, we will expose our web service to the client by exposing directly the service interface and that is the HelloWorld.class.

For this purpose, CXF provides a factory class called ClientProxyFactoryBean that allows us to attach to the desired interface to the created factory instance.

First, we create a factory bean instance as follows −

ClientProxyFactoryBean factory = new ClientProxyFactoryBean();

We call the setAddress method on the factory bean instance to set the URL by which our web service can be invoked. In our case, we will use the URL used while creating the server in our earlier step −

factory.setAddress("http://localhost:5000/Hello");

Next, we call the create method on the factory instance to attach our service interface HelloWorld.class to it.

HelloWorld helloServer = factory.create(HelloWorld.class);

Finally, we call the greetings method to invoke the remote web service.

System.out.println(helloServer.greetings(System.getProperty("user.name")));

This would print a greetings message on your console.

The entire source for the client application is shown below −

//HelloClient.java
package com.howcodex.cxf.pojo;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
public class HelloClient {
   public static void main(String[] args) throws Exception {
      ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
      factory.setAddress("http://localhost:5000/Hello");
      HelloWorld helloServer = factory.create(HelloWorld.class);
      System.out.println(helloServer.greetings(System.getProperty("user.name")));
   }
}

Running Client

Make sure that the server is still running on your machine. In case, if it has timed out, restart the server with the following command −

mvn -Pserver

You will see the following message on the console −

Listening on port 5000 ...

Now, before the server times out which we have set to 5 minutes, open another command line window and start the client with the following command −

mvn -Pclient

You will see a message similar to the following on the command line −

Hi howcodex

Note that howcodex is our user name. You will get a greeting with your own name.

In the next chapter, we will learn how to use CXF in a JAX-WS (Apache CXF API for XML Web Services) project.

Advertisements