Using enterprise JavaBeans with remote interfaces on Liberty

You can remotely access Enterprise Java™ Bean (EJB) methods with remote interfaces when the EJB is hosted by another Java virtual machine (JVM) or another application within the same JVM. WebSphere® Application Server implements remote EJB interfaces by using RMI-IIOP technologies. You can enable remote EJB support with the ejbRemote-3.2 feature.

About this task

To configure a Liberty server to run an application with remote EJB support enabled, you must set the ejbRemote-3.2 feature.

When you use remote EJB interfaces, review the following considerations:

Naming
Using the java: namespace
The EJB specification requires that remote interfaces are bound to the java: namespace, which is available to the application server and the application client container, as shown in the following example:
java:global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface    
java:app/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface    
java:module/ExampleBean!com.ibm.example.ExampleRemoteInterface

[20.0.0.12 and later] In version 20.0.0.12 and later, EJB components are bound to both the default and the ejblocal: Java Naming and Directory Interface (JNDI) namespaces, as in WebSphere® Application Server traditional. In these versions, for EJB components that are hosted within the same server, @EJB lookups and bindings in ibm-*-bnd.xml/xmi files can use either the java: namespace or the heritage namespaces from WebSphere Application Server traditional. For EJB components that are hosted in another server, lookups and bindings can use corbaname URLs. Before version 20.0.0.12, EJB components are not bound to the default JNDI namespace and must use the java: names for EJB components that are hosted within the same server.

Using corbaname URLs
Interfaces are also bound to the ORB CosNaming name service in similar contexts to those interfaces used in the java:global namespace. These interfaces can be accessed through JNDI by using corbaname URLs; for example:
corbaname::test.ibm.com:2809#ejb/global/ExampleApp/ExampleModule/ExampleHomeBean!com.ibm.example.ExampleEJBHome
corbaname:rir:#ejb/global/ExampleApp/ExampleModule/ExampleHomeBean!com.ibm.example.ExampleEJBHome

On the server, the rir: form of the URL uses the local name service. On the client, it uses the default or configured remote name service.

Escaping corbaname URLs

According to the Object Management Group (OMG) Naming Service specification, some characters in corbaname URLs must be escaped. Liberty tries to determine whether a corbaname URL that is derived from the java:global namespace needs to be escaped, and then escapes it automatically. It is not possible to do the escape in all cases. For example, if a name contains a single dot (.), and has no invalid characters, it cannot be escaped automatically. To force a name to be interpreted in a particular way, it is necessary to escape the URL manually as described in the OMG Naming Service specification.

Consider the following java:global name for an enterprise bean:
java:global/TestApp/TestModule/TestBean!test.TestRemoteInterface
The simple form of the corbaname URL cannot be escaped automatically because it represents a different, but valid location. Therefore, the following URL does not work as expected:
corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test.TestRemoteInterface
Instead, this URL must be manually escaped as follows:
corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test%5c.TestRemoteInterface
Not all client and application server implementations support the use of %5c in a JNDI name to represent an escape character. For these implementations, including WebSphere Application Server traditional, the backslash ( \ ) character can be used directly. Because a backslash must be escaped in a Java String, the URL can be manually escaped as shown in the following example:
corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test\\.TestRemoteInterface

The syntax for escaping corbaname URLs is described fully in OMG Naming Service specification.

Using JNDI names programmatically
All of the URLs and JNDI names in these examples can be looked up programmatically from an InitialContext. When you look up a java: name, the resulting object can be cast directly to the expected type; for example:
Object found = new InitialContext().lookup("java:global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface");
ExampleRemoteInterface bean = (ExampleRemoteInterface) found;
However, when you retrieve objects by using corbaname URLs, the RMI style of casting, called narrowing, must be used; for example:
Object found = new InitialContext().lookup("corbaname:rir:#ejb/global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface");
ExampleRemoteInterface bean = (ExampleRemoteInterface)PortableRemoteObject.narrow(found, ExampleRemoteInterface.class);
If the same context is used to look up multiple enterprise beans from the same remote server, then the corbaloc value can be used when you create the InitialContext class, as shown in the following example:
        Properties p = new Properties();
        p.put(Context.PROVIDER_URL, "corbaloc::test.ibm.com:2809");
        InitialContext c = new InitialContext(p);
        Object found = c.lookup("ejb/global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface");
        ExampleRemoteInterface bean = (ExampleRemoteInterface)PortableRemoteObject.narrow(found, ExampleRemoteInterface.class);
