7.7.4. Comportement de transaction des invocations EJB
Les attributs de transaction d'applications distribuées EAP doivent être gérés comme si l'application était appelée sur le même serveur. Pour mettre fin à une transaction, la méthode de destination doit comporter la mention REQUIRES_NEW, à l'aide d'interfaces différentes.
Note
Pour invoquer les beans de session EJB avec un client EAP 6 autonome, le client doit avoir une référence à l'objet InitialContext tandis que les proxies EJB ou UserTransaction sont utilisés. Il est également important de garder l'objet InitialContext ouvert tant que les proxies EJB ou UserTransaction sont utilisés. Le contrôle des connexions se fera à l'intérieur des classes créées par InitialContext avec les propriétés.
InitialContext :
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 sur un client n'est pas prise en charge pour les scénarios de contextes client EJB scoped et pour les invocations qui utilisent le protocole remote-naming. C'est parce que dans ces scénarios, InitialContext encapsule sa propre instance de contexte client, à laquelle on ne peut pas accéder par les méthodes statiques de la classe EJBClient. Quand la méthode EJBClient.getUserTransaction() est invoquée, elle renvoie une transaction en provenance du contexte client EJB (global) par défaut (pas forcément initialisé) et non pas en provenance du contexte souhaité.
L'exemple suivant vous montre comment obtenir une référence UserTransaction sur un client autonome :
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 côté client, démarrer votre serveur avec la propriété système suivante -Djboss.node.name=yourServerName et utilisez-là ensuite côté client comme suit :
tx=EJBClient.getUserTransaction("yourServerName");
UserTransaction avec un protocole de nommage à distance ou avec un scoped-context.