How to get initial context from GlassFish server in Java SE?
Solution 1
In order to use JNDI you need to specify the java.naming.factory.initial
somehow, just like the error message says.
There are multiple ways of doing this:
You could specify it as a system property in Glassfish, through server (Admin server)
-> Properties
Alternatively, you could specify it in a HashTable and pass it to the constructor of InitialContext
:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.SerialInitContextFactory");
Context ctx = new InitialContext(env);
If you use Spring you could also do this:
<bean id="myJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">com.sun.enterprise.naming.SerialInitContextFactory</prop>
<prop key="java.naming.factory.url.pkgs">com.sun.enterprise.naming</prop>
<prop key="java.naming.factory.state">com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl</prop>
</props>
</property>
</bean>
See http://docs.oracle.com/javase/jndi/tutorial/beyond/env/context.html for more information.
As far as the actual values go, the Spring config above is what we actually use with Glassfish
. We do not specify provider url or credentials..
I don't think this is really connected to creating an ldap-realm, Glassfish might use JNDI to lookup the realm though.
Edit:
I think I might understand what the problem is, you are trying to access remote classes from a client. With this assumption, you can use Spring to do this, with JndiTemplate. Assuming that the server makes available the correct EJB-classes, do this on the client side:
Create a bean for JndiTemplate:
<bean id="myJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">com.sun.enterprise.naming.SerialInitContextFactory</prop>
<prop key="org.omg.CORBA.ORBInitialHost">${servername}</prop>
<prop key="org.omg.CORBA.ORBInitialPort">${jndiport}</prop>
</props>
</property>
</bean>
You can then use this bean to lookup stuff on the server. If you want to take it a step further, and call your own remote EJB-classes, you could also do this:
<bean id="ejbProxy"
class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"
abstract="true">
<property name="refreshHomeOnConnectFailure" value="true"/>
<property name="cacheHome" value="true"/>
<property name="lookupHomeOnStartup" value="true"/>
<property name="resourceRef" value="false"/>
<property name="jndiTemplate" ref="mySpringTemplate"/>
</bean>
And then define beans as:
<bean id="someRemoteService" parent="ejbProxy">
<property name="jndiName"
value="com.company.service.MyRemoteService"/>
<property name="businessInterface"
value="com.company.service.MyRemoteService"/>
</bean>
You can inject this like a regular bean, any calls to it will be made to the server.
Solution 2
In order to access glassfish (and too look up the EIB) running on localhost I had to use:
public class Main {
public static void main(String[] args) throws NamingException {
java.util.Hashtable<String, String> hashTable = new Hashtable<String, String>();
hashTable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.impl.SerialInitContextFactory");
hashTable.put(Context.STATE_FACTORIES, "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
hashTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
Context ctx = new InitialContext(hashTable);
// Looks up the EJB with JNDI
BookEJBRemote bookEJB = (BookEJBRemote) ctx.lookup("java:global/chapter08-service-1.0/BookEJB!org.agoncal.book.javaee7.chapter08.BookEJBRemote");
}
}
When glassfish is running on localhost, Context can be initiated with default properties (without hashtable parameter)
Context ctx = new InitialContext();
pshemek
Updated on June 04, 2022Comments
-
pshemek about 2 years
I have a class like below:
public class Poligon { public static void main(String[] args) { try { Context ctx = new InitialContext(); ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup("jms/javaee7/ConnectionFactory"); Destination destination = (Destination) ctx.lookup("jms/javaee7/Topic"); JMSContext context = connectionFactory.createContext(); OrderDTO order = context.createConsumer(destination).receiveBody(OrderDTO.class); System.out.println("Order received: " + order); } catch (NamingException ex) { Logger.getLogger(Poligon.class.getName()).log(Level.SEVERE, null, ex); } } }
I would like to get the InitialContext() form the server (glassfish) running on localhost, but I get the below error:
SEVERE: null javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662) at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307) at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:344) at javax.naming.InitialContext.lookup(InitialContext.java:411) at poligon.Poligon.main(Poligon.java:29)
I know I have to create ldap realm on glassfish and add the below code (? - dont know the exact values) to my class:
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "?"); env.put(Context.PROVIDER_URL, "?"); env.put(Context.SECURITY_PRINCIPAL, "?"); env.put(Context.SECURITY_CREDENTIALS, "?"); Context ctx = new InitialContext(env);
My problem is that I dont know what values should be at:
Context.INITIAL_CONTEXT_FACTORY Context.PROVIDER_URL (I want it on localhost) Context.SECURITY_PRINCIPAL Context.SECURITY_CREDENTIALS
And I dont know how I should configure glassfish server?
maven dependencies
<dependency> <groupId>org.glassfish.main.extras</groupId> <artifactId>glassfish-embedded-all</artifactId> <version>4.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.main.appclient.client</groupId> <artifactId>gf-client</artifactId> <version>3.1.2.2</version> </dependency>
-
pshemek almost 10 yearsI used the hashTable solution but i got an error: javax.naming.NoInitialContextException: Cannot instantiate class: com.sun.enterprise.naming.SerialInitContextFactory [Root exception is java.lang.ClassNotFoundException: com.sun.enterprise.naming.SerialInitContextFactory]
-
Tobb almost 10 yearsHmm that class should be included with Glassfish. You are running this on glassfish?
-
pshemek almost 10 yearsNo it is stand alone application.
-
Tobb almost 10 yearsThen you need to add some jars to the classpath, glassfish-embedded-all has the class, with a pom dependency to org.glassfish.main.appclient.client:gf-client (has a transitive dep to glassfish-naming which holds the class) should also do the trick. See stackoverflow.com/questions/12002948/…
-
pshemek almost 10 yearsi updated my maven repository and now it says: Could not resolve dependencies for project com.mycompany:JMS:jar:1.0-SNAPSHOT: The following artifacts could not be resolved: org.eclipse.persistence:javax.persistence:jar:2.0.4.v201112200901, org.eclipse.persistence:org.eclipse.persistence.core:jar:2.3.2, org.eclipse.persistence:org.eclipse.persistence.jpa:jar:2.3.2, org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen:jar:2.3...
-
Tobb almost 10 yearsSomething to do with your remote maven repositories i guess. Make sure you have the correct remote repositories set up.
-
Baldy almost 10 yearsIn your
main()
method you are instantiating anInitialContext
and calling various Glassfish methods without ever starting Glassfish. See glassfish.java.net/docs/4.0/embedded-server-guide.pdf for information on how to configure your project and start Glassfish. -
Tobb almost 10 yearsI don't think an embedded glassfish it what op wants, but the question is not very clear so can't be sure..