Interoperability
Any product that supports the IIOP protocol can call enterprise beans that use the EJB 2.x remote programming model with EJBHome and EJBObject when it is packaged in an EJB JAR module with a version 2.0 deployment descriptor. The WLP_INSTALL_DIR/clients/ejbRemotePortable.jar file must be included on the class path of the remote client. This file contains system value classes that are required for communication with a Liberty server. This file is not required when you remotely access EJB components from the WebSphere Application Server Liberty or WebSphere Application Server traditional. EJB components that use the EJB 3 remote programming model on Liberty can be remotely accessed by WebSphere Application Server processes. Liberty does not provide a thin client to start EJB components from a stand-alone Java process. Liberty does not provide workload management or failover capabilities for remote EJB components, including when you start EJB components that are hosted from WebSphere Application Server traditional.
Stub classes
A client must include stub classes when you start a remote EJB that is hosted on an WebSphere Application Server. In some cases, if the client is WebSphere Application Server, the product automatically generates the correct stub classes:
  • If a client application starts a remote EJB that is contained within the same application, Liberty automatically generates stub classes.
  • If the target EJB is running in a separate application and is using the EJB 2.x remote programming model with EJBHome and EJBObject, then the client must include stub classes on its classpath. If the EJB is hosted on WebSphere Application Server traditional, you can copy the EJB client JAR from the application from the EAR after it is processed by the ejbdeploy command. If the EJB is hosted on Liberty, you must use the rmic program that is included with your Java SDK to generate the stub classes for the target EJB, and then you must include the stub classes with the client.
  • If the target EJB is running in a separate application and is using the EJB 3 remote programming model, then the client Liberty or WebSphere Application Server traditional process automatically generates stub classes. EJB components that use the EJB 3 remote programming model on Liberty can be remotely accessed by WebSphere Application Server or WebSphere Application Client processes only.
Transaction propagation
Liberty does not support outbound or inbound transaction propagation. Additionally, the EJB specification requires that, even if a product supports outbound transaction propagation, it must still send a null transaction context. This context must be rejected by EJB components that use the Required (default), Mandatory, or Supports transaction attributes. A client with an active global transaction cannot start an EJB with default transaction attributes if either the client or server is in Liberty. The client can start the EJB if the EJB is changed to use the RequiresNew or NotSupported transaction attributes. However, the transactional work that is done by the EJB is not committed as part of the transactions of the client.
Asynchronous methods
An EJB remote interface can have an asynchronous method with a return value of type Future. The server will return a Future object to the client, which is used to retrieve the value. Remote asynchronous methods are not recommended because accumulation of unclaimed results can exhaust memory. To mitigate this problem, the server results expire if the client does not retrieve the result within 24 hours or if the maximum number of unclaimed results exceeds 1000. These values can be adjusted in the server.xml file; for example:
<ejbContainer>        
     <async maxUnclaimedRemoteResults="10"unclaimedRemoteResultTimeout="10m"/>    
</ejbContainer>

Procedure

  1. To enable this feature, update the server.xml file to add the ejbRemote-3.2 feature; for example:
    <featureManager>
         <feature>ejbRemote-3.2</feature>
    </featureManager>
    
  2. Configure your application binding files, ibm-*-bnd.xml files, for remote EJB references that have been defined either in the deployment descriptor <ejb-ref> or with source code annotations, @EJB.
    A binding is not required for EJB references that provide a lookup name, either on the annotation or in the deployment descriptor. In the binding file, the EJB reference can be bound using one of the java: names for an EJB or with one of the corbaname: names; for example:
    For an EJB reference:
    @EJB(name="TestBean")
       TestRemoteInterface testBean;
    The binding is defined:
     <ejb-ref name="TestBean" binding-name="corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test\\.TestRemoteInterface"/>
    
  3. Configure your application client to include stub classes.
  4. (Optional) Configure interoperability for applications that support the IIOP protocol to use EJB remote interfaces by adding the WLP_INSTALL_DIR/clients/ejbRemotePortable.jar file on the class path of the remote client.