When I configure the Recovery Manager for JBoss Messaging, Why do I get the error,
"[com.arjuna.ats.jta.logging.loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa] [com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa] Could not find new XAResource to use for recovering non-serializable XAResource"
This error occurs because because the recovery data being passed back to arjuna and the recovery manager are not valid for the local server.
What is Recovery and what does the Recovery Manager do?
From the Arjuna Failure Recovery Guide.
"The Recovery Manager is a daemon process responsible for performing crash recovery. Only one Recovery Manager runs per node. The Object Store provides persistent data storage for transactions to log data. During normal transaction processing each transaction will log persistent data needed for the commit phase to the Object Store. On successfully committing a transaction this data is removed, however if the transaction fails then this data remains within the Object Store.
The Recovery Manager functions by:
� Periodically scanning the Object Store for transactions that may have failed. Failed transactions are indicated by the presence of log data after a period of time that the transaction would have normally been expected to finish.
� Checking with the application process which originated the transaction whether the transaction is still in progress or not
� Recovering the transaction by re-activating the transaction and then replaying phase two of the commit protocol.
How Do I configure recovery for JBM?
Open the conf/jbossjta-properties.xml file and add the following to the "jta" properties:
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.JBMESSAGING1" value="org.jboss.jms.server.recovery.MessagingXAResourceRecovery;java:/DefaultJMSProvider"/>
How does this relate to JBM?
When the session is enlisted in a transaction, data is passed to the Transaction Manager. This data references message in the local message store.
Looking at the configuration above, The class defined, "org.jboss.jms.server.recovery.MessagingXAResourceRecovery", will get called with the data that was persisted in the objectstore during the transaction. This data is passed back to the MessagingXAResourceRecovery and it then does what it needs to to recover the resource. You will notice that the recovery also gets the attribute java:/DefaultJMSProvider. This information is needed so that we can connect to the correct provider to be able to handle the message recovery.
Why do I get the error above when I cluster?
One word, "Failover". In JBM, when one server goes down, all of the data is moved from one server to another. This happens via the database. When one server goes down, its buddy in the cluster hears about it and will load all of the dead servers messages from the database.
If you had data enlisted in a Transaction when a server goes down, it's possible that the data can get written to the arjuna object store, but the messages and associated data get moved to another server in the cluster.
When you bring the dead server back to life, the recovery manager kicks in and tries to recover the transactions stored in the arjuna object store. If the messages and data have been moved to another server, it's impossible to return the XAResource, because the messages and affiliated data are no longer on that server. The result is that arjuna returns
Could not find new XAResource to use for recovering non-serializable XAResource
Because it could not find the data needed to recover the transaction in the local JBM instance.
How do I fix it?
You will need to add a provider and a Recovery Manager for each node in the system.
For instance, if you had 2 nodes, you would need to add to conf/jbossjta-properties.xml for each node:
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.JBMESSAGING1" value="org.jboss.jms.server.recovery.MessagingXAResourceRecovery;java:/DefaultJMSProvider"/> <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.JBMESSAGING2" value="org.jboss.jms.server.recovery.MessagingXAResourceRecovery;java:/RemoteProvider2"/>
RemoteProvider2 would have to be defined:
<!-- The JMS provider loader --> <mbean code="org.jboss.jms.jndi.JMSProviderLoader" name="jboss.jms:service=JMSProviderLoader,name=RemoteProvider2"> <attribute name="ProviderName">RemoteProvider2</attribute> <attribute name="ProviderAdapterClass"> org.jboss.jms.jndi.JNDIProviderAdapter </attribute> <!-- The combined connection factory --> <attribute name="FactoryRef">XAConnectionFactory</attribute> <!-- The queue connection factory --> <attribute name="QueueFactoryRef">XAConnectionFactory</attribute> <!-- The topic factory --> <attribute name="TopicFactoryRef">XAConnectionFactory</attribute> <!-- Uncomment to use HAJNDI to access JMS <attribute name="Properties"> java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces java.naming.provider.url=RemoteHost2:1099 </attribute> --> </mbean>
Notice in the RemoteProvider2, we define the jndi properties required to go to that remote server.
For each node of the Messaging Cluster, you will need to add providers and recovery managers for all the other nodes of the cluster in order to get proper recovery.
What does this do?
When you bring the dead server back up, Arjuna will start to recover transactions. It loops through the recovery managers invoking the recovery on each one. If the messages and other information has been moved to a sibling server, one of the recovery managers configured will have access to the messages and other information required to do the recovery.