HelloWorld Resource Adapter tutorial

[Updated] In this tutorial we will show how you can create build and deploy an HelloWorld Resource Adapter and deploy it on WildFly 10.

The Java Connector Architecture (JCA) defines a standard architecture for connecting the Java EE platform to heterogeneous Enterprise Information Systems (EIS). Examples of EISs include Enterprise Resource Planning (ERP), mainframe transaction processing (TP), database and messaging systems.

The IronJacamar project implements the Java Connector Architecture 1.6 specification and is available in a stable version, and a developer version.

In order to create your own Adapter, you need to define your Contract in a Resource Adapter Connection class, define a Factory for creating your Connection to the Resource Adapter and provide the Connector Managed classes which are used to creates a new physical connection to the underlying EIS resource manager and communicate with it.

Create a Resource Adapter from a Maven project

We will first show how to create a new Resource Adapter from a Maven project. Create a new Maven Java Project as follows:

$ mvn archetype:generate -DgroupId=com.sample -DartifactId=jcademo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

We will not expose all the project classes but just the core parts of it (You can the project on github at. https://github.com/fmarchioni/mastertheboss/tree/master/jca-demo).

The first step will be defining your connector exposed methods in the HelloWorldConnection class

package com.sample.adapter;
 
public interface HelloWorldConnection
{

  public String helloWorld();
  public String helloWorld(String name);

  public void close();
}

Next, your main concern will be implementing the Managed Connection class which contains the actual implementation for our method write which writes our Hello World message to a Stream:

package com.sample.adapter;


import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ConnectionEventListener;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.LocalTransaction;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionMetaData;

import javax.security.auth.Subject;
import javax.transaction.xa.XAResource;


public class HelloWorldManagedConnection implements ManagedConnection
{
   /** The logger */
   private static Logger log = Logger.getLogger("HelloWorldManagedConnection");

   /** MCF */
   private HelloWorldManagedConnectionFactory mcf;

   /** Log writer */
   private PrintWriter logWriter;

   /** Listeners */
   private List<ConnectionEventListener> listeners;

   /** Connection */
   private Object connection;


   public HelloWorldManagedConnection(HelloWorldManagedConnectionFactory mcf)
   {
      this.mcf = mcf;
      this.logWriter = null;
      this.listeners = new ArrayList<ConnectionEventListener>(1);
      this.connection = null;
   }


   public Object getConnection(Subject subject,
                               ConnectionRequestInfo cxRequestInfo) 
      throws ResourceException
   {
      connection = new HelloWorldConnectionImpl(this, mcf);

      return connection;
   }


   public void associateConnection(Object connection) throws ResourceException
   {
      this.connection = connection;
   }


   public void cleanup() throws ResourceException
   {
   }


   public void destroy() throws ResourceException
   {
      this.connection = null;
   }


   public void addConnectionEventListener(ConnectionEventListener listener)
   {
      if (listener == null)
         throw new IllegalArgumentException("Listener is null");

      listeners.add(listener);
   }

   public void removeConnectionEventListener(ConnectionEventListener listener)
   {
      if (listener == null)
         throw new IllegalArgumentException("Listener is null");

      listeners.remove(listener);
   }


   public PrintWriter getLogWriter() throws ResourceException
   {
      return logWriter;
   }


   public void setLogWriter(PrintWriter out) throws ResourceException
   {
      this.logWriter = out;
   }


   public LocalTransaction getLocalTransaction() throws ResourceException
   {
      throw new NotSupportedException("LocalTransaction not supported");
   }


   public XAResource getXAResource() throws ResourceException
   {
      throw new NotSupportedException("GetXAResource not supported");
   }


   public ManagedConnectionMetaData getMetaData() throws ResourceException
   {
      return new HelloWorldManagedConnectionMetaData();
   }


   String helloWorld(String name)
   {
      return "Hello World, " + name + " !";
   }


   void closeHandle(HelloWorldConnection handle)
   {
      ConnectionEvent event = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED);
      event.setConnectionHandle(handle);

      for (ConnectionEventListener cel : listeners)
      {
         cel.connectionClosed(event);
      }
   }
}

Finally, the ConnectionImpl class which sends data to the server:

package com.sample.adapter;

import java.util.logging.Logger;


public class HelloWorldConnectionImpl implements HelloWorldConnection
{
   /** The logger */
   private static Logger log = Logger.getLogger("HelloWorldConnectionImpl");

   /** ManagedConnection */
   private HelloWorldManagedConnection mc;

   /** ManagedConnectionFactory */
   private HelloWorldManagedConnectionFactory mcf;


