The Resource Adapter Examples

This chapter describes two examples that demonstrate how to use resource adapters in Jakarta EE applications and how to implement simple resource adapters.

Overview of the Resource Adapter Examples

The trading example shows how to use a simple custom client interface to connect to an EIS from a web application. The resource adapter in this example implements the outbound contract and the custom client interface. The traffic example shows how to use a message-driven bean (MDB) to process traffic information updates from an EIS. The resource adapter in this example implements the inbound and work management contracts.

The trading Example

The trading example demonstrates how to implement and use a simple outbound resource adapter that submits requests to a legacy EIS using a TCP socket. The example demonstrates the scenario in Figure 1, “The trading Example” and consists of the following modules:

  • trading-eis: A Java SE program that simulates a legacy EIS

  • trading-rar: The outbound resource adapter implementation

  • trading-war: A web application that uses the resource adapter

  • trading-ear: An enterprise archive that contains the resource adapter and the web application

This figure shows the trading example components: a deployed WAR and RAR that communicate with the EIS over a TCP socket.
Figure 1. The trading Example

The trading-eis module is an auxiliary project that resembles a legacy stock trading execution platform. It contains a Java SE program that listens for trading requests in plain text on a TCP socket. The program replies to trading requests with a status value, a confirmation number, and the dollar amounts for the requested shares and fees. For example, a request-response pair would look like this:

>> BUY 1000 ZZZZ MARKET
<< EXECUTED #1234567 TOTAL 50400.00 FEE 252.00

The trading-rar module implements the outbound contract of the Jakarta Connectors to submit requests and obtain responses from the legacy stock trading execution platform. The trading-rar module provides and implements a custom client interface for Jakarta EE applications to use. This interface is simpler than the Common Client Interface (CCI).

The trading-war module is a web application with a Jakarta Faces interface and a managed bean. This application enables clients to submit trades to the EIS using the resource adapter provided by the trading-rar module. The trading-war module uses the custom client interface provided by the resource adapter to obtain connections to the EIS.

Using the Outbound Resource Adapter

In most cases, Jakarta EE application developers use outbound resource adapters developed by a third party. Outbound resource adapters either implement the Common Client Interface (CCI) or provide a custom interface for applications to interact with the EIS. Outbound resource adapters provide Jakarta EE applications with the following elements:

  • Connection factories

  • Connection handles

  • Other interfaces and objects specific to the EIS domain

Jakarta EE applications obtain an instance of the connection factory via resource injection and then use the factory object to obtain connection handles to the EIS. The connection handles enable the application to make requests and obtain information from the EIS.

The trading-rar module provides a custom client interface that consists of the classes listed in Classes and Interfaces in the trading-rar module.

Classes and Interfaces in the trading-rar module
API Component Description

TradeOrder

Represents a trade order for the EIS

TradeResponse

Represents a response from the EIS to a trade request

TradeConnection

Represents a connection handle to the EIS

Provides a method for applications to submit trades to the EIS

TradeConnectionFactory

Enables applications to obtain connection handles to the EIS

TradeProcessingException

Indicates that a problem occurred processing a trade request

The ResourceAccessBean managed bean in the trading-war module configures a connection factory for the trading-rar resource adapter by using the @ConnectionFactoryDefinition annotation as follows:

@Named
@SessionScoped
@ConnectionFactoryDefinition(
    name = "java:comp/env/eis/TradeConnectionFactory",
    interfaceName = "ee.jakarta.tutorial.trading.rar.api.TradeConnectionFactory",
    resourceAdapter = "#trading-rar",
    minPoolSize = 5,
    transactionSupport =
            TransactionSupport.TransactionSupportLevel.NoTransaction
)
public class ResourceAccessBean implements Serializable { ... }

The name parameter specifies the JNDI name for the connection factory. This example registers the connection factory in the java:comp scope. You can use the ConnectionFactoryDefinition annotation to specify a different scope, such as java:global, java:app, or java:module. The AdministeredObjectDefinition annotation also enables you to register administered connector objects in the JNDI namespace.

The interfaceName parameter specifies the interface implemented by the connection factory included in the resource adapter. In this example, this is a custom interface.

The resourceAdapter parameter specifies the name of the resource adapter that contains the connection factory implementation. The # prefix in #trading-rar indicates that trading-rar is an embedded resource adapter that is bundled in the same EAR as this web application.

