Two remote EJB calls to two different servers in the same transaction
dbdbdb Apr 27, 2018 6:11 PMIt is possible to invoke two remote EJB targeting two remote server (each EJB in their own server) in the same distributed transaction? (cascanding calls)
I am using Wildfly 12 and for this situation, the container only invoke the first EJB invocation corretly, targeting the correct server. But when tries to invoke the second EJB, I'm getting error because Wildfly tries to lookup the second EJB targeting the first server, which is wrong. The correct behavior would be targeting the second server, as declared in <remote-ejb-receiver>.
This behavior becomes more strange because if I make the second invocation in a separate transaction (i.e. annotating the second remote EJB with @TransactionAttribute(REQUIRES_NEW)) all works fine.
The problem is that I can't change all the remote invocations to REQUIRES_NEW because I don't want to lose the atomicity of the whole transaction.
Follow the sequence diagram for this situations:
It is possible to achieve the second behavior but with just one transaction?
Follow my configurations:
jboss-ejb-client.xml (inside WEB-INF directory):
<?xml version="1.0" encoding="UTF-8"?> <jboss-ejb-client xmlns="urn:jboss:ejb-client:1.3"> <client-context> <profile name="profile-my-app" /> </client-context> </jboss-ejb-client>
domain.xml
<subsystem xmlns="urn:jboss:domain:ejb3:5.0"> ... ... <remote connector-ref="http-remoting-connector" thread-pool-name="default"> <channel-creation-options> <option name="READ_TIMEOUT" value="${prop.remoting-connector.read.timeout:20}" type="xnio"/> <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/> </channel-creation-options> <profiles> <profile name="profile-my-app"> <remoting-ejb-receiver name="rer-i-1" outbound-connection-ref="other-app-outbound-connection-1"/> <remoting-ejb-receiver name="rer-i-2" outbound-connection-ref="other-app-outbound-connection-2"/> </profile> </profiles> ... </remote> ... </subsystem> ... ... <subsystem xmlns="urn:jboss:domain:remoting:4.0"> <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm" sasl-authentication-factory="application-sasl-authentication"/> <outbound-connections> <remote-outbound-connection name="other-app-outbound-connection-1" outbound-socket-binding-ref="other-app-outbound-1" authentication-context="ejb-outbound-context"/> <remote-outbound-connection name="other-app-outbound-connection-2" outbound-socket-binding-ref="other-app-outbound-2" authentication-context="ejb-outbound-context"/> </outbound-connections> </subsystem> ... ... <socket-binding-group name="consensus-full-ha-sockets" default-interface="public"> ... ... <outbound-socket-binding name="my-app-outbound-1"> <remote-destination host="10.0.108.184" port="8080"/> </outbound-socket-binding> <outbound-socket-binding name="my-app-outbound-2"> <remote-destination host="10.0.108.102" port="8080"/> </outbound-socket-binding> </socket-binding-group>
wildfly-config.xml (the servers startup with "wildfly.config.url" system property pointing to this config file):
<configuration> <authentication-client xmlns="urn:elytron:1.0"> <authentication-rules> <rule use-configuration="default"/> </authentication-rules> <authentication-configurations> <configuration name="default"> <set-user-name name="ejb"/> <credentials> <clear-password password="ejbejb"/> </credentials> <sasl-mechanism-selector selector="DIGEST-MD5"/> <providers> <use-service-loader /> </providers> </configuration> </authentication-configurations> </authentication-client> </configuration>
Lookup and Inject:
@Produces public ParameterRemote produceParameter() throws Exception { ParameterRemote remote = (ParameterRemote) new InitialContext().lookup("ejb:/oneApp/ParameterBean!com.mycompany.client.service.interfaces.ParameterRemote"); return remote; } @Produces public IndexerRemote produceIndexer() throws Exception { IndexerRemote remote = (IndexerRemote) new InitialContext().lookup("ejb:/secondApp/IndexerBean!com.mycompany.client.service.interfaces.IndexerRemote"); return remote; } @Stateless public class SomeBusinessObject { @Inject private IndexerRemote indexerRemote; public void performIndex() { ... ... indexerRemote.performIndex(); //this works fine. Wildfly corretly lookup the first server } } //Deployed at server 1 @Stateless public class IndexerBean implements IndexerRemote { //IndexerRemote has the @Remote annotation @Inject private ParameterRemote parametersRemote; //deployed at server 2 @Override public void performIndex() { ... ... Parameter parameter = parameterRemote.getParameter(group, key); //this fails. Wildfly tris to lookup the parameterRemote targeting the first server again but this EJB is in other server } }
Am I missing something?
Could you help-me with this, please?
Thanks!