   public HelloWorldConnectionImpl(HelloWorldManagedConnection mc,
                                   HelloWorldManagedConnectionFactory mcf)
   {
      this.mc = mc;
      this.mcf = mcf;
   }


   public String helloWorld()
   {
      return helloWorld(((HelloWorldResourceAdapter)mcf.getResourceAdapter()).getName());
   }


   public String helloWorld(String name)
   {
      return mc.helloWorld(name);
   }

   public void close()
   {
      mc.closeHandle(this);
   }
}

Done with the Java classes. We will now add into the META-INF folder the ironjacamar.xml file which contains the connection definition which will be used by the resource adapter clients:

<ironjacamar>
  <connection-definitions>
    <connection-definition 
     class-name="com.sample.adapter.HelloWorldManagedConnectionFactory" 
     jndi-name="java:/eis/HelloWorld"/>
  </connection-definitions>
</ironjacamar>

In order to build the project, we will add the required dependencies to the pom.xml, including the RAR Maven plugin which will generate a RAR file, including the ironjacamar.xml descriptor:

<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.sample</groupId>
	<artifactId>jca-demo</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>

	<name>jca-demo</name>
	<url>http://maven.apache.org</url>

	<properties>
		<version.org.jboss.ironjacamar>1.0.9.Final</version.org.jboss.ironjacamar>
		 <version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.jboss.ironjacamar</groupId>
			<artifactId>ironjacamar-spec-api</artifactId>
			<version>${version.org.jboss.ironjacamar}</version>
			<scope>provided</scope>
		</dependency>

	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.jboss.ironjacamar</groupId>
				<artifactId>ironjacamar-depchain</artifactId>
				<version>${version.org.jboss.ironjacamar}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>

		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.4</version>
				<configuration>
					<excludes>
						<exclude>**/META-INF/*</exclude>
					</excludes>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-rar-plugin</artifactId>
				<version>2.2</version>
				<executions>
					<execution>
						<id>test</id>
						<goals>
							<goal>rar</goal>
						</goals>
						<configuration>

							<raXmlFile>src/main/resources/META-INF/ironjacamar.xml</raXmlFile>
						</configuration>
					</execution>
				</executions>
			</plugin>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>${version.wildfly.maven.plugin}</version>
            </plugin>
		</plugins>
	</build>

</project>

Build and deploy the project with:

$ mvn clean install rar:rar wildfly:deploy

Finally, here's a Test Servlet which can be used to test our resource adapter:

package com.sample;

import java.io.IOException;
import java.io.PrintWriter;

import javax.annotation.Resource;
import javax.resource.ResourceException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

 import com.sample.adapter.HelloWorldConnection;
 import com.sample.adapter.HelloWorldConnectionFactory;

 
@WebServlet("/TestRA")
public class TestRA extends HttpServlet {
	private static final long serialVersionUID = 1L;
	@Resource(mappedName = "java:/eis/HelloWorld")
	private HelloWorldConnectionFactory connectionFactory;

	 public TestRA() {
	        super();
	        
	    }
	    /**
	     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	     */
	    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    	  String result = null;
	  	  HelloWorldConnection connection = null;
	        try {
	         	 connection = connectionFactory.getConnection();	  	       
		         result = connection.helloWorld();
		       
	        } catch (ResourceException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
 

	        PrintWriter out = response.getWriter();
	        out.println(result);

	        out.flush();
	      //  connection.close();
	    }

 
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

In order to be able to run your client application provide a dependency through the WEB-INF/jboss-deployment-structure.xml file as follows:

<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="deployment.jca-demo-1.0.rar" />
    </dependencies>
  </deployment>
</jboss-deployment-structure> 

Now test your application:

$ curl http://localhost:8080/raclient/TestRA

HelloWorld WildFly!

Build the Project with Eclipse

If you are not using Maven to build your projects, you can still use a Wizard which is built-in with Eclipse. All you have to do is creating a new Connector Project from Eclipse (You can also use an ordinary Java Project, however the Connector project has the advantage of automatically publishing the project as RAR archive to WildFly ):

jca tutorial jboss rar resource adapter 

Your Connector classes will be, by default, placed into the connectorModule folder:

jca tutorial jboss rar resource adapter

Finally, the last screenshot allows you to include or not the standard descriptor for the resource adapter (ra.xml). This is not a mandatory step as we will use the custom resource adapter from the IronJacamer project named ironjacamar.xml.

jca tutorial jboss rar resource adapter

Finish by copying the source from guthub into the connectorModule folder and you are done!

References: http://www.ironjacamar.org/doc/userguide/1.2/en-US/html_single/index.html#sample_helloworld_resourceadpater

Follow us on Twitter