Two remote EJB calls to two different servers in the same transaction

436 views
Skip to first unread message

Nikhil Popat

unread,
May 3, 2023, 6:53:00 PM5/3/23
to WildFly

It 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 23 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?

Nikhil Popat

unread,
May 3, 2023, 6:53:01 PM5/3/23
to WildFly

jfinelli

unread,
May 9, 2023, 5:51:08 AM5/9/23
to WildFly
Hi Nikhil, I’m not an expert in EJB remoting but your goal should be possible. By any chance, have you had a look at our quickstart demonstrating how to execute transactions across multiple servers?

Marco Sappe Griot

unread,
May 9, 2023, 11:47:16 AM5/9/23
to WildFly
Hi Nikhil,
as Manuel said that should be feasible.
The error you get seems to me a problem related to a clustered environment. Are your servers in a cluster environment?
If that is the case: As written in the quickstart README Manuel's shared "The expected behaviour varies depending on type of the remote call. It depends on running the call as part of the transaction – then the transaction affinity makes all calls hit the same server instance". If I understood well you are trying to invoke the second EJB in the second server (within the same transaction) and this might be a problem depending on your implementation.
Might it be that your client cannot find the second EJB because your call hits the first server due to transaction affinity?
Looking at the documentation if you manage transactions on the client side, it is possible to choose to target a specific node in the cluster instead of allow the client to lazily select the cluster node.
It would be helpful to see the error log.
Have a nice day,
Marco

Tom Jenkinson

unread,
May 10, 2023, 6:58:53 AM5/10/23
to WildFly
The WildFly documentation can found at http://docs.wildfly.org/ - I am not an expert on the configuration of EJB remoting, but if you are trying to use EJB remoting please do take a look in the Developer guide (this is from WildFly 28 which you should consider to upgrade to): http://docs.wildfly.org/28/Developer_Guide.html (I can spot things about "EJB Invocations" and "remote" in there which might be useful to look at).

Please be aware that there are two ways that remote EJB calls are possible, JTS (over CORBA) and a WildFly protocol. I am not sure which you are trying to use? Do you happen to have sample code and configuration available that you are able to share?

Nikhil Popat

unread,
May 15, 2023, 11:25:25 AM5/15/23
to WildFly
Hi All,

Thank you for your responses.

We are not using cluster environment. We are using 2 standalone server. 

Please find a simple flow of what we are doing in code.

client ---> EJB1 (server 1) --> EJB2 (server 1) --> EJB3 (server 2)

Here EJB1, EJB2 is local EJBs deployed on server 1(localhost:8080) and EJB3 is remote EJB deployed on server 2 (localhost:8081)

client code :

Properties jndiProperties = new Properties();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put(Context.PROVIDER_URL, "remote+http://127.0.0.1:8080");
jndiProperties.put(Context.SECURITY_PRINCIPAL, "user");
jndiProperties.put(Context.SECURITY_CREDENTIALS, "password");


Context jndiCtx1 = new InitialContext(jndiProperties);;


BookingControllerRemote bookingControllerRemote = null;
try {
bookingControllerRemote = (BookingControllerRemote)jndiCtx1.lookup("ejb:/booking/EJB1!org.airline.controller.BookingControllerRemote");
bookingControllerRemote.book();
} catch (NamingException e) {
throw new RuntimeException(e);
}




EJB1 code :

Context jndiCtx = new InitialContext();
BookingRemote bookingRemote = (BookingRemote) jndiCtx.lookup("ejb:/booking/EJB2!org.airline.BookingRemote");
bookingRemote.book();


EJB2 code:
Properties jndiProperties = new Properties();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put(Context.PROVIDER_URL, "remote+http://127.0.0.1:8081");   // call should go to remote server running on 8081 port but It's going on server 1 8080 port only.
jndiProperties.put(Context.SECURITY_PRINCIPAL"user");
jndiProperties.put(Context.SECURITY_CREDENTIALS"password");

try {
Context jndiCtx = new InitialContext(jndiProperties);
RemoteEJB remoteEJB = (RemoteEJB) jndiCtx.lookup("ejb:/booking/EJB3!com.airline.jms.ejb.RemoteEJB");
remoteEJB.sendMessage("TeestingQueue", "KLJLKJLKJLKJLKJ");
} catch (NamingException e) {
throw new RemoteException();
}



This could be due to transaction affinity. Is there any way we can disable transaction affinity ? 

Brad Maxwell

unread,
May 16, 2023, 12:22:03 PM5/16/23
to WildFly

Hello,


Where is this defined? <remote-ejb-receiver>.   , it looks like perhaps you meant you have a jboss-ejb-client.xml with something like:

<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection"/>

 that you have configured to point to server2 ?  If so, then you have the EJB2 code specifying a provider url as well, so basically 2 different methods of invoking EJBs.


It looks like an issue is you have something like a booking.jar deployed in server1 and server2, but these are not the same deployment, as in server1 booking.jar has EJB1 & EJB2, but then in server2 it has EJB3 ?  If this is the case, then the location mapping of EJBs is done based on the appName/moduleName , so Wildfly sees this as there is a booking.jar with EJB1, EJB2 & EJB3 when that is not the case.  Changing the deployment name on server2 or using <distinct-name>... in the jboss-ejb3.xml and then changing the EJB lookup to include the distinct-name would allow it to distinguish between the 2 different deployments.


ejb:/booking/EJB1

ejb:/booking/EJB2

ejb:/booking/EJB3

Richard Achmatowicz

unread,
May 17, 2023, 6:12:18 PM5/17/23
to WildFly
Hello Nikhil
If you are still having problems with this issue, it would be helpful to see what EJB2 is actually doing when it tries to contact EJB3. In that case, you can configure logging for the EJB client activity on server1. 

Ordinarily, you could just drop a logging.properties file into the war WEB-INF/classes directory for the deployment on server1, but that will only apply to the loggers of classes defined in the war. Because the EJB client code which your classes use is packaged as a WildFly module, you need to configure the logging subsystem of Wildfly in order to enable a specific level of logging in the EJB client (or Xnio or Elytron) code that your application uses.

For example, with these Wildfly CLI commands, you can enable DEBUG logging for the EJB client code in your application:
  /subsystem=logging/file-handler=client:add(file={path="client.log", relative-to=jboss.server.log.dir}, named-formatter=PATTERN)
  /subsystem=logging/logger=org.jboss.ejb.client:add(level=DEBUG,handlers=[client])
If you add this configuration to your server and redeploy the applications, this will cause logging output from the EJB client code in your application to be written to the file client.log in the server1/standalone/log directory. If you could post that output here, we could have a look to see what is going on.

Richard
Reply all
Reply to author
Forward
0 new messages