Friday, September 24, 2010

Remote Session Bean - EJB 2.0

Moving Ahead
In my previous EJB Session Bean Post, I talked about local session bean. In this blog, we will learn about remote stateless session bean.

A Brief Idea

The client looks up the EJB home object of the installed enterprise bean via Java Naming and Directory Interface (JNDI) services. The client then uses the home object to create an enterprise bean instance.
However, the client isn’t given a direct reference to the newly created enterprise bean instance. Instead the client receives reference to an EJB object, an object of the component interface. The client then calls the EJB object, which delegates calls to the enterprise bean instance.

Remote method invocation (RMI) 
RMI is the action of invoking a method of a remote interface on a remote object.

RMI uses a standard mechanism for communicating with remote objects: stubs and skeletons.
A stub for a remote object acts as a client’s local representative or proxy for the remote object. The caller invokes a method on the local stub, which is responsible for carrying out the method call on the remote object.
In RMI, a stub for a remote object implements the same set of remote interfaces that the remote object implements.

When a stub’s method is invoked, it does the following:
         • Initiates a connection with the remote JVM containing the remote object.
         • Marshals (writes and transmits) the parameters to the remote JVM.
         • Waits for the result of the method invocation.
         • Unmarshals (reads) the return value or exception returned.
         • Returns the value to the caller.

The stub hides the serialization of parameters and the network-level communication in order to present a simple invocation mechanism to the caller.

In a remote JVM, each remote object may have a corresponding skeleton. A skeleton is responsible for dispatching the call to the actual remote object implementation. 
When a skeleton receives an incoming method invocation, it does the following:
         • Unmarshals (reads) the parameters for the remote method.
         • Invokes the method on the actual remote object implementation.
         • Marshals (writes and transmits) the result (return value or exception) to the caller.










Home Interface

Clients use the home interface to create, remove, and find Enterprise JavaBean instances.You can think of the home object as the Enterprise JavaBean factory; you write the interface, the container tools generate the home class that corresponds to it, and the home interface defines the creation methods for the Enterprise JavaBean.

Home interface of a remote session bean must extend EJBHome.

package com.sarf.remote.business;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface HelloWorldRemoteHome extends EJBHome
{
      public HelloWorldRemote create() throws CreateException,RemoteException;
}



Component Interface

The component interface exposes an Enterprise JavaBean’s business methods to a client. The client calls the methods defined in the component interface to invoke the business logic implemented by the bean. You can think of the component object as a proxy to the Enterprise JavaBean instance. You write this interface. The container tools generate the component class corresponding to this interface.
 

Component Interface of remote session bean must extend EJBObject.

package com.sarf.remote.business;

import java.rmi.RemoteException;
import javax.ejb.EJBObject;

public interface HelloWorldRemote extends EJBObject
{
      public String sayHello(String strName) throws RemoteException;
}



 The component interface has only the methods that are callable by the client. The Enterprise JavaBean may have other methods in it, but if they aren’t listed in the component interface, clients cannot call them.




Session Bean
 
The following excerpt is our session bean definition.

package com.sarf.remote.business;

import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class HelloWorldRemoteSessionBean implements SessionBean {
     
    private static final long serialVersionUID = 1L;

    // Methods of Remote interface
    public String sayHello(String strName) throws RemoteException {
      return "EJB.... Hello, world !" + strName;
     }

    // Methods of Home interface
    public void ejbCreate() throws RemoteException{
     }
     
    protected SessionContext ctx;
    public void setSessionContext(SessionContext ctx) 
     throws EJBException,RemoteException {
           this.ctx = ctx;
     }
    public void ejbRemove() throws EJBException, RemoteException {
     }
    public void ejbActivate() throws EJBException, RemoteException {
     }
    public void ejbPassivate() throws EJBException, RemoteException {
      }
}

Deployment Descriptor

Following excerpt from our  ejb-jar.xml file shows how we configure our remote session bean.

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
  http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
<display-name>EJB Example</display-name>
 <enterprise-beans>
  <session>
   <ejb-name>HelloWorldRemoteSessionBean</ejb-name>
    <home>com.sarf.remote.business.HelloWorldRemoteHome</home>
    <remote>com.sarf.remote.business.HelloWorldRemote</remote>
    <ejb-class> 
     com.sarf.remote.business.HelloWorldRemoteSessionBean
    </ejb-class>     
    <session-type>Stateless</session-type>
    <transaction-type>Container</transaction-type>
  </session>
 </enterprise-beans>
 <assembly-descriptor>
  <container-transaction>
   <method>
    <ejb-name>HelloWorldRemoteSessionBean</ejb-name>
    <method-name>*</method-name>
   </method>
   <trans-attribute>Required</trans-attribute>
  </container-transaction>
 </assembly-descriptor>
</ejb-jar>


Following excerpt from our jboss.xml shows how to confgure JNDI for Jboss application server.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" 
   "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
<jboss>
      <enterprise-beans>
            <session>
                  <ejb-name>HelloWorldRemoteSessionBean</ejb-name>
                  <jndi-name>HelloWorldRemoteSession</jndi-name>             
            </session> 
      </enterprise-beans>
</jboss>   


Following excerpt from our application.xml shows how to configure the application.


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/application_5.xsd" version="5">
    <description>EJB Remote Example</description>
    <display-name>EJB Remote Example</display-name>
    <module>
      <ejb>EJBRemoteExample.jar</ejb>
    </module>
    <module>   
        <web>
            <web-uri>EJBRemoteExample.war</web-uri>
            <context-root>/EJBRemoteExample</context-root>
        </web>
    </module>   
</application>


Client Code









Here is the excerpt of our remoteClient.jsp which will use remote session bean.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="remote.client.*, javax.naming.*, javax.rmi.*, java.util.*"%>
<%@page import="javax.ejb.CreateException"%>
<%@page import="java.rmi.*"%><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello World Example</title>
</head>
<body>
 <%
  String message = null;
  try
      {
         Properties prop = new Properties();
         prop.put(Context.INITIAL_CONTEXT_FACTORY,
           "org.jnp.interfaces.NamingContextFactory");
         prop.setProperty(Context.URL_PKG_PREFIXES,
           "org.jboss.naming:org.jnp.interfaces");
         prop.put(Context.PROVIDER_URL, "jnp://remote-pc:1099");
         prop.put(Context.SECURITY_PRINCIPAL, "admin");
         prop.put(Context.SECURITY_CREDENTIALS, "admin");
         prop.put(Context.INITIAL_CONTEXT_FACTORY, 
           "org.jboss.security.jndi.JndiLoginInitialContextFactory");
         Context initialContext = new InitialContext(prop);
         Object obj = initialContext.lookup("HelloWorldRemoteSession");
         HelloWorldRemoteHome home = (HelloWorldRemoteHome)  
          PortableRemoteObject.narrow(obj,HelloWorldRemoteHome.class);
         HelloWorldRemote myHelloWorld = home.create();
         message = myHelloWorld.sayHello("Sarf");
       }
       catch (RemoteException ce)
       {}
 %>
  <%=message %>
</body>
</html>