ejbwebsphere-libertyejb-3.2

Lookup Remote EJBs on Liberty (wlp-javaee8.21.0.0.8)


As the title says. I have some EJBs in an EAR and I have a client jar providing remote methods to a JSF app also sitting in liberty (different server/machine). The client jar tries to access the remote EJBs via lookup.

This is breaking my heart for two days now. As the title says...

I am aware of other stackoverflow questions from the past and I am aware of the following resources: https://www.ibm.com/docs/en/was-liberty/core?topic=liberty-using-enterprise-javabeans-remote-interfaces

https://github.com/OpenLiberty/open-liberty/blob/release/dev/com.ibm.ws.ejbcontainer.remote_fat/test-applications/RemoteClientWeb.war/src/com/ibm/ws/ejbcontainer/remote/client/web/RemoteTxAttrServlet.java

I have tried every combination provided in the above but no joy.


I use (wlp-javaee8.21.0.0.8) with javaee8 feature enabled, this enables everything else I need e.g. ejb-3.2, ejbRemote-3.2, jndi-1.0 and a few others)

I have an EAR my-ear that contains a module my-module-1.0.4-SNAPSHOT.jar which contains my beans. I am using gradle/liberty plugin and IntelliJ. I am using tests from within IntelliJ in the client jar module to try to access the remote beans.

My myEAR deploys fine and starts up fine and the app shows running in admincenter. In messages.log I see my EJB bindings. Just picking one example.

[16/08/21 10:58:42:384 IST] 00000022 com.ibm.ws.ejbcontainer.osgi.internal.NameSpaceBinderImpl I CNTR0167I: The server is binding the my.org.functiona.ejb.advance.MyAdvance interface of the MyAdvanceBean enterprise bean in the my-module-1.0.4-SNAPSHOT.jar module of the my-ear application. The binding location is: ejb/my-ear/my-module-1.0.4-SNAPSHOT.jar/MyAdvanceBean#my.org.functiona.ejb.advance.MyAdvance [16/08/21 10:58:42:385 IST] 00000022 com.ibm.ws.ejbcontainer.osgi.internal.NameSpaceBinderImpl I CNTR0167I: The server is binding the my.org.functiona.ejb.advance.MyAdvance interface of the MyAdvanceBean enterprise bean in the my-module-1.0.4-SNAPSHOT.jar module of the my-ear application. The binding location is: my.org.functiona.ejb.advance.MyAdvance [16/08/21 10:58:42:385 IST] 00000022 com.ibm.ws.ejbcontainer.runtime.AbstractEJBRuntime
I CNTR0167I: The server is binding the my.org.functiona.ejb.advance.MyAdvance interface of the MyAdvanceBean enterprise bean in the my-module-1.0.4-SNAPSHOT.jar module of the my-ear application. The binding location is: java:global/my-ws-ear/my-module-1.0.4-SNAPSHOT.jar/MyAdvanceBean!my.org.functiona.ejb.advance.MyAdvance

This is my corresponding interface:

package my.org.functiona.ejb.advance;

import javax.ejb.Remote;

@Remote
public interface MyAdvance {

This is my corresponding implementation:

package my.org.functiona.ejb.advance;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;

@Stateless(mappedName = "MyAdvance")
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyAdvanceBean implements MyAdvance {

Like I said, its breaking my heart. I tried every combination of provided in the (patchy) documentation and other sources. The most progress I made was by accessing "corbaname::localhost:2809/NameService" through a default InitialContext().lookup. So at least I was able to confirm I can gwet through to the NameService. But any subsequent bean lookup using that context with any combination of the names provided in messages.log or in the code snippets from documentation all fail with the exception below.

javax.naming.NameNotFoundException [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]

Same for InitialContext() lookups where I prefix the names with "corbaname::localhost:2809/NameService#".

I tried

and probably a few others

I replaced the # sign with an exclamation mark in all of the above. And went through it again. I tried corbaloc:: and corbaloc:iiop: for context. Nothing.

I am no web dev expert but this feels very try and error and I dont feel it should be like that. I understand in websphere proper I could identify the names in the admin console but then I'm not even certain websphere proper and liberty behave the same way.

Sine accessing EJBs from remote seems bread & butter stuff I assume I am overlooking something basic and silly due to my inexperience.

Any pointers anyone? Thank you so much for your time reading this.

Carsten

Edit: server.xml

<server description="disbCoreServer">

  <featureManager>
    <feature>javaee-8.0</feature>
    <feature>adminCenter-1.0</feature>
    <feature>websocket-1.1</feature>
  </featureManager>

  <quickStartSecurity userName="admin" userPassword="carsten" />

  <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
  <httpEndpoint id="defaultHttpEndpoint"
                host="${hostname}"
                httpPort="${default.http.port}"
                httpsPort="${default.https.port}">
      <accessLogging filepath="${com.ibm.ws.logging.log.directory}/accessLog.log" logFormat='%h %i %u %t "%r" %s %b %{R}W' />
      <tcpOptions soReuseAddr="true" />
  </httpEndpoint>

  <include location="appConfXML/disb_core_jndi.xml"/>
  <include location="appConfXML/disb_core_jdbc.xml"/>
  <include location="appConfXML/disb_core_jms.xml"/>
  <include location="appConfXML/disb_core_mail.xml"/>

</server>

Solution

  • The example provided through the FAT test (remoteLookup) works just fine. I just didnt have all my ducks in a row.

    https://github.com/OpenLiberty/open-liberty/blob/release/dev/com.ibm.ws.ejbcontainer.remote_fat/test-applications/RemoteClientWeb.war/src/com/ibm/ws/ejbcontainer/remote/client/web/RemoteTxAttrServlet.java

    My scenario is serverA hosting EJBs and serverB running the remote client calling serverA's EJBs.

    Steps on serverB are:

    1. Get (local) InitialContext with no properties: InitialContext initialContext = new InitialContext();

    2. With the above lookup the remote Context: Context remoteContext = (Context) initialContext.lookup("corbaname::remotehost:remotePort/NameService");

    3. With the remoteContext lookup the EJB remote interfaces and 'narrow' and cast them to appropriate type

      String lookupName = "ejb/global" + "/" + "MyAppName" + "/" + "MyModuleName" + "/" + jndiName; Object remoteObj = remoteContext.lookup(lookupName); return interfaceClass.cast(PortableRemoteObject.narrow(remoteObj, interfaceClass));

      Where

      • "MyAppName" is my apps name, the name of the EAR in my case (without .jar)
      • "MyModuleName" is the name of the EJB module within my EAR (without .jar)
      • and jndiName is the bean name / fully qualified interface name separated by exclamation mark e.g. "MyBean!myorg.ejb.interfaces.MyBeanIfc"
    4. Call the interfaces to remotely execute serverA EJB code

    Note: When running serverA and serverB on the same machine (e.g. localhost) ensure they are not operating on the same port for NameService.

    Thanks to everyone who tried to help!