Problem invoking method on remote EJB from another EJB
gadgetman Mar 20, 2003 12:40 AMI have a problem in trying to invoke a method on another EJB which is in another server from an EJB on one server. The 2 EJBs are stateless session beans. I am using 2 instances of JBoss for the 2 EJBs. Instance 1 of JBoss is on the standard port of 1099, whereeas instance 2 of JBoss is on port 11099. When I try to invoke the create method on EJB B from EJB A, I get a RemoteException indicating an rmi.MarshallException. In detail, it gives me a NotSerializableException. I find out I do get back a reference to the home interface of EJB B. I don't know why this is the case. If I invoke an EJB in the same server then it works. I would be grateful for any help anyone can provide. Thanks.
I've also added the <ejb-ref> in the ejb-jar.xml and jboss.xml for EJB A, as mentioned from www.jboss.org/online-manual/HTML/ch05s13.html.
Here's the code for EJB A:
package A;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.ejb.EJBException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import A.*;
import java.util.Properties;
import java.io.*;
public class Bean implements javax.ejb.SessionBean
{
// for stateful session bean
public javax.ejb.SessionContext ejbContext;
public javax.naming.Context jndiContext;
public void ejbCreate()
{
System.out.println("ABean: create()");
}
public String Method1(String user)
throws RemoteException {
System.out.println("ABean: method1");
return user;
}
public void sendToB(String user)
throws RemoteException {
System.out.println("ABean: Sending to B ");
try {
Context jndiContext = getInitialContext();
//InitialContext jndiContext = new InitialContext();
System.out.println("Got context");
Object ref = jndiContext.lookup("ejb/BBean");
System.out.println("Found B in JNDI context");
B.BeanHomeRemote home = (B.BeanHomeRemote)
PortableRemoteObject.narrow(ref,B.BeanHomeRemote.class);
//B.BeanHomeRemote home = (B.BeanHomeRemote) PortableRemoteObject(ref);
System.out.println("Starting to invoke on B ");
if (home != null) {
System.out.println("Got reference to EJB B");
}
else {
System.out.println("No reference to EJB B");
}
B.BeanRemote b = home.create();
if (b != null) {
System.out.println("EJB B remote interface is not null");
}
else {
System.out.println("EJB B remote interface is null");
}
b.Method1(user);
}
/*catch (MalformedURLException murle) {
System.out.println();
System.out.println(
"MalformedURLException");
System.out.println(murle);
} */
catch (RemoteException re) { System.out.println();
System.out.println(
"RemoteException");
System.out.println(re);
}
catch (Throwable t) { t.printStackTrace();}
}
public void ejbRemove(){}
public void ejbActivate(){}
public void ejbPassivate(){}
public void setSessionContext(javax.ejb.SessionContext cntx){
ejbContext = cntx;
try {
jndiContext = new InitialContext();
}
catch (NamingException ne) {
throw new EJBException(ne);
}
}
protected Object getHome(String name, Class type) {
try {
Object ref = jndiContext.lookup(name);
return PortableRemoteObject.narrow(ref, type);
}
catch (NamingException ne) {
throw new EJBException(ne);
}
}
static public Context getInitialContext() throws Exception
{
//context initialized by jndi.properties file
String jndiFile = "";
java.util.Properties p = new java.util.Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
jndiFile = "E:\\Code\\B\\jndi\\jndi.properties";
java.util.Properties jndi_prop = new Properties();
jndi_prop.load(new FileInputStream(jndiFile));
// look for Context.PROVIDER_URL in jndi file
String jndi_url = jndi_prop.getProperty("java.naming.provider.url");
//p.put(Context.PROVIDER_URL, "localhost:1099");
p.put(Context.PROVIDER_URL, jndi_url);
return new javax.naming.InitialContext(p);
}
}
Here's the code for EJB B:
package B;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.ejb.EJBException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.util.Properties;
import java.io.*;
public class Bean implements javax.ejb.SessionBean
{
public javax.ejb.SessionContext ejbContext;
public javax.naming.Context jndiContext;
public void ejbCreate()
{
//System.out.println("BBean: create()");
}
public String Method1(String user)
throws RemoteException {
System.out.println("BBean: method1");
return user;
}
public void ejbRemove(){}
public void ejbActivate(){}
public void ejbPassivate(){}
public void setSessionContext(javax.ejb.SessionContext cntx){
ejbContext = cntx;
try {
jndiContext = new InitialContext();
}
catch (NamingException ne) {
throw new EJBException(ne);
}
}
protected Object getHome(String name, Class type) {
try {
Object ref = jndiContext.lookup(name);
return PortableRemoteObject.narrow(ref, type);
}
catch (NamingException ne) {
throw new EJBException(ne);
}
}
static public Context getInitialContext() throws Exception
{
//context initialized by jndi.properties file
String jndiFile = "";
java.util.Properties p = new java.util.Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
jndiFile = "E:\\Code\\B\\jndi\\jndi.properties";
java.util.Properties jndi_prop = new Properties();
jndi_prop.load(new FileInputStream(jndiFile));
// look for Context.PROVIDER_URL in jndi file
String jndi_url = jndi_prop.getProperty("java.naming.provider.url");
//p.put(Context.PROVIDER_URL, "localhost:1099");
p.put(Context.PROVIDER_URL, jndi_url);
return new javax.naming.InitialContext(p);
}
}
Here's the ejb-jar.xml for EJB A:
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<ejb-name>AEJB</ejb-name>
A.BeanHomeRemote
A.BeanRemote
<ejb-class>A.Bean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<ejb-ref-name>ejb/BBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
B.BeanHomeRemote
B.BeanRemote
</ejb-ref>
</enterprise-beans>
<assembly-descriptor>
<security-role>
This role represents everyone who is allowed full access to the beans.
<role-name>everyone</role-name>
</security-role>
<method-permission>
<role-name>everyone</role-name>
<ejb-name>AEJB</ejb-name>
<method-name>*</method-name>
</method-permission>
<container-transaction>
<ejb-name>AEJB</ejb-name>
<method-name>*</method-name>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Here's the jboss.xml for EJB A:
<?xml version="1.0"?>
<enterprise-beans>
<ejb-name>AEJB</ejb-name>
<jndi-name>A</jndi-name>
<ejb-ref>
<ejb-ref-name>ejb/BBean</ejb-ref-name>
<jndi-name>jnp://localhost:11099/ejb/BBean</jndi-name>
</ejb-ref>
</enterprise-beans>
The home and remote interfaces for EJB B are packaged in the A.jar which is deployed on JBoss instance 1.
Any ideas what's going wrong, I've been tackling this for couple of days, and looking at various posts on the Internet, but haven't solved the problem. I am sure this has been addressed before, but I can't easily find it. It's getting pretty frustrating now!
Thanks for any help that anyone can provide, I am new to EJBs.