How to connect to WebSphere in J2EE client environment? - java

I'm trying to connect to EJB on WebSphere 7.0. The EJB requires javax.ejb.SessionContext and reads Principal from it, so I need to log in before calling it.
I'm using the following code in stand-alone application:
import javax.naming.InitialContext;
import javax.security.auth.login.LoginContext;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
public static void main(String[] args) throws Exception {
InitialContext ic = new InitialContext(System.getProperties());
LoginContext lc = new LoginContext("WSLogin",
new WSCallbackHandlerImpl("myuser","mypass"));
lc.login();
WSSubject.setRunAsSubject(lc.getSubject());
SessionContext sessionContext=(SessionContext) ic.lookup(
"java:comp/env/sessionContext");
}
I've added the entry to my jmxremote.access:
myuser readwrite
However, I get an exception:
Caused by: javax.naming.ConfigurationException: Name space accessor
for the java: name space has not been set. Possible cause is that the
user is specifying a java: URL name in a JNDI Context method call but
is not running in a J2EE client or server environment. at
com.ibm.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:98)
at
com.ibm.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:82)
at
javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at
javax.naming.spi.NamingManager.getURLContext(NamingManager.java:533)
at
javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:320)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
What else should I do, to run my code in the 'J2EE client environment' mentionend in the error message?

In order to use java:comp, you would need to package the client application in an .ear and use launchClient. Ultimately, that's just going to use -CCBootstrapHost/-CCBootstrapPort (or defaults) to connect to the target server to look up the EJB, so you could just use the EJB thinclient and use the fully-qualified EJB binding name instead (see the CNTR0167I messages in SystemOut.log).

