3 Replies Latest reply on Apr 27, 2018 6:19 PM by dbdbdb

    Wildfly 12 - Problem invoking subsequent (A->B->C) remote EJBs (server-to-server) in the same transaction. With a new transaction works.

    dbdbdb

      I have a web application (App-1) which invoke two (App-2 and App-3) remote EJBs (each one in its own server) in the same transaction.

      Important notice: App-1 is in the same server as App-2. But App-3 is in another server.

       

      Only the first remote invocation works (App-1 -> App-2), the second one (App-2 -> App-3), Wildfly tries to lookup at the same server, instead of lookup in the other server.

      <remote-ejb-receiver> is properly declared, socket-binds as well. And works fine, but just for the first remote invocation in the stack.

       

      Two scenarios, same behaviour:

       

      Scenario 1:

      App-1 has a timer-service that start a transaction, do some work and invoke an EJB in App-2 (remote EJB to the same server). Then, App-2 invoke an EJB in App-3 (remote EJB call to another server).

       

      Result:

      This works fine in the first remote invocation. App-1 can lookup and invoke App-2, which is on the same server.

      At the second invocation, when App-2 tries to lookup and invoke App-3 in the same transaction (that one created in the App-1 timer-service), Wildfly can't find App-3's EJB throwing a NoSuchEJBException. Looks like the App-2 is trying to lookup App-3 in the same server as App-2 and can't find it.

      ===> But if a new transaction is created (with REQUIRES_NEW) between App-1 and App-2, Wildfly is able to find App-3 and the invocation works!

       

      Diagram of scenario 1:

       

       

      Scenario 2:

      App-2 has a REST endpoint and receives a GET request, open a transaction, do some work and invokes App-3 (other server). This call works fine, Wildfly lookups the remote EJB in the other server, get the result of App-3 (back execution to the first server) and invoke App-1 (same server).

       

      Result:

      First call works fine. Wildfly correctly find the App-3 in the other server and make the invocation. Then, back to the App-2, tries to invoke App-1 (same server) but it can't. Throwing a NoSuchEJBException because it tried to lookup App-1's EJB int the App-3's server.

      ===> But, again, if a new transaction is created (with REQUIRES_NEW) between App-2 and App-1, Wildfly is able to find App-1 and the invocation works!

       

      Diagram of scenario 2:

       

       

      Looks like Wildfly's EJB Client is "reusing" the target server when is within the same transaction. But when a new transaction is created, it can properly finds the correct server.

       

      How can I properly configure the server or the apps to not "reuse" the target server for the sequent calls?

       

      Thanks!

       

      (And sorry for the long post)

        • 1. Re: Wildfly 12 - Problem invoking subsequent (A->B->C) remote EJBs (server-to-server) in the same transaction. With a new transaction works.
          andey

          There are two possible scenarios.

           

          1.the client invokes an EJB in two different JBoss servers (or JEE servers from different vendors);

          2.the client invokes an EJB in a JBoss server and also performs some local work;

           

          In cases 1 and 2 where the client wishes to enlist other servers or local resources with the transaction

           

          These Scenario  is supported by the JBoss application server but requires a distributed transaction manager (TM). JBossTS is the default TM supported by the AS and comes in two flavors: JTA only (which is the default TM shipped with the AS); and a JTS version

          1 of 1 people found this helpful
          • 2. Re: Wildfly 12 - Problem invoking subsequent (A->B->C) remote EJBs (server-to-server) in the same transaction. With a new transaction works.
            dbdbdb

            Thank you for your response, andey !

            Our apps already use distributed transaction through JTA and works fine.

             

            The problem we are facing now is to perform two remote EJB invocations targeting different servers in the same distributed transaction.

            Once the app performs the first remote ejb call, it seems it is "caching" this target server and at the second ejb call to other server, Wildfly tries to lookup this second ejb but targeting at the first server, which is wrong. It should targeting at the second server as declared in remote-ejb-receiver.

             

            But, if I change the code in order to create a new transaction before the second call, Wildfly correctly targeting the second server.

             

            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.

             

            Am I missing something?

             

            Thanks!

            • 3. Re: Wildfly 12 - Problem invoking subsequent (A->B->C) remote EJBs (server-to-server) in the same transaction. With a new transaction works.
              dbdbdb

              Follow the code and 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> 
              

               

              Code (inject, lookups and invocations):

              @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 produceIndex() throws Exception {  
                  IndexerRemote remote = (IndexerRemote) new InitialContext().lookup("ejb:/secondApp/IndexerBean!com.mycompany.client.service.interfaces.IndexerRemote");  
                  return remote;  
              }  
                
                
                
                
              @Stateless  
              public class SomeBusinessObject {   //App-1
              
              
                  @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 (App-2)
                  
                  @Inject  
                  private ParameterRemote parametersRemote; //deployed at server 2   (App-3)
                    
                  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  
                  }  
              } 

               

              Thanks