I created a small junit test that is launched from my application client.
My server is glassfish 3.1.1 .
When i run the test i get this error:
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
I have already added the propreties to the context but nothing changed.
This how i set up my context:
#Before
public void setUp() throws NamingException {
Properties props = new Properties();
System.out.println("launch");
props.setProperty("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs",
"com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state",
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
// optional. Defaults to localhost. Only needed if web server is running
// on a different host than the appserver
//props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
//props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
Context annuaire = new InitialContext(props);
GeoBeanRemote service = (GeoBeanRemote) annuaire.lookup(GeoBeanRemote.class.getName());
BeanProvider.setGeoBean(service);
}
app-serv.rt and gf-client are added to my run-test.
Thanks.
I've the same issue when jndi.properties was missing from my classpath.
Addendum:
I'm feeling a bit silly here, but I don't think you can set your initial context that way. I note though that JNDI properties don't even need to be set on Glassfish, so color me confused.
Related
In my web.xml od my webapp application I have following element:
<env-entry>
<env-entry-name>aMessage</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello World</env-entry-value>
</env-entry>
EJB in this web application can read it:
final InitialContext context = new InitialContext();
final Context env = (Context) context.lookup("java:comp/env");
System.out.println("MSG: " + env.lookup("aMessage")); // prints Hello World
Now I am trying to change that value with asadmin:
martin#bono:~/glassfish4/glassfish/bin$ ./asadmin set-web-env-entry --name=aMessage --value=test webapp
Previous env-entry setting of aMessage for application/module webapp was overridden.
Command set-web-env-entry executed successfully.
martin#bono:~/glassfish4/glassfish/bin$ ./asadmin list-web-env-entry webapp
Reported 1 env-entry setting
aMessage (java.lang.String) = test ignoreDescriptorItem=true //
Command list-web-env-entry executed successfully.
Unfortunately my EJB still prints the old value "Hello World", even after re-enabling this webapp or restarting webserver.
I've also tried to set-web-env-entry for names not defined in web.xml and also played with --ignoredescriptoritem parameter, but nothing helped. Enumerating whole environment also shows no additional or changed web environment entries, but shows he old one plus many other objects not related to this problem:
final NamingEnumeration<Binding> enu = env.listBindings("");
while (enu.hasMore()) {
final Binding binding = enu.next();
System.out.println(binding);
}
What I am doing wrong?
It seems to be a bug - but I have another solution for your needs. You can use custom resources which are available in glassfish. You have to declare custom resource in domain.xml
<resources>
<custom-resource factory-class="org.glassfish.resources.custom.factory.PropertiesFactory" res-type="java.util.Properties" jndi-name="test/properties">
<property name="aMessage" value="Hello World"></property>
</custom-resource>
</resources>
then you can use it in the code
public class Environment
{
public String getProperty() {
InitialContext ctx = new InitialContext();
properties = (Properties) ctx.lookup("test/properties");
if(properties == null) {
return "default value - hello";
}
return properties.getProperty("aMessage");
}
}
The one disadvantage of this approach is that custom resources are global for whole domain. But this solution has advantage you can change resources by using asadmin and admin web console also.
I have configured MysqlDataSource in tomcat using this link.I have written junit test cases.when am i calling below connection from junit it throws following errors.
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
I have used following code
class DataConnection {
private static DataSource dataSource;
public DataConnection() {
try {
Context ctx = new InitialContext();
dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
new DataConnection();
Connection con=dataSource.getConnection();
return con;
}
}
How to call tomcat from junit? How to achieve this?
The code you give gets the database connection from JNDI, e.g. when running in tomcat from the container. However, for Unit Tests (assuming that's what you use JUnit for) I'd rather suggest to use "dependency injection" - e.g. explicitly pass a database connection to the code under test or manually set it up before the test runs.
There's no need to rely on JNDI for executing your tests: That's not what you want to test, instead, you want to just verify that your actual code is running correctly.
You don't need any fancy library (e.g. spring) for dependency injection, just a slightly adjusted architecture. This will greatly enhance the testability of your application and lower the execution time of your tests.
(This is based on my assumptions of your situation based on the little bit of information that you give in your question)
Give TomcatJNDI a try. It is based on embedded Tomcat but initializes only Tomcat's JNDI environment without starting a server. So you can access all your resources as configured in Tomcat's configuration files in tests or from within any Java SE application. The API is simple. For instance to get a DataSource declared in context.xml:
TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processContextXml(contextXmlFile);
tomcatJNDI.start();
Then you can lookup the DataSource as usual
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/path/to/datasource")
More information about TomcatJNDI can be found here.
I'm creating a java enterprise application which uses activemq to send messages to a standalone queue broker.
I currently maintain access to long lived resources through jndi lookup which works quite nicely. I'd like to continue this pattern with the ActiveMQ connection factories and queue connection factories, however in the amq documentation it specifies that my jndi.properties should have:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
while the default jndi.properties (which works with my simple object and facade lookups has:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
Can I use one with the other? Can I have two jndi.properties files or two initial contexts somehow?
This question shows how to configure ONLY activemq through jndi. I want them to play nicely together.
You can create any number of InitialContext objects you want. You just have to pass environment to its constructor to properly initialize it.
So you can still safely use jndi.properties and initialize initial context for activemq with the code which may look like this:
public void setUpActiveMQResources() throws IOException, NamingException {
InitialContext context = createInitialContext("/activemq.jndi.properties");
// do what you want
}
public InitialContext createInitialContext(String resource) throws IOException, NamingException {
InputStream is = getClass().getResourceAsStream(resource);
Properties props = new Properties();
try {
props.load(is);
} finally {
is.close();
}
return new InitialContext(props);
}
activemq.jndi.properties in that case is the classpath resource with content like here
I'm trying to (unit) test my EJB class without having to startup my websphere environment. Now I'm using Open EJB, but there are some issues with resolving the JNDI Names for other EJBs that are used within my EJB... and there is no way for me to inject mocked classes from my test right now.
Getting the InitialContext
final Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
properties.setProperty("log4j.category.OpenEJB.options ", "debug");
properties.setProperty("log4j.category.OpenEJB.startup ", "debug");
properties.setProperty("log4j.category.OpenEJB.startup.config ", "debug");
properties.setProperty("MyOwnDatasource.JdbcDriver ", "com.ibm.as400.access.AS400JDBCDriver");
properties.setProperty("MyOwnDataSource.JdbcUrl ", "jdbc:as400:MYHOSTNAME;database name=MYDATABASE;libraries=MYDEFAULTTABLE");
ic = new InitialContext(properties);
Inside my class under test there is a lookup for java:comp/env/ejb/PrefixEjbNameLocalHome and I can not set Open EJB to generate JNDI names in that format.
Additional Property for JNDI name format
I tried setting the formatting rule like this:
properties.setProperty("openejb.jndiname.format ", "comp/env/ejb/{interfaceClass}");
Properties aren't used?
Also the logging configuration isn't used. I'm only seeing INFO and WARN messages from Open EJB, although I set log4j.category.OpenEJB.* and the like to DEBUG or TRACE.
It's the "java:" part that is messing up your test case. Basically Context.INITIAL_CONTEXT_FACTORY and "java:" are mutually exclusive. The InitialContext class has a special understanding of "java:" or any "foo:" lookups and if they are at the beginning of the name it will not use INITIAL_CONTEXT_FACTORY you specified. A somewhat frustrating part of JNDI.
If you lookup the name exactly as printed in the log, it will work. So for example this log message:
INFO - Jndi(name=WidgetBeanRemote) --> Ejb(deployment-id=WidgetBean)
Then in code:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
// set any other properties you want
Context context = new InitialContext(p);
Object o = context.lookup("WidgetBeanRemote");
I'm having problems calling EJB3 stateless bean outside the container.
Code for getting the object reference:
Context envCtx = (Context) context.lookup("ejb");
MyObject o = (MyObject) envCtx.lookup(MyObject);
The second row results in exception:
java.lang.ClassCastException: javax.naming.Reference
I use JBoss.org 5.1.0 GA.
Based on some other posts I suspect this might be due to wrong version of client libraries. However, I'm unsure which library jar(s) I should include in the jar? (I get the error using 5.0.4.GA jnpserver.)
For JBoss, your code should look something like that:
Properties properties = new Properties();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","=org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url","localhost:1099");
Context context = new InitialContext(properties);
(EchoBeanRemote) c.lookup("EchoBean/remote");
If you prefer, you can put the JNDI environement settings in a jndi.properties file (that needs to be on the classpath):
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
And use the non-arg InitialContext constructor:
Context context = new InitialContext();
(EchoBeanRemote) c.lookup("EchoBean/remote");
This is obviously more portable.
And in both case, you'll need jbossall-client.jar on the classpath on the client side.
P.S.: You can check the Global JNDI Name your bean is registered at in the JNDI View of the web-based JMX console (if it still exists).