Java – narrow down the class cast exception in JNDI reference in EJB
I'm trying to write a simple stateless session bean, but I gave a narrow reference when looking up
I use
My beans
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 family 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 components
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>
Exceptions I received
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 would appreciate your advice very much
Solution
First, your XML file indicates that you are using EJB3 (actually, this is the only version worth considering), but your bean is EJB2 bean
If your server does run EJB 3, delete the XML file and delete the unnecessary EJB home directory and component implementation Add @ stateless annotation and remote interface Make sure it looks 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 that people use here are almost endless. Anyway, it is basically always effective, but only to ensure that the correct variants are used)
In addition, and probably the main culprit, you use EJB name if it is a global JNDI name, but this is not the case EJB name is a somewhat confusing logical name that is used as an additional qualifier when referring to a specific bean when injecting or creating EJB Ref
In your case, you set it to be the same as the unqualified bean name, which is already the default Since sinabean exists, I guess you deploy an independent EJB jar instead of an ear, right?
If you are using JBoss as 6 (EJB 3.1), you can use global portable JNDI names. Otherwise, you can use the old JBoss specific JNDI names: [ear name] / [simple bean name] / remote Note that [simple bean name] is not EJB name, but in your case, they are exactly the same Since [ear name] / is deleted when you only deploy EJB jars, this explains the exception you get: sinabean is a directory (context in JNDI terminology), which can contain local, remote and no actual entry interfaces What you're doing is trying to convert this intermediate directory node into a proxy for your bean, which of course doesn't work
In any case, finally, remove the usage of portableremoteobject, which is no longer needed The client code will 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");