EJB3 Glassfish JNDI lookup
I am using Glassfish-bundled Eclipse IDE. I wrote a simple EJB application. but it doesn't work.
@Stateless
@Remote(CalculatorRemote.class)
@Local(CalculatorLocal.class)
public class Calculator implements CalculatorRemote, CalculatorLocal {
@Override
public String sayHello(String name) {
System.out.println("ejb:"+name);
return null;
}
}
----
@Remote
public interface CalculatorRemote {
public String sayHello(String name);
}
-------
@Local
public interface CalculatorLocal {
public String sayHello(String name);
}
I wrote a standalone client to test, but failed. can't find JNDI.
public class Main {
public static void main(String[] args) throws Exception {
InitialContext ctx = new InitialContext();
CalculatorRemote bean = (CalculatorRemote) ctx.lookup("java:global/TestEAR/TEjb/Calculator!com.CalculatorRemote");
bean.sayHello("Billy Bob");
}
}
In the server log, it said
INFO: Portable JNDI names for EJB Calculator : [java:global/TestEAR/TEjb/Calculator!com.CalculatorRemote, java:global/TestEAR/TEjb/Calculator!com.CalculatorLocal]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB Calculator : [com.CalculatorRemote, com.CalculatorRemote#com.CalculatorRemote]
Also, I have tried
ctx.lookup("com.CalculatorRemote")
still doesn't work.
error message is
java.lang.NullPointerException
at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297)
at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.Main.main(Main.java:9)
Exception in thread "main" javax.naming.NamingException: Lookup failed for 'java:global/TestEAR/TEjb/Calculator!com.CalculatorRemote' in SerialContext [Root exception is javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext [Root exception is java.lang.NullPointerException]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.Main.main(Main.java:9)
Caused by: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext [Root exception is java.lang.NullPointerException]
at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialCont开发者_运维百科ext.java:276)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
... 2 more
Caused by: java.lang.NullPointerException
at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297)
at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271)
... 3 more
Please help me.
Can you just add the above lines:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
// glassfish default port value will be 3700,
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
InitialContext ctx = new InitialContext(props);
CalculatorRemote bean = (CalculatorRemote) ctx.lookup("java:global/TestEAR/TEjb/Calculator! com.CalculatorRemote");
I have created a blog post here using EJB3x with Glassfish v3. http://anirbanchowdhury.wordpress.com/2012/06/07/ejb-3-application-in-glassfish-3x/
I think that exception is thrown because you didn't configure the initial context properly. Either create a jndi.properties file, or create a hash table with the properties and it send it to the constructor of IntialContext.
Creating EJB3 using Netbeans and Glassfish
Just today I had an issue with this. Your standalone client failed but it will work inside GF EJB container.
For client testing you need 2 things to make it work:
- from GlassFish_install_folder\glassfish\lib get javaee, gf-client and appserv-rt jars. the last one contains jndi.prop so you could use default c-tor InitialContext();
- from GlassFish_install_folder\glassfish\modules get all jars.
These jars need to be in your classpath. It is silly but I don`t know yet the minimum jars from 2) in order to make it work.
Solution is as below.
In the code below, You have to call a bean in another JVM Right ? For ex, your main class is in JRE and BEAN is in Glassfish JVM.
The code is partially right. But more coded is needed to your class..
Go through this link, complete example you can follow.
- Accessing a stateless EJB from another instance of Glassfish
public class Main {
public static void main(String[] args) throws Exception {
InitialContext ctx = new InitialContext();
CalculatorRemote bean = (CalculatorRemote) ctx.lookup("java:global/TestEAR/TEjb/Calculator!com.CalculatorRemote");
bean.sayHello("Billy Bob");
}
}
- Most of your code is correct the catch is the client, as you have local and remote interfaces I have added my comments in client hope its self explanatory.And....
- Added on EJB @javax.ejb.Stateless(name = "CalculatorEJB") //This is portable No Vendor locked in. Alternative is mappedName which i believe is more weblogic and glassfish centric.
- Ensure you have client.jar in your class path.
- I have deployed the EJB's in glassfish container once ear deployed successfully, run the client.
- Apart from the below code you wont need any other configurations. This code is portable and should work on most containers however Surprises is fun do run as is and let me know .....
==============================
- The Remote interfaces
package com.au.ejbs;
import javax.ejb.Local;
@Local
public interface CalculatorLocalI {
String sayHello(String name);
}
package com.au.ejbs;
import javax.ejb.Remote;
@Remote
public interface CalculatorRemoteI {
String sayHello(String name);
}
=================================
2. The Impl
package com.au.ejbs;
@javax.ejb.Stateless(name = "CalculatorEJB") //Added this is portable instead of using mappedName
public class Calculator implements CalculatorRemoteI, CalculatorLocalI {
@Override
public String sayHello(String name) {
return "ejb:"+name;
}
}
======================================
3. The client
package com.au.clients;
import com.au.ejbs.CalculatorRemoteI;
import javax.naming.InitialContext;
public class CalculatorT {
public static void main(String[] args) throws Exception {
InitialContext ctx = new InitialContext();
CalculatorRemoteI bean = (CalculatorRemoteI) ctx.lookup("java:global/ejb3_2_ear_exploded/ejb/CalculatorEJB!com.au.ejbs.CalculatorRemoteI");
//portable syntax java:global/[ ear name]/[module name normally the jar name in my case ejb.jar within the ear, ejb3_2_ear_exploded]/name in ....javax.ejb.Stateless(name = "CalculatorEJB")/
//Now since you have both local and remote interfaces so the extra after the bang ! symbol namely the explicit remote interface name.
//if you had only 1 remote interface impl you will require only (CalculatorRemoteI) ctx.lookup("java:global/ejb3_2_ear_exploded/ejb/CalculatorEJB");
System.out.println("===output==" +bean.sayHello("Billy Bob"));
}
}
4. output
===output==ejb:Billy Bob
精彩评论