You can also configure a connection factory for a previously deployed outbound resource adapter using the administration commands from your application server. However, this is a vendor-specific procedure.

The managed bean obtains a connection factory object using resource injection as follows:

...
public class ResourceAccessBean implements Serializable {
    @Resource(lookup = "java:comp/env/eis/TradeConnectionFactory")
    private TradeConnectionFactory connectionFactory;
    ...
}

The managed bean uses the connection factory to obtain connection handles as follows:

TradeConnection connection = connectionFactory.getConnection();

The resource adapter returns a connection handle associated with a physical connection to the EIS. Once a connection handle is available, the managed bean submits a trade and obtains the response as follows:

TradeOrder order = new TradeOrder();
order.setNShares(1000);
order.setTicker(TradeOrder.Ticker.YYYY);
order.setOrderType(TradeOrder.OrderType.BUY);
order.setOrderClass(TradeOrder.OrderClass.MARKET);
...
try {
    TradeResponse response = connection.submitOrder(order);
    ...
} catch (TradeProcessingException ex) { ... }

Implementing the Outbound Resource Adapter

The trading-rar module implements the outbound contract and a custom client interface for the simple legacy stock trading platform EIS used in this example. The architecture of the outbound resource adapter is shown in Figure 2, “Architecture of the trading Example”.

This figure shows the classes in each of the modules of the trading example.
Figure 2. Architecture of the trading Example

The trading-rar module implements the interfaces listed in Interfaces Implemented in the trading-rar Module.

Interfaces Implemented in the trading-rar Module
Package Interface Description

jakarta.resource.spi

ResourceAdapter

Defines the lifecycle methods of the resource adapter

jakarta.resource.spi

ManagedConnectionFactory

Defines a connection factory that the connection manager from the application server uses to obtain physical connections to the EIS

jakarta.resource.spi

ManagedConnection

Defines a physical connection to the EIS that can be managed by the connection manager

trading.rar.api

TradeConnectionFactory

Defines a connection factory that applications use to obtain connection handles

trading.rar.api

TradeConnection

Defines a connection handle that applications use to interact with the EIS

When the trading-ear archive is deployed and a connection pool resource is configured as described in Using the Outbound Resource Adapter, the application server creates TradeConnectionFactory objects that applications can obtain using resource injection. The TradeConnectionFactory implementation delegates creating connections to the connection manager provided by the application server.

The connection manager uses the ManagedConnectionFactory implementation to obtain physical connections to the EIS and maintains a pool of active physical connections. When an application requests a connection handle, the connection manager associates a connection from the pool with a new connection handle that the application can use. Connection pooling improves application performance and simplifies resource adapter development.

For more details, see the code and the comments in the trading-rar module.

Running the trading Example

You can use either NetBeans IDE or Maven to build, package, deploy, and run the trading example.

To Run the trading Example Using NetBeans IDE

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

  2. From the File menu, choose Open Project.

  3. In the Open Project dialog box, navigate to:

    jakartaee-examples/tutorial/connectors
  4. Select the trading folder.

  5. Click Open Project.

  6. In the Projects tab, expand the trading node.

  7. Right-click the trading-eis module and select Open Project.

  8. Right-click the trading-eis project and select Run.

    The messages from the EIS appear in the Output tab:

    Trade execution server listening on port 4004.
  9. Right-click the trading-ear project and select Build.

    This command packages the resource adapter and the web application in an EAR file and deploys it to GlassFish Server.

  10. Open the following URL in a web browser:

    http://localhost:8080/trading/

    The web interface enables you to connect to the EIS and submit trades. The server log shows the requests from the web application and the call sequence that provides connection handles from the resource adapter.

  11. Before undeploying the trading-ear application, close the trading-eis application from the status bar.

To Run the trading Example Using Maven

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

  2. In a terminal window, go to:

    jakartaee-examples/tutorial/connectors/trading/
  3. Enter the following command:

    mvn install

    This command builds and packages the resource adapter and the web application into an EAR archive and deploys it to GlassFish Server.

  4. In the same terminal window, go to the trading-eis directory:

    cd trading-eis
  5. Enter the following command to run the trade execution platform:

    mvn exec:java

    The messages from the EIS appear in the terminal window:

    Trade execution server listening on port 4004.
  6. Open the following URL in a web browser:

    http://localhost:8080/trading/

    The web interface enables you to connect to the EIS and submit trades. The server log shows the requests from the web application and the call sequence that provides connection handles from the resource adapter.

  7. Before undeploying the trading-ear application, press Ctrl+C on the terminal window to close the trading-eis application.

