7.7.4. Transaction Behavior of EJB Invocations
Transaction attributes for distributed EAP applications need to be handled in a way as if the application is called on the same server. To discontinue a transaction, the destination method must be marked REQUIRES_NEW
using different interfaces.
Note
To invoke EJB session beans with an EAP 6 standalone client, the client must have a reference to the InitialContext
object while the EJB proxies or UserTransaction
are used. It is also important to keep the InitialContext
object open while EJB proxies or UserTransaction
are being used. Control of the connections will be inside the classes created by the InitialContext
with the properties.
InitialContext
object:
package org.jboss.as.quickstarts.ejb.multi.server; import java.util.Date; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import org.jboss.as.quickstarts.ejb.multi.server.app.MainApp; import org.jboss.ejb.client.ContextSelector; import org.jboss.ejb.client.EJBClientConfiguration; import org.jboss.ejb.client.EJBClientContext; import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration; import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector; public class Client { /** * @param args no args needed * @throws Exception */ public static void main(String[] args) throws Exception { // suppress output of client messages Logger.getLogger("org.jboss").setLevel(Level.OFF); Logger.getLogger("org.xnio").setLevel(Level.OFF); Properties p = new Properties(); p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false"); p.put("remote.connections", "one"); p.put("remote.connection.one.port", "4447"); p.put("remote.connection.one.host", "localhost"); p.put("remote.connection.one.username", "quickuser"); p.put("remote.connection.one.password", "quick-123"); EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p); ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc); EJBClientContext.setSelector(selector); Properties props = new Properties(); props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); InitialContext context = new InitialContext(props); final String rcal = "ejb:jboss-ejb-multi-server-app-main/ejb//" + ("MainAppBean") + "!" + MainApp.class.getName(); final MainApp remote = (MainApp) context.lookup(rcal); final String result = remote.invokeAll("Client call at "+new Date()); System.out.println("InvokeAll succeed: "+result); } }
Note
UserTransaction
reference on the client is unsupported for scenarios with a scoped EJB client context and for invocations which use the remote-naming
protocol. This is because in these scenarios, InitialContext
encapsulates its own EJB client context instance; which cannot be accessed using the static methods of the EJBClient
class. When EJBClient.getUserTransaction()
is called, it returns a transaction from default (global) EJB client context (which might not be initialized) and not from the desired one.
The following example shows how to get UserTransaction
reference on a standalone client:
import org.jboss.ejb.client.EJBClient; import javax.transaction.UserTransaction; . . Context context=null; UserTransaction tx=null; try { Properties props = new Properties(); // REMEMBER: there must be a jboss-ejb-client.properties with the connection parameter // in the clients classpath props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); context = new InitialContext(props); System.out.println("\n\tGot initial Context: "+context); tx=EJBClient.getUserTransaction("yourServerName"); System.out.println("UserTransaction = "+tx.getStatus()); tx.begin(); // do some work ... }catch (Exception e) { e.printStackTrace(); tx.rollback(); }finally{ if(context != null) { context.close(); } }
Note
UserTransaction
reference on the client side; start your server with the following system property -Djboss.node.name=yourServerName
and then use it on client side as following:
tx=EJBClient.getUserTransaction("yourServerName");Replace "yourServerName" with the name of your server. If a user transaction is started on a node all invocations are sticky on the node and the node must have all the needed EJBs. It is not possible to use
UserTransaction
with remote-naming protocol and scoped-context.