Apache CXF with JMS


Advertisements

As mentioned earlier, you can use CXF with JMS transport. In this case, the client will send a JMS message to a known Messaging Server. Our server application is continuously listening to the messaging server for the incoming messages. When the message arrives, it processes the message, executes the client request and sends the response as another message to the client.

As earlier, we will first create a sample server application that provides a singular web method called sayHi.

Creating Service Interface

The service interface for our HelloWorld service is shown here −

//HelloWorld.java
package com.howcodex.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public interface HelloWorld {
   @WebMethod
   String sayHi(@WebParam(name = "name") String name);
}

Implementing Service

The implementation of the service interface is defined as follows −

//HelloWorldImpl.java
package com.howcodex.service.impl;

import javax.jws.WebService;
import com.howcodex.service.HelloWorld;

@WebService
public class HelloWorldImpl implements HelloWorld {
   @Override
   public String sayHi(String name) {
      return "Hello " + name;
   }
}

The implementation simply returns a Hello message to the user. As you see, the interface and its implementation are similar to all the earlier projects in this tutorial that you have studied so far.

Now, comes the most important point which is to create a server application that sets up a message queue and keeps on listening to the incoming messages.

Creating Server

In the server application, first we create a JMS end point as follows −

private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
      + "&jndiConnectionFactoryName=ConnectionFactory"
      + "&jndiInitialContextFactory"
      + "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
      + "&jndiURL = tcp://localhost:61616";

Note that we set up a queue on a specified port that lives for a specified amount of time. We now create a messaging service by instantiating org.apache.activemq.broker.BrokerService class. This is a server class for ActiveMQ messaging server.

BrokerService broker = new BrokerService();

You may use any other messaging server of your choice other than ActiveMQ. We now connect this server to a desired URI.

broker.addConnector("tcp://localhost:61616");

We set up the directory for the data storage of the incoming messages −

broker.setDataDirectory("target/activemq-data");

Finally, we start the server using the start method −

broker.start();

Next, we create an instance of our service bean HelloWorld using the server factory bean class as used in our earlier POJO application −

Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);

Next, we set up the JMS endpoint on the factory so that the factory will keep on listening to the incoming messages −

factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);

Finally, we set up the implementer class in the factory and start running it −

factory.setServiceBean(implementor);
factory.create();

At this point your server is up and running. Note that since we have used the factory bean class as in the POJO application, the need for CXFServlet and the web.xml file is not required.

The full server application code is shown here −

//ServerJMS.java
package com.howcodex.server;

import java.util.Collections;
import org.apache.cxf.ext.logging.LoggingFeature;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;
import com.howcodex.service.HelloWorld;
import com.howcodex.service.impl.HelloWorldImpl;
import org.apache.activemq.broker.BrokerService;

public final class ServerJMS {

   private static final String JMS_ENDPOINT_URI = 
      "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
         + "&jndiConnectionFactoryName=ConnectionFactory"
         + "&jndiInitialContextFactory"
         + "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"
         + "&jndiURL = tcp://localhost:61616";

   public static void main(String[] args) throws Exception {

      BrokerService broker = new BrokerService();
      broker.addConnector("tcp://localhost:61616");
      broker.setDataDirectory("target/activemq-data");
      broker.start();

      Object implementor = new HelloWorldImpl();
      JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
      factory.setServiceClass(HelloWorld.class);
      factory.setTransportId
      (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
      factory.setAddress(JMS_ENDPOINT_URI);
      factory.setServiceBean(implementor);
      factory.setFeatures(Collections.singletonList(new LoggingFeature()));
      factory.create();

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

Adding Dependencies

The server application that we have created uses ActiveMQ messaging server. Thus, you will need to add few more dependencies to your project. The complete pom.xml file is shown here for you to understand the additional needed dependencies.

<?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-jms</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   
   <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>

   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.howcodex.server.ServerJMS
                           </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.client.ClientJMS
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>

   <dependencies>
      <dependency>
         <groupId>org.apache.activemq</groupId>
         <artifactId>activemq-broker</artifactId>
         <version>5.15.8</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.activemq</groupId>
         <artifactId>activemq-kahadb-store</artifactId>
         <version>5.15.8</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-jms</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</project>

Running Server

To start running the server, as in the earlier cases, type the following command in your command window −

mvn -Pserver

This will start the ActiveMQ message server, set up the messaging queue and create a factory bean that keeps listening to this queue.

Our next task is to create a client application.

Creating Client

In the client application, first we set up the JMS endpoint same as the one used in the server application −

private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
      + "&jndiConnectionFactoryName=ConnectionFactory"
      + "&jndiInitialContextFactory"
      + " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
      + "&jndiURL = tcp://localhost:61616";

We create a factory as in the POJO application.

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

We set the endpoint URI and the implementer class as follows −

factory.setTransportId (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress (JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);

Finally, we call the service method and print its resultant output −

String reply = client.sayHi("Howcodex");
System.out.println(reply);

The complete client code is given below −

// ClientJMS.java
package com.howcodex.client;

import com.howcodex.service.HelloWorld;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;

public final class ClientJMS {
   private static final String JMS_ENDPOINT_URI =
   "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"
   + "&jndiConnectionFactoryName=ConnectionFactory"
   + "&jndiInitialContextFactory"
   + " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"
   + "&jndiURL = tcp://localhost:61616";

   public static void main(String[] args) throws Exception {
      JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
      factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
      factory.setAddress(JMS_ENDPOINT_URI);
      HelloWorld client = factory.create(HelloWorld.class);
      String reply = client.sayHi("Howcodex");
      System.out.println(reply);
      System.exit(0);
   }
}
Advertisements