The traffic Example

The traffic example demonstrates how to implement and use a simple inbound resource adapter that receives data from a legacy EIS using a TCP socket.

The example is in the jakartaee-examples/tutorial/connectors/traffic directory. See Using the Tutorial Examples for basic information on building and running sample applications.

The example demonstrates the scenario in Figure 3, “The traffic Example” and consists of the following modules:

  • traffic-eis: A Java SE program that simulates an EIS

  • traffic-rar: The inbound resource adapter implementation

  • traffic-ejb: A message-driven bean that is the endpoint for incoming messages

  • traffic-war: A web application that displays information from the message-driven bean

  • traffic-ear: An enterprise archive that contains the resource adapter, the message-driven bean, and the web application

This figure shows the components of the traffic example: a WAR communicating with an enterprise bean using a JMS topic, and a RAR communicating with an EIS over a TCP socket.
Figure 3. The traffic Example

The traffic-eis module is an auxiliary project that resembles a legacy traffic information system. It contains a Java SE program that sends traffic status updates for several cities to any subscribed client. The program sends the updates in JSON format over a TCP socket. For example, a traffic update looks like this:

{"report":[
    {"city":"City1", "access":"AccessA", "status":"GOOD"},
    {"city":"City1", "access":"AccessB", "status":"CONGESTED"},
    ...
    {"city":"City5", "access":"AccessE", "status":"SLOW"}
 ]}

The traffic-rar module implements the inbound contract of the Jakarta Connectors specification. This module subscribes to the traffic information system using the TCP port indicated by the configuration provided by the MDB and invokes the methods of the MDB to process traffic information updates.

The traffic-ejb module contains a message-driven bean that activates the resource adapter with a configuration parameter (the TCP port to subscribe to the traffic information system). The MDB contains a method to process the traffic information updates. This method filters the updates for a particular city and publishes the results to a Jakarta Messaging topic.

The traffic-war module contains a message-driven bean that receives filtered traffic information updates from the Jakarta Messaging topic asynchronously and sends them to the clients using a WebSocket endpoint.

Using the Inbound Resource Adapter

In most cases, Jakarta EE application developers use inbound resource adapters developed by a third party. To use an inbound resource adapter, a Jakarta EE application includes a message-driven bean with the following characteristics.

  • The MDB implements the business interface defined by the resource adapter.

  • The MDB specifies configuration parameters to activate the resource adapter.

The business interface defined by the resource adapter is not specified in the Jakarta Connectors specification; it is specific to the EIS.

The MDB in this example is defined as follows:

@MessageDriven(
    activationConfig = {
      @ActivationConfigProperty(propertyName = "port",
                                propertyValue = "4008")
    }
)
public class TrafficMdb implements TrafficListener { ... }

The TrafficListener interface is defined in the API package of the resource adapter. The resource adapter requires the MDB to provide the port property.

When the MDB is deployed, it activates the traffic-rar resource adapter, which invokes the methods of the MDB to process traffic information updates. Then the MDB filters the updates for a particular city and publishes the results to a Jakarta Messaging topic.

In this particular example, the TrafficListener interface is empty. In addition to this interface, the resource adapter provides the TrafficCommand annotation and uses reflection to discover which methods in the MDB are decorated with this annotation:

@MessageDriven(...)
public class TrafficMdb implements TrafficListener {

    @TrafficCommand(name="report", info="Process report")
    public void processReport(String jsonReport) { ... }
    ...
}

This approach enables you to adapt the MDB to support new features in the EIS without having to modify the TrafficListener interface or the resource adapter module.

Implementing the Inbound Resource Adapter

The traffic-rar module implements the Jakarta Connectors inbound resource adapter contract for the simple traffic information system (EIS) used in this example. The architecture of the inbound resource adapter is shown in Figure 4, “Architecture of the traffic Example”.

This figure shows the classes in each of the components of the traffic example.
Figure 4. Architecture of the traffic Example

The traffic-rar module implements the interfaces listed in Interfaces Implemented in the traffic-rar Module.

Interfaces Implemented in the traffic-rar Module
Package Interface Description

jakarta.resource.spi

ResourceAdapter

Defines the lifecycle methods of the resource adapter.

