I am trying to write a simple stateless sesssion bean but I have problem with narrow reference I give in lookup time. I got
class cast exeption
I use
eclipse IDE
my bean class
package codes;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class SinaBean implements SessionBean {
/**
*
*/
private static final long serialVersionUID = 1L;
public String getHello()
{
return "hello";
}
public void ejbCreate(){
}
@Override
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
}
}
my home interface
package codes;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface SinaHome extends EJBHome {
public SinaObject create() throws RemoteException,CreateException;
}
my component
package codes;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface SinaObject extends EJBObject {
String getHello() throws RemoteException;
}
my client
package codes;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
Context con=null;
try {
Properties p=new Properties();
p.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
p.setProperty(Context.PROVIDER_URL, "localhost:1099");
p.setProperty(Context.URL_PKG_PREFIXES,
"org.jboss.namingrg.jnp.interfaces");
con = new InitialContext(p);
Object o=con.lookup("SinaBean");
System.out.println(o);/***/untill know it works.it sysout :
//org.jnp.interfaces.NamingContext@e83912***
@SuppressWarnings("unused")
SinaHome sh=(SinaHome)PortableRemoteObject.narrow(o, SinaHome.class);//***exeption is here!!***
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
my xml file
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 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/ejb-jar_3_0.xsd">
<display-name>Ejb </display-name>
<enterprise-beans>
<session>
<display-name>SinaBean</display-name>
<ejb-name>SinaBean</ejb-name>
<home>codes.SinaHome</home>
<remote>codes.SinaObject</remote>
<ejb-class>codes.SinaBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
<security-identity>
<description></description>
<use-caller-identity></use-caller-identity>
</security-identity>
</session>
</enterprise-beans>
</ejb-jar>
the exception I receive
java.lang.ClassCastException
at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229)
at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137)
at codes.Client.main(Client.java:27)
Caused by: java.lang.ClassCastException: org.jnp.interfaces.NamingContext cannot be cast to org.omg.CORBA.Object
at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212)
... 2 more
I will be extremely grateful for your advices.
First of all, your xml file indicates you are using EJB3 (which is actually the only version even worth considering), but your bean is an EJB2 bean.
If your server indeed runs EJB3, remove the XML file and remove the needless EJB home and component implementations. Add the @Stateless
annotation and a remote interface. Make sure it looks something like this:
@Remote
public interface SinaRemote {
String getHello();
}
@Stateless
public class SinaBean implements SinaRemote {
public String getHello() {
return "hello";
}
}
Then correct your JNDI properties. The following is wrong:
p.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.namingrg.jnp.interfaces");
it should be:
p.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
(the variants people use here are almost endless and it basically always works anyway, but just to be sure use the correct variant)
Furthermore, and most likely the main culprit, you're using the ejb-name
as-if it was a global JNDI name but this is not the case. The ejb-name
is a somewhat confusing logical name that's used as an extra kind of qualifier when referring to a specific bean when injecting or creating an ejb-ref.
In your case you're setting it to the same as the unqualified bean name, which is already the default. Since SinaBean
exists, I'm guessing you're not deploying via an EAR, but deploy a standalone EJB jar, right?
If you are using JBoss AS 6 (EJB3.1) you can use the global portable JNDI names, otherwise the old JBoss specific JNDI naming can be used: [ear name]/[simple bean name]/remote
. Note that [simple bean name] is not the ejb-name, but again in your case they happened to be the same. Since [ear name]/
is removed when you're deploying only an EJB jar, this explains the exception you're getting: SinaBean
is a directory (context in JNDI terms), which can contain the actual entries local
, remote
and no-interface
. What you're doing is trying to cast this intermediate directory node to the proxy to your bean, which of course doesn't work.
Anyway, finally, remove the usage of PortableRemoteObject
, this is no longer needed. The client code will then look like this:
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
properties.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
properties.setProperty(Context.PROVIDER_URL, "localhost:1099");
context = new InitialContext(properties);
SinaRemote sina = (SinaRemote) context.lookup("SinaBean/remote");