you'll need to use the WAS client runtime JARs. WAS_HOME/AppServer/runtimes. You will need the ORB and the other service specific JARs. As an alternative to using launchClient, you can manually specify the context factory you'll be using here:
InitialContext ic = new InitialContext(System.getProperties());
set the
java.naming.factory.initial
variable (in your system env or in a Properties object) to
com.ibm.websphere.naming.WsnInitialContextFactory`

Related

JNDI clarification: JNDI API, JNDI SPI, Service Provider

I am new to JNDI and i read the online material by oracle:
http://docs.oracle.com/javase/jndi/tutorial/getStarted/overview/index.html
It says JNDI has two API's viz:
1) JNDI API
2) JNDI SPI
Further, it says to use JNDI we should have JNDI classes as well as Service providers.
From what I understand, Service provider is the actual resource (naming or directory) e.g. LDAP or DNS (Is this my understanding correct)?
I have following doubts:
a) JNDI API: We write application and use JNDI API's to do lookup etc. Now, who does implement JNDI API? Are they complete implementation in itself i.e implemented by JDK providers themselves or by service providers?
b) JNDI SPI: what exactly is it? Are JNDI SPI specific to a service e.g. LDAP server? Who provides implementations of JNDI SPI. FYI i saw the source code of javax.naming.spi (among others) I saw there are some interface and some classes. And are these JNDI SPI's used in the application side (like If i am writing a simple application to do lookup from LDAP, so would this jar be in application)
Any help appreciated a lot.
EDIT:
Here is one simple JNDI program.
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JNDIExample {
public static void main(String s[]) {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
// Is "com.sun.jndi.fscontext.RefFSContextFactory" the SPI API?
// What exactly is this?
Context ctx = new InitialContext(env);
try {
// Create the initial context
Context ctx = new InitialContext(env);
// Look up an object
Object obj = ctx.lookup(name);
// Print it
System.out.println(name + " is bound to: " + obj);
} catch (NamingException e) {
System.err.println("Problem looking up " + name + ": " + e);
}
}
}
With respect to above example, i have following doubts:
In this above example we are mainly using javax.naming.* stuff; who implements them?
Where is the SPI involved in this?
a) JNDI API: We write application and use JNDI API's to do lookup etc. Now, who does implement JNDI API? Are they complete implementation in itself i.e implemented by JDK providers themselves or by service providers?
By whoeveer has registered an ObjectFactory. In a JRE application this probably won't extend beyond the JRE itself. In a Servlet or J2EE container it will definitely extend to include the container itself, for java:comp resources, and possibly the Web-app itself as well.
b) JNDI SPI: what exactly is it?
It is a Service Provider Interface that service providers must implement.
Are JNDI SPI specific to a service e.g. LDAP server?
Yes.
Who provides implementations of JNDI SPI.
Almost entirely the JRE itself.
Are these JNDI SPI's used in the application side
They can be, at least as far as ObjectFactory, but it isn't usual.
(like If i am writing a simple application to do lookup from LDAP, so would this jar be in application)
No.
EDIT Re your new questions:
In this above example we are mainly using javax.naming.* stuff; who implements them?
The JRE, specifically the factory class you specified and its friends.
Where is the SPI involved in this?
The factory class and friends implement the SPI.

Glassfish 4 Acessing EJBs via Standalone Application

I am trying to access an EJB via JSE Standalone application.
I was struggling a lot with JNDI Names not being found during lookup.
After some research without any solution I found in the Glassfish server log after a deploy a message stating something like:
"[glassfish 4.1] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=47 _ThreadName=admin-listener(4)] [timeMillis: 1424811833554] [levelValue: 800] [[ Portable JNDI names for EJB HelloBean:java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote, java:global/ponteWS/HelloBean!br.com.pontews.HelloBean]]]
"
I tried the remote name and voilá!!! It works.
I tried the other name and did not work.
Here comes the questions:
1-Why the JNDI name is so weird???? Is there something I can do in order to avoid the package name in front of the name of the bean?
2-What is the error I get when acessing the bean directly instead the HelloRemote Interface?
Here is the HelloRemote:
package br.com.pontews;
import javax.ejb.Remote;
#Remote
public interface HelloRemote {
public String sayHello(String name);
}
Here is the Bean:
package br.com.pontews;
import java.io.Serializable;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Stateless;
#Stateless(name="HelloBean")
#LocalBean
#Remote
public class HelloBean implements HelloRemote, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public HelloBean() {
}
public String sayHello(String name) {
return "Hello," + name + ".!" ;
}
}
Here is the call that works:
Object lookup =
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote");
Here is the call that does not works:
Object lookup =
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloBean");
And finally the error I get with call that does not work:
Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.RemoteException: CORBA NO_IMPLEMENT 1398079489 Maybe; nested exception is:
org.omg.CORBA.NO_IMPLEMENT: ----------BEGIN server-side stack trace----------
org.omg.CORBA.NO_IMPLEMENT: WARNING: 01000001: Missing local value implementation vmcid: SUN minor code: 1 completed: Maybe
:
:
:
Caused by: java.lang.ClassNotFoundException: br.com.pontews.EJB31_Generated__HelloBean__Intf____Bean (no security manager: RMI class loader disabled)
Thanks
The name you are using to lookup () has the format as specified by the EJB specification.
In case of glassfish it should also be possible to use the fully qualified name of the remote business interface to lookup the bean (https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#SessionBeanGlobalJNDINameAssignment). In your case this would be
br.com.pontews.HelloRemote
If you still have problems on the lookup the instructions here might help: (from https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB)
Step 1. Use the no-arg InitialContext() constructor in your code.
The most common problem developers run into is passing specific JNDI bootstrapping properties to InitialContext(args). Some other vendors require this step but GlassFish does not. Instead, use the no-arg InitialContext() constructor.
Step 2. Pass the global JNDI name of the Remote EJB to InitialContext.lookup()
Stand-alone java clients do not have access to a component naming environment (java:comp/env) or to the #EJB annotation, so they must explicitly use the global JNDI name to lookup the Remote EJB. (See here for more information on how global JNDI names are assigned to EJB components) Assuming the global JNDI name of the Remote EJB is "FooEJB" :
For Beans with a 3.x Remote Business interface :
Foo foo = (Foo) new InitialContext().lookup("FooEJB");
Note that in the EJB 3.x case the result of the lookup can be directly cast to the remote business interface type without using PortableRemoteObject.narrow().
For EJB 2.1 and earlier session/entity beans :
Object homeObj = new InitialContext().lookup("FooEJB");
FooHome fooHome = (FooHome)
PortableRemoteObject.narrow(homeObj,FooHome.class);
Foo foo = fooHome.create(...)
Step 3. Include the appropriate GlassFish .jars in the java client's classpath.
For GlassFish 3.
Include $GLASSFISH_HOME/glassfish/lib/gf-client.jar in the client's classpath.
E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :
java -classpath $GLASSFISH_HOME/glassfish/lib/gf-client.jar:/home/user1/myclasses acme.MyClient
Note that the Java EE 6 API classes are automatically included by gf-client.jar so there is no need to explicitly add javaee.jar to the classpath. gf-client.jar refers to many other .jars from the GlassFish installation directory so it is best to refer to it from within the installation directory itself rather than copying it(and all the other .jars) to another location.
Note: gf-client.jar is located in $GLASSFISH_HOME/modules/gf-client.jar in GlassFish v3.

Imported java files is not being called

I am facing problem as the actual imported java file is not being called. Please have a look of my code :-
import javax.naming.Context;
import javax.naming.InitialContext;
.....
public class ABC{
.....
1. Context lContext = null;
2. ObjectDataSourceFactory lSource = null;
3. try
4. {
5. lContext = new InitialContext();
6. lSource = ((ObjectDataSourceFactory)lContext.lookup(....));
}
catch (Exception e)
{
}
The Problem I am facing here is : when flow control goes into line number 6. it calls the "lookup method" from "SelectorContext.java" but not from "InitialContext.java", I have found this with the help of DEBUGGING mode in eclipse . As a result it cannot find the proper JNDI and gives exception.
FYI..
My code is running on Tomcat6.
I have set the classpath of jar files from my JRE1.6 and so the JDK.
Can someone please suggest me -
how can I know from which JAR this "SelectorContext.java" is being called and how to make it to Look into the InitialContext.class which is present inside RT.JAR, if I am not wrong ?
Your understanding is not correct. SelectorContext is one of the JNDI implementations of the tomcat.
There is an option to use external JNDI context by setting java.naming.factory.initial as system variable. This is set by Tomcat (javaURLContextFactory) to provide it's own JNDI services.
When you call new InitialContext(), JVM sees if there is user provided naming factory, and if it is available, JVM calls initialFactory.getInitialContext to get the custom JNDI implementation and makes this default and all the method calls to context is inturn routed to custom implementation.
In your case, call to SelectorContext is right, see if you have the required configuration in place to have the resource in JNDI.

How to debug a call to an EJB from a Netbeans platform module

Using GlassFish 3.1.2, I try to call a Session Bean from a Netbeans platform module, and I get a null pointer exception. My problem is that I have no trace explaining how / where the NPE is generated.
The code in my Module is simply:
import ejb.MySessionRemote;
import javax.ejb.EJB;
public class TestServer {
#EJB
private static MySessionRemote mySession;
public boolean execute() {
System.out.println("result = " + mySession.getString()); //NPE here: mySession is null
return true;
}
}
The Session bean "My Session", the remote interface and the application deployed on the server side are just the ones from this tutorial: https://netbeans.org/kb/docs/javaee/entappclient.html
Any help greatly appreciated.
Note: I've checked this tutorial, without solving my issue.
If mySession is null, it was probably not injected. You can inject into managed beans (EJBs for example), because these instances are managed (created/removed) by a container, and the container does the injection for you.
You can possibly inject into a POJO, if you use CDI.
If TestServer is part of a stand-alone application for example, try to lookup the EJB using JNDI. This is what your tutorial does as well. It involves setting up the properties to get an InitialContext, and the lookup of the EJB using JNDI.

#EJB annotation does not work for initialize bean within the EJB application

I have a Maven project with this structure:
-myproject
-myproject-ear
-myproject-service
-webservice
-myproject-ejb
In the myproject-ejb I have this java packages:
-src/main/java/
-src/test/java/
I have an EJB and the corresponding bean implementation in
-src/main/java/org/mypackage/MyBean.java
-src/main/java/org/mypackage/MyBeanImpl.java
In src/test/java/ I have a test called MyBeanTest.java with the following code:
import javax.ejb.EJB;
import org.mypackage.MyBean;
import org.junit.*;
public class MyBeanTest {
#EJB
private MyBean myBean;
#Test
public void testBean() {
System.out.println("myBean: "+myBean); // prints null
myBean.writeToDB("Hello", "World"); // fails since myBean is null
}
}
When I run the unit test, the myBean is null. I am wondering why the #EJB annotation does not work. The test package is in the same application as the bean, so #EJB should work.
Any ideas?
EDIT 1
I found this link with the same problem as I have, but the solution there doesn´t seem to work for me. Am I doing anything wrong?
package org.myproject.ejb;
import java.util.Hashtable;
import java.util.Properties;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import org.myproject.ejb.MyBean;
import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
import org.junit.*;
public class MyBeanTest {
private MyBean myBean;
#Before
public void init() {
try {
Properties clientProp = new Properties();
clientProp.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
clientProp.put("remote.connections", "default");
clientProp.put("remote.connection.default.port", "4447");
clientProp.put("remote.connection.default.host", "localhost");
clientProp.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(clientProp);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);
Properties env = new Properties();
env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_CREDENTIALS, "testing");
InitialContext ctx = new InitialContext(env);
myBean = (MyBean) ctx.lookup("java:app/myproject-ejb-1.0-SNAPSHOT/MyBeanImpl");
}
catch(NamingException ex) {
ex.printStackTrace();
}
}
#Test
public void testBean() {
System.out.println("ejb: "+myBean); // prints null
}
}
The error I get with the above configuration is:
WARN: Unsupported message received with header 0xffffffff
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)
Container resource injection, such as #EJB, requires a populated JNDI directory and only works within Java EE managed components executing in a Java EE container. Is a challenge for unit testing. See JSR318 Java EE 6 Platform Spec, section EE.5 Resources, Naming, and Injection.
You're now attempting JNDI lookup - Java SE unit test app remotely connecting its JNDI Context. Disadvantages: must deploy full Java EE 6 app as precondition to run test; test-bugfix-build-deploy-retest lifecycle can slow things.
Some issues:
Your username/password properties are different than JBoss doc;
From doc it appears JNDI lookup name needs to be "ejb:..." rather than "java:app/..." because the JBoss EJB-client-project code uses this to intercept the lookup. Also from Java EE 6 platform spec EE.5.2.2: Names in java:app namespace are shared by all components in all modules in a single Java EE app. If your test is a separate JSE app using java:app, I suspect JBoss treats it as separate to the single Java EE application, and lookup will fail.
Make sure you lookup the interface, not the implementation class (i.e. the EJB no interface view) for remote access
You're refering to an unusual reference showing direct use of EJBClientConfiguration & EJBClientContext. It seems this is not required/preferred.
Try these actions:
Include these properties:
clientProp.put("remote.connection.default.username", "admin");
clientProp.put("remote.connection.default.password", "testing");
Change client reference:
java:app/myproject-ejb-1.0-SNAPSHOT/MyBeanImpl to
ejb:<app-ear-name>/<module-jar-name>/<jboss-optional-distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
E.g. if MyBean is a stateless EJB deployed in myproject-ejb-1.0-SNAPSHOT.jar (without any ear). Then:
ejb:/myproject-ejb-1.0-SNAPSHOT//MyBeanImpl!org.mypackage.MyBean
If it's a stateful EJB, then add "?stateful" to string.
Setup ejb-client.properties directly (via file or program) and apply directly to JNDI Context. See https://docs.jboss.org/author/display/AS72/EJB+invocations+from+a+remote+client+using+JNDI and https://docs.jboss.org/author/display/AS72/Scoped+EJB+client+contexts and http://middlewaremagic.com/jboss/?p=1177
In future: use CDI for injection; JUnit + CDI #Mock for "POJO" unit testing; Arquillian for "Java EE" unit/module testing in containers. Then you could avoid/reduce tests like (2) above (JSE client -> EJB).
CDI supports:
Java EE resource injection into POJOs (including #EJB annotation). This still requires a deployed Java EE app/component and populated JNDI directory to lookup.
Managed beans as POJOs or Java EE components (incl. EJBs) - inject "any" to "any" with superior #Inject annotation. Works without JNDI directory, is typesafe & bean scope-aware.
Supports unit testing via simple mocking. Use #Mock & #Specializes to declare replacement version for any bean. Test EJB clients without EJBs. Test EJBs as POJOs.
To enable CDI, include a beans.xml file (can be empty, if all config via annotation).
To declare a managed bean:
optional scope above class e.g. #SessionScoped
no-arg constructor / #Inject on constructor
Use this to inject a reference:
#Inject (optional #MyDeclaredQualifier) private MyBean myBean;
Arquillian ("JUnit for Java EE 6") runs test code itself on a Java EE server. It dynamically deploys test code to configured container(s) and runs tests. It supports #EJB annotation, JNDI connection becomes simple and you can include Java EE classes in unit tests without mocking, or refactoring to abstract away from them.
1) Annotation injection is done by container. So the class which is not managed(container managed) will not be able to do annotation injection.
2) Now, in this scenarios, you will have to make a manual call to JNDI and retrieve EJB instance:
ie:
InitialContext ctx = new InitialContext();
MyBean bean = (MyBeanRemote) ctx.lookup("java:global/<portable jndi name of your bean>");
Note: The use of no arg constructor InitialContext(). Because your java class is deployed in a server I presume. Or else you may need to specify context factory class if your class is a standalone java class, depending on the vendor.
Note: You will need Bean Remote interface if you are making a call to EJB from a different application (ie: different war, ear ...) or else Local interface is enough.
This exception is thrown when no initial context implementation can be created. The policy of how an initial context implementation is selected is described in the documentation of the InitialContext class.
This exception can be thrown during any interaction with the InitialContext, not only when the InitialContext is constructed. For example, the implementation of the initial context might lazily retrieve the context only when actual methods are invoked on it. The application should not have any dependency on when the existence of an initial context is determined.

Categories

Resources