jakarta.resource.spi

ActivationSpec

Defines the configuration parameters that the MDB provides to activate the inbound resource adapter.

jakarta.resource.spi

Work

The traffic service subscriber implements this interface from the work management contract to wait for traffic updates on a separate thread.

When an MDB activates the inbound resource adapter, the container invokes the endpointActivation method in the TrafficResourceAdapter class:

@Connector(...)
public class TrafficResourceAdapter implements ResourceAdapter, Serializable {
    ...
    @Override
    public void endpointActivation(MessageEndpointFactory endpointFactory,
                                   ActivationSpec spec)
                                   throws ResourceException {
        Class endpointClass = endpointFactory.getEndpointClass();
        /* this method is called from a new thread in the example:
        MessageEndpoint endpoint = endpointFactory.createEndpoint(null); */
    }
}

The getEndpointClass method returns the Class type of the MDB performing the activation, which enables the resource adapter to use reflection to find methods annotated with @TrafficCommand in the MDB.

The createEndpoint method returns an instance of the MDB. The resource adapter uses this instance to invoke the methods of the MDB when it receives requests from the EIS.

After obtaining the message endpoint instance (MDB), the resource adapter uses the work management contract to create the traffic service subscriber thread that receives traffic updates from the EIS. The resource adapter obtains the WorkManager instance from the bootstrap context as follows:

WorkManager workManager;
...
@Override
public void start(BootstrapContext ctx) ... {
    workManager = ctx.getWorkManager();
}

The resource adapter schedules the traffic service subscriber thread using the work manager:

tSubscriber = new TrafficServiceSubscriber(tSpec, endpoint);
workManager.scheduleWork(tSubscriber);

The TrafficServiceSubscriber class implements the jakarta.resource.spi.Work interface from the work management contract.

The traffic service subscriber thread uses reflection to invoke the methods in the MDB:

private String callMdb(MessageEndpoint mdb, Method command,
                       String... params) ... {
    String resp;
    /* this code contains proper exception handling in the sources */
    mdb.beforeDelivery(command);
    Object ret = command.invoke(mdb, (Object[]) params);
    resp = (String) ret;
    mdb.afterDelivery();
    return resp;
}

For more details, see the code and the comments in the traffic-rar module.

Running the traffic Example

You can use either NetBeans IDE or Maven to build, package, deploy, and run the traffic example.

To Run the traffic Example Using NetBeans IDE

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

  2. From the File menu, choose Open Project.

  3. In the Open Project dialog box, navigate to:

    jakartaee-examples/tutorial/connectors
  4. Select the traffic folder.

  5. Click Open Project.

  6. In the Projects tab, expand the traffic node.

  7. Right-click the traffic-eis module and select Open Project.

  8. Right-click the traffic-eis project and select Run.

    The messages from the EIS appear on the Output tab:

    Traffic EIS accepting connections on port 4008
  9. In the Projects tab, right-click the traffic project and select Clean and Build.

    This command builds and packages the resource adapter, the MDB, and the web application into an EAR archive and deploys it. The server log shows the call sequence that activates the resource adapter and the filtered traffic updates for City1.

  10. Open the following URL in a web browser:

    http://localhost:8080/traffic/

    The web interface shows filtered traffic updates for City1 every few seconds.

  11. After undeploying the traffic-ear application, close the traffic-eis application from the status bar.

To Run the traffic Example Using Maven

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

  2. In a terminal window, go to:

    jakartaee-examples/tutorial/connectors/traffic/traffic-eis/
  3. Enter the following command in the terminal window:

    mvn install

    This command builds and packages the traffic EIS.

  4. Enter the following command in the terminal window:

    mvn exec:java

    The messages from the EIS appear in the terminal window:

    Traffic EIS accepting connections on port 4008

    Leave this terminal window open.

  5. Open a new terminal window and go to:

    jakartaee-examples/tutorial/connectors/traffic/
  6. Enter the following command:

    mvn install

    This command builds and packages the resource adapter, the MDB, and the web application into an EAR archive and deploys it. The server log shows the call sequence that activates the resource adapter and the filtered traffic updates for City1.

  7. Open the following URL in a web browser:

    http://localhost:8080/traffic/

    The web interface shows the filtered traffic updates for City1 every few seconds.

  8. After undeploying the traffic-ear application, press Ctrl+C in the first terminal window to close the traffic-eis application.