Java Connector Architecture (JCA) support for integrating with resource adapters and message endpoints in enterprise application servers.
Spring's JCA support is provided through two main packages:
Base class for message endpoint factories that integrate with JCA-compliant resource adapters.
/**
* Abstract base class for JCA 1.7 MessageEndpointFactory implementations.
* Provides transaction management integration.
*/
public abstract class AbstractMessageEndpointFactory
implements MessageEndpointFactory, BeanNameAware {
/**
* Set the transaction manager to use for transactional endpoints.
* Accepts either TransactionManager or TransactionFactory.
*/
public void setTransactionManager(Object transactionManager);
/**
* Set the JCA TransactionFactory to use for transactional endpoints.
*/
public void setTransactionFactory(TransactionFactory transactionFactory);
/**
* Set the name for transactions created by this endpoint.
*/
public void setTransactionName(String transactionName);
/**
* Set the transaction timeout in seconds.
*/
public void setTransactionTimeout(int transactionTimeout);
/**
* Set the bean name for this endpoint factory.
*/
@Override
public void setBeanName(String beanName);
/**
* Return the activation name for this endpoint.
*/
public String getActivationName();
/**
* Return the endpoint class handled by this factory.
*/
protected abstract Class<?> getEndpointClass();
/**
* Create the actual endpoint instance.
*/
protected abstract AbstractMessageEndpoint createEndpointInternal() throws UnavailableException;
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException;
@Override
public MessageEndpoint createEndpoint(XAResource xaResource, long timeout)
throws UnavailableException;
@Override
public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException;
}Concrete MessageEndpointFactory implementation that wraps a plain message listener object.
/**
* Generic JCA 1.7 MessageEndpointFactory implementation that wraps
* a plain message listener object.
*/
public class GenericMessageEndpointFactory extends AbstractMessageEndpointFactory {
/**
* Set the message listener object to expose as endpoint.
*/
public void setMessageListener(Object messageListener);
/**
* Return the configured message listener object.
*/
protected Object getMessageListener();
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException;
@Override
protected AbstractMessageEndpoint createEndpointInternal() throws UnavailableException;
}Usage Example:
@Configuration
public class JcaConfig {
@Bean
public GenericMessageEndpointFactory messageEndpointFactory(
MyMessageListener listener,
JtaTransactionManager transactionManager) {
GenericMessageEndpointFactory factory = new GenericMessageEndpointFactory();
factory.setMessageListener(listener);
factory.setTransactionManager(transactionManager);
factory.setTransactionName("MessageEndpointTransaction");
factory.setTransactionTimeout(30);
return factory;
}
}Manager that activates a JCA message endpoint using a given MessageEndpointFactory and ResourceAdapter.
/**
* Generic manager for JCA 1.7 message endpoints, activating a specific
* message endpoint with a ResourceAdapter.
*/
public class GenericMessageEndpointManager
implements SmartLifecycle, InitializingBean, DisposableBean {
/**
* Set the JCA ResourceAdapter to use for activation.
*/
public void setResourceAdapter(ResourceAdapter resourceAdapter);
/**
* Return the configured ResourceAdapter.
*/
public ResourceAdapter getResourceAdapter();
/**
* Set the MessageEndpointFactory to activate.
*/
public void setMessageEndpointFactory(MessageEndpointFactory messageEndpointFactory);
/**
* Return the configured MessageEndpointFactory.
*/
public MessageEndpointFactory getMessageEndpointFactory();
/**
* Set the JCA ActivationSpec to use for activation.
*/
public void setActivationSpec(ActivationSpec activationSpec);
/**
* Return the configured ActivationSpec.
*/
public ActivationSpec getActivationSpec();
/**
* Set whether to automatically start the endpoint on context refresh.
* Default is true.
*/
public void setAutoStartup(boolean autoStartup);
@Override
public boolean isAutoStartup();
/**
* Set the startup phase for this lifecycle bean.
*/
public void setPhase(int phase);
@Override
public int getPhase();
@Override
public void afterPropertiesSet() throws ResourceException;
@Override
public void start();
@Override
public void stop();
@Override
public void stop(Runnable callback);
@Override
public boolean isRunning();
@Override
public void destroy();
}Usage Example:
@Configuration
public class MessageEndpointConfig {
@Bean
public GenericMessageEndpointManager endpointManager(
ResourceAdapter resourceAdapter,
GenericMessageEndpointFactory endpointFactory,
ActivationSpec activationSpec) {
GenericMessageEndpointManager manager = new GenericMessageEndpointManager();
manager.setResourceAdapter(resourceAdapter);
manager.setMessageEndpointFactory(endpointFactory);
manager.setActivationSpec(activationSpec);
manager.setAutoStartup(true);
return manager;
}
}FactoryBean that creates a local JCA connection factory for use in standalone applications.
/**
* FactoryBean that creates a local JCA connection factory in standalone mode,
* without support for XA transactions.
*/
public class LocalConnectionFactoryBean
implements FactoryBean<Object>, InitializingBean {
/**
* Set the JCA ManagedConnectionFactory to use.
*/
public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory);
/**
* Set the JCA ConnectionManager to use.
* If not specified, a default ConnectionManager will be created.
*/
public void setConnectionManager(ConnectionManager connectionManager);
@Override
public void afterPropertiesSet() throws ResourceException;
@Override
public Object getObject();
@Override
public Class<?> getObjectType();
@Override
public boolean isSingleton();
}Usage Example:
@Configuration
public class ConnectionConfig {
@Bean
public LocalConnectionFactoryBean connectionFactory(
ManagedConnectionFactory managedConnectionFactory) {
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
factory.setManagedConnectionFactory(managedConnectionFactory);
return factory;
}
@Bean
public DataSource dataSource(Object connectionFactory) throws Exception {
// Use the connection factory
return (DataSource) connectionFactory;
}
}FactoryBean that bootstraps and exposes a JCA ResourceAdapter in standalone mode.
/**
* FactoryBean that bootstraps a JCA ResourceAdapter in standalone mode,
* starting and stopping it as part of the application lifecycle.
*/
public class ResourceAdapterFactoryBean
implements FactoryBean<ResourceAdapter>, InitializingBean, DisposableBean {
/**
* Set the ResourceAdapter class to instantiate.
*/
public void setResourceAdapterClass(Class<? extends ResourceAdapter> resourceAdapterClass);
/**
* Set the ResourceAdapter instance directly.
*/
public void setResourceAdapter(ResourceAdapter resourceAdapter);
/**
* Set the JCA BootstrapContext to use for starting the ResourceAdapter.
*/
public void setBootstrapContext(BootstrapContext bootstrapContext);
/**
* Set the JCA WorkManager to include in the BootstrapContext.
*/
public void setWorkManager(WorkManager workManager);
/**
* Set the JCA XATerminator to include in the BootstrapContext.
*/
public void setXaTerminator(XATerminator xaTerminator);
@Override
public void afterPropertiesSet() throws ResourceException;
@Override
public ResourceAdapter getObject();
@Override
public Class<? extends ResourceAdapter> getObjectType();
@Override
public boolean isSingleton();
@Override
public void destroy();
}Usage Example:
@Configuration
public class ResourceAdapterConfig {
@Bean
public ResourceAdapterFactoryBean resourceAdapter(
WorkManager workManager,
XATerminator xaTerminator) {
ResourceAdapterFactoryBean factory = new ResourceAdapterFactoryBean();
factory.setResourceAdapterClass(MyResourceAdapter.class);
factory.setWorkManager(workManager);
factory.setXaTerminator(xaTerminator);
return factory;
}
}Simple implementation of JCA BootstrapContext interface for standalone usage.
/**
* Simple implementation of the JCA 1.7 BootstrapContext interface,
* for use in standalone applications.
*/
public class SimpleBootstrapContext implements BootstrapContext {
/**
* Create a new SimpleBootstrapContext for the given WorkManager.
*/
public SimpleBootstrapContext(WorkManager workManager);
/**
* Create a new SimpleBootstrapContext for the given WorkManager and XATerminator.
*/
public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator);
/**
* Create a new SimpleBootstrapContext with WorkManager, XATerminator,
* and TransactionSynchronizationRegistry.
*/
public SimpleBootstrapContext(
WorkManager workManager,
XATerminator xaTerminator,
TransactionSynchronizationRegistry transactionSynchronizationRegistry);
@Override
public WorkManager getWorkManager();
@Override
public XATerminator getXATerminator();
@Override
public Timer createTimer() throws UnavailableException;
@Override
public boolean isContextSupported(Class<? extends WorkContext> workContextClass);
@Override
public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry();
}Usage Example:
@Configuration
public class BootstrapContextConfig {
@Bean
public SimpleBootstrapContext bootstrapContext(
WorkManager workManager,
XATerminator xaTerminator,
TransactionSynchronizationRegistry txSyncRegistry) {
return new SimpleBootstrapContext(
workManager,
xaTerminator,
txSyncRegistry
);
}
@Bean
public ResourceAdapterFactoryBean resourceAdapter(SimpleBootstrapContext bootstrapContext) {
ResourceAdapterFactoryBean factory = new ResourceAdapterFactoryBean();
factory.setResourceAdapterClass(MyResourceAdapter.class);
factory.setBootstrapContext(bootstrapContext);
return factory;
}
}@Configuration
public class CompleteJcaConfig {
@Bean
public SimpleBootstrapContext bootstrapContext() {
// Create work manager and XA terminator
WorkManager workManager = new SimpleWorkManager();
XATerminator xaTerminator = new SimpleXATerminator();
return new SimpleBootstrapContext(workManager, xaTerminator);
}
@Bean
public ResourceAdapterFactoryBean resourceAdapter(SimpleBootstrapContext bootstrapContext) {
ResourceAdapterFactoryBean factory = new ResourceAdapterFactoryBean();
factory.setResourceAdapterClass(MyResourceAdapter.class);
factory.setBootstrapContext(bootstrapContext);
return factory;
}
@Bean
public GenericMessageEndpointFactory endpointFactory(
MyMessageListener listener,
JtaTransactionManager transactionManager) {
GenericMessageEndpointFactory factory = new GenericMessageEndpointFactory();
factory.setMessageListener(listener);
factory.setTransactionManager(transactionManager);
return factory;
}
@Bean
public GenericMessageEndpointManager endpointManager(
ResourceAdapter resourceAdapter,
GenericMessageEndpointFactory endpointFactory,
ActivationSpec activationSpec) {
GenericMessageEndpointManager manager = new GenericMessageEndpointManager();
manager.setResourceAdapter(resourceAdapter);
manager.setMessageEndpointFactory(endpointFactory);
manager.setActivationSpec(activationSpec);
return manager;
}
}@Configuration
public class StandaloneJcaConfig {
@Bean
public ManagedConnectionFactory managedConnectionFactory() {
MyManagedConnectionFactory mcf = new MyManagedConnectionFactory();
mcf.setServerName("localhost");
mcf.setPortNumber(5432);
return mcf;
}
@Bean
public LocalConnectionFactoryBean connectionFactory(
ManagedConnectionFactory managedConnectionFactory) {
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
factory.setManagedConnectionFactory(managedConnectionFactory);
return factory;
}
@Bean
public DataSource dataSource() throws Exception {
return (DataSource) connectionFactory(managedConnectionFactory()).getObject();
}
}public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
// Process message
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
String text = textMessage.getText();
processMessage(text);
} catch (JMSException e) {
throw new RuntimeException("Failed to process message", e);
}
}
}
private void processMessage(String message) {
// Business logic
}
}
@Configuration
public class ListenerConfig {
@Bean
public MyMessageListener messageListener() {
return new MyMessageListener();
}
@Bean
public GenericMessageEndpointFactory endpointFactory(
MyMessageListener listener,
JtaTransactionManager transactionManager) {
GenericMessageEndpointFactory factory = new GenericMessageEndpointFactory();
factory.setMessageListener(listener);
factory.setTransactionManager(transactionManager);
factory.setTransactionName("MessageProcessing");
return factory;
}
}AbstractMessageEndpointFactory provides transaction management for message endpointsGenericMessageEndpointFactory wraps any message listener object as a JCA message endpointGenericMessageEndpointManager handles the lifecycle of message endpoint activation with a resource adapterLocalConnectionFactoryBean creates non-XA connection factories for standalone useResourceAdapterFactoryBean manages ResourceAdapter lifecycle including bootstrap and shutdownSimpleBootstrapContext provides basic JCA infrastructure for standalone applicationssetAutoStartup(false) on GenericMessageEndpointManager to control endpoint activation manuallysetTransactionTimeout()