Call EJBs Deployed in GlassFish from the NetBeans Platform
http://netbeans.org/bugzilla/show_bug.cgi?id=125107
http://netbeans.org/bugzilla/show_bug.cgi?id=151368
http://forums.netbeans.org/viewtopic.php?t=37499
The last link above describes the problem of a user wanting to use the NetBeans Platform with Java SE 6 to call Session Beans deployed to GlassFish 3. Additional requirements are authentication, encryption, and using the same API on the client and the server. The user wants to use this code on the client:
System.setProperty("java.security.auth.login.config", "D:\\appclientlogin.conf");
GreeterBeanRemote greeterRemote = null;
Properties props = new Properties();
props.setProperty("org.omg.CORBA.ORBInitialHost", "10.1.1.13"); // default!
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); // default!
InitialContext context = new InitialContext(props);
ProgrammaticLogin login = new ProgrammaticLogin();
login.login("john.doe", "xxxxx");
greeterRemote = (GreeterBeanRemote) context.lookup("foo.bar.blubb.GreeterBeanRemote");
String output = greeterRemote.greetMe("John Doe");
System.out.printf("Got Answer:%ngreeting=%s%n", output);So, let's create a simple example and see if we get this to work! I'm using NetBeans 7.0.1 with Glassfish 3.1 for the instructions below.Server Side
We will start by implementing the GreeterBean, a simple "HelloWorld" EJB:
- In NetBeans IDE (I use 7.0.1), create a new EJB Module Project (New Project -> JavaEE -> EJB Module) and call it "HelloWorldEJB" and choose Glassfish Server 3.1 (default) as the server.
- Create a Client (New Project -> Java -> Java Application) and call it "GreeterClient". We'll use this to demo the use case in a non NetBeans Platform project, i.e, outside the NetBeans Platform.
- Inside "HelloWorldEJB", create a new Session Bean (New -> Enterprise Java Beans -> Session Bean), call it "GreeterBean" in package "foo.bar.blubb", make it stateless (default), and create remote interface (Create Interface -> Remote in Project). As Project, select GreeterClient.
- Add business logic to the GreeterBean (Right-click in editor and choose "Insert Code -> Add Business Method"). Method name is "greetMe", make it return a String instead of void and add a String parameter "name", and implement like this:
- Now cut the GreeterBeanRemote interface from the GreeterClient Module foo.bar.blubb package and paste it in the HelloWorldEJB projects foo.bar.blubb package via drag & drop because one requirement is to reuse the server code in different projects, so we want everything in one place.
@OverrideThe system will automatically add the method definition to the interface as well.
public String greetMe(String name) {
return "Hello "+ name;
}
OK, that's the server part. You should now be able to deploy the project, and we can take care of the client side.
Client Side
First we'll try to get it to work in a standard Java Project. Afterwards, we'll port the code to the NetBeans Platform. We've already created a Java Application, "GreeterClient", which we can use for the standard Java client.
- In GreeterClient, open greeterclient.GreeterClient.java in the editor. Copy the code from the problem description with which this article started into the main method:
System.setProperty("java.security.auth.login.config", "D:\\appclientlogin.conf");
GreeterBeanRemote greeterRemote = null;
Properties props = new Properties();
props.setProperty("org.omg.CORBA.ORBInitialHost", "10.1.1.13"); // default!
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); // default!
InitialContext context = new InitialContext(props);
ProgrammaticLogin login = new ProgrammaticLogin();
login.login("john.doe", "xxxxx");
greeterRemote = (GreeterBeanRemote) context.lookup("foo.bar.blubb.GreeterBeanRemote");
String output = greeterRemote.greetMe("John Doe");
System.out.printf("Got Answer:%ngreeting=%s%n", output); - Replace the location of the "D:\\appclientlogin.conf" with a real conf file on your machine. There is one in the Glassfish directory "<GLASSFISH_HOME>/lib/appclient/appclientlogin.conf".
- Replace the string "10.1.1.13" with "localhost" for our demo. Later, when running the client, if you see an error message starting with this line:
org.omg.CORBA.COMM_FAILURE: FINE: IOP00410001: Connection failure: socketType: IIOP_CLEAR_TEXT; hostname: localhost; port: 3700 vmcid: OMG minor code: 1 completed: No
...the reason may be that your port number is wrong. Above, it is 3700. Go to the GlassFish Admin Console, which is accessible from the GlassFish node in the Services window, and then look in Configurations | server-config | ORB | IIOP Listeners and use the listener port of "orb-listener-1".
- This will still leave you with a lot of errors due to missing dependencies. To fix those, right-click the project's Libraries node and choose "Add Project" from the context menu. Select "HelloWorldEJB" as the project. (Avoid the cyclic reference problem by removing the GreeterClient project from the Libraries node of the HelloWorldEJB first.) This should fix the first part of your imports.
- When the RemoteInterface was created in our GreeterClient, the system automatically added a "Java EE 6" library. Remove it. Instead, we'll add some GlassFish libraries. To do that, right click on the GreeterClient project node in the Projects window and choose Properties -> Libraries -> Add JAR/Folder to add the following jar files:
- appserv-rt.jar
- javaee.jar
- ejb.security.jar
- security.jar
Update: Since Glassfish version 3, you can use gf-client.jar instead. It contains all the above dependencies. Note: You'll find the above in the $GLASSFISH_HOME/lib and the $GLASSFISH_HOME/modules directory. - Now use the editor hint to throw the NamingException (add throws clause for javax.naming.NamingException).
We've now put everything together. The demo should work now as expected, once you run it, and you should get a response as follows:
Got Answer: greeting=Hello John Doe
Port to the NetBeans Platform
Now, back to our problem... let's use this from the NetBeans Platform.
- Create a new NetBeans Platform Application (New Project -> NetBeans Modules -> NetBeans Platform Application).
- Create a module "GreeterClient", with code name base "de.eppleton.ejbclient".
- Create a new Library Wrapper module and wrap the 4 JARs we used before, that is, appserv-rt.jar, javaee.jar, ejb.security.jar, and security.jar. Name the module "security" and give it any code name base you want.
- Create another Library Wrapper module and name it "ejb-container", wrapping the "ejb-container.jar" you'll find in <GLASSFISH_HOME>/modules/.
- Now create a third Library Wrapper module for the JAR file of the HelloWorldEJB project (HelloWorldEJB/dist/HelloWorldEJB.jar). If the "dist" dirrectory doesn't exist, do a "Clean & Build" on the HelloWorldEJB project first.
- In your GreeterClient module, create an Installer (New -> Installer/Activator) and, in the "restored()" method, add the code from your regular Java Client (including the customizations you made earlier).
- Fix the imports, after adding the Library Wrapper modules you just created as dependencies, and surround the block with a try/catch as indicated by the editor hint.
- Now move to the NetBeans Platform Application project and locate the "project.properties" file. Insert this configuration code to put everything you need on the classpath and configure Corba settings:
- Now run your application. You should see this, somewhere in your Output Window (not right at the end, but higher up):
Got Answer:
greeting=Hello John Doe
run.args.extra=-J-da -J-Dorg.omg.CORBA.ORBInitialHost=localhost -J-Dorg.omg.CORBA.ORBInitialPort=3700 \
-cp:a <GLASSFISH_HOME>/lib/appserv-rt.jar:<GLASSFISH_HOME>/lib/appserv-ext.jar:\
<GLASSFISH_HOME>/lib/appserv-deployment-client.jar:<GLASSFISH_HOME>/lib/javaee.jar:\
<GLASSFISH_HOME>/lib/jmxremote_optional.jar
Replace <GLASSFISH_HOME> with the real locations on your machine. These settings put everything you need on the classpath. The classpath always takes precedence over the modules.
Troubleshooting
Originally I worked on a solution for Glassfish 3.1-b29 and earlier versions, where the above did not work due to conflicting ClassLoader Hierarchies. It seems that problem has been fixed in Glassfish in the meantime. Still, if the above doesn't work for you, and you're getting ClassNotFound Errors instead, you can temporarily switch to the Glassfish ClassLoader like this in the "restored()" method of the ModuleInstall class:
ClassLoader prev = Thread.currentThread().getContextClassLoader();The problem now might be that the classloader can't see the GreeterBeanRemote. To fix that, you also need to add the HelloWorldEJB.jar to the Application classpath in the suite project.properties:
try {
Thread.currentThread().setContextClassLoader(EJBUtils.class.getClassLoader());
System.setProperty("java.security.auth.login.config", "<GLASSFISH_HOME>/lib/appclient/appclientlogin.conf");
GreeterBeanRemote greeterRemote = null;
Properties props = new Properties();
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
InitialContext context = new InitialContext(props);
ProgrammaticLogin login = new ProgrammaticLogin();
login.login("john.doe", "xxxxx");
greeterRemote = (GreeterBeanRemote) context.lookup("foo.bar.blubb.GreeterBeanRemote");
String output = greeterRemote.greetMe("John Doe");
System.out.printf("Got Answer:%ngreeting=%s%n", output);
} catch (NamingException ex) {
Exceptions.printStackTrace(ex);
} finally {
Thread.currentThread().setContextClassLoader(prev);
}
run.args.extra=-J-da -J-Dorg.omg.CORBA.ORBInitialHost=localhost -J-Dorg.omg.CORBA.ORBInitialPort=3700 \
-cp <path_to_your>/HelloWorldEJB.jar:<glassfish_home>/glassfish/lib/gf-client.jar
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Geoff Capper replied on Mon, 2011/09/05 - 12:04am
Hi Toni,
Thanks for the article, it actually works!
With regard to the project.properties classpath changes, how would I go about dealing with that when deploying the platform application as a remote client on a machine without an install of glassfish? Is it enough to wrap those jars in another library? I'm guessing not as that approach wasn't taken in the first place.
Thanks,
Geoff
Toni Epple replied on Mon, 2011/09/05 - 3:09am
Hi Geoff,
library wrappers won't work. They are only used for compilation ( Actually the above example should be cleaned up, because also the library modules we created here are not needed at runtime )
To deploy on a remote client, you need to carry the dependencies with you. Most importantly, you'll have to take a look at the manifests of the jars and make sure that all dependencies are there. E.g. gf-client.jar has these dependencies:
Class-Path: ../modules/woodstox-osgi.jar ../modules/jtype.jar ../modul
es/tools.jar ../modules/glassfish-corba-asm.jar ../modules/glassfish-
corba-codegen.jar ../modules/glassfish-corba-csiv2-idl.jar ../modules
/glassfish-corba-internal-api.jar ../modules/glassfish-corba-newtimer
.jar ../modules/glassfish-corba-omgapi.jar ../modules/glassfish-corba
-orb.jar ../modules/glassfish-corba-orbgeneric.jar ../modules/auto-de
pends.jar ../modules/config.jar ../modules/config-types.jar ../module
s/hk2.jar ../modules/hk2-core.jar ../modules/osgi-adapter.jar ../modu
les/grizzly-comet.jar ../modules/grizzly-config.jar ../modules/grizzl
y-framework.jar ../modules/grizzly-http.jar ../modules/grizzly-http-s
ervlet.jar ../modules/grizzly-lzma.jar ../modules/grizzly-portunif.ja
r ../modules/grizzly-rcm.jar ../modules/grizzly-utils.jar ../modules/
grizzly-websockets.jar ../modules/javax.mail.jar ../modules/pkg-clien
t.jar ../modules/jaxb-osgi.jar ../modules/activation.jar ../modules/e
l-api.jar ../modules/jaxrpc-api-osgi.jar ../modules/endorsed/jaxb-api
-osgi.jar ../modules/junit.jar ../modules/javax.persistence.jar ../mo
dules/org.eclipse.persistence.antlr.jar ../modules/org.eclipse.persis
tence.asm.jar ../modules/org.eclipse.persistence.core.jar ../modules/
org.eclipse.persistence.jpa.jar ../modules/org.eclipse.persistence.jp
a.modelgen.jar ../modules/org.eclipse.persistence.oracle.jar ../modul
es/endorsed/javax.annotation.jar ../modules/javax.ejb.jar ../modules/
javax.enterprise.deploy.jar ../modules/javax.jms.jar ../modules/javax
.management.j2ee.jar ../modules/javax.resource.jar ../modules/javax.s
ecurity.auth.message.jar ../modules/javax.security.jacc.jar ../module
s/javax.servlet.jar ../modules/javax.servlet.jsp.jar ../modules/javax
.transaction.jar ../modules/simple-glassfish-api.jar ../modules/admin
-core.jar ../modules/admin-util.jar ../modules/config-api.jar ../modu
les/monitoring-core.jar ../modules/acc-config.jar ../modules/gf-clien
t-module.jar ../modules/gms-bootstrap.jar ../modules/amx-core.jar ../
modules/amx-j2ee.jar ../modules/annotation-framework.jar ../modules/c
ommon-util.jar ../modules/container-common.jar ../modules/glassfish-a
pi.jar ../modules/glassfish-ee-api.jar ../modules/glassfish-naming.ja
r ../modules/internal-api.jar ../modules/scattered-archive-api.jar ..
/modules/stats77.jar ../modules/connectors-inbound-runtime.jar ../mod
ules/connectors-internal-api.jar ../modules/connectors-runtime.jar ..
/modules/work-management.jar ../modules/glassfish.jar ../modules/kern
el.jar ../modules/logging.jar ../modules/deployment-common.jar ../mod
ules/deployment-javaee-core.jar ../modules/dol.jar ../modules/ejb-con
tainer.jar ../modules/ejb-internal-api.jar ../modules/ldapbp-repackag
ed.jar ../modules/libpam4j-repackaged.jar ../modules/management-api.j
ar ../modules/flashlight-agent.jar ../modules/flashlight-framework.ja
r ../modules/gmbal.jar ../modules/ha-api.jar ../modules/class-model.j
ar ../modules/asm-all-repackaged.jar ../modules/bean-validator.jar ..
/modules/jms-core.jar ../modules/endorsed/webservices-api-osgi.jar ..
/modules/webservices-extra-jdk-packages.jar ../modules/webservices-os
gi.jar ../modules/orb-connector.jar ../modules/orb-iiop.jar ../module
s/eclipselink-wrapper.pom ../modules/jpa-connector.jar ../modules/per
sistence-common.jar ../modules/cmp-internal-api.jar ../modules/appcli
ent.security.jar ../modules/ejb.security.jar ../modules/jaspic.provid
er.framework.jar ../modules/security.jar ../modules/ssl-impl.jar ../m
odules/websecurity.jar ../modules/webservices.security.jar ../modules
/jta.jar ../modules/jts.jar ../modules/transaction-internal-api.jar .
./modules/el-impl.jar ../modules/jsp-impl.jar ../modules/war-util.jar
../modules/web-cli.jar ../modules/web-core.jar ../modules/web-embed-
api.jar ../modules/web-glue.jar ../modules/web-gui-plugin-common.jar
../modules/web-naming.jar ../modules/jsr109-impl.jar ../modules/mimep
ull.jar ../modules/tiger-types.jar ../modules/shoal-gms-api.jar ../..
/mq/lib/imq.jar ../../mq/lib/imqadmin.jar ../../mq/lib/imqutil.jar ..
/../mq/lib/fscontext.jar ../lib/install/applications/jmsra/imqjmsra.j
ar ../lib/install/applications/__ds_jdbc_ra/__ds_jdbc_ra.jar ../lib/i
nstall/applications/__cp_jdbc_ra/__cp_jdbc_ra.jar ../lib/install/appl
ications/__xa_jdbc_ra/__xa_jdbc_ra.jar ../lib/install/applications/__
dm_jdbc_ra/__dm_jdbc_ra.jar ../../javadb/lib/derby.jar ../../javadb/l
ib/derbyclient.jar ../../javadb/lib/derbynet.jar ../../javadb/lib/der
bytools.jar ../../javadb/lib/derbyrun.jar ../lib/install/applications
/jaxr-ra/jaxr-ra.jar
You might want to have a look at the "package-appclient" command which is used for Application Client Components as defined in the Java EE Spec:
http://download.oracle.com/docs/cd/E18930_01/html/821-2433/package-appclient-1m.html#scrolltoc
It creates a single jar file that you can unpack on the client. It contains a directory appclient/glassfish with everything you need, including the dependencies.
( Instead of appserv-rt.jar and javaee.jar you should then put gf-client.jar on the classpath. In glassfish 3 appserv-rt.jar is mainly a wrapper around gf-client.jar anyway, and javaee.jar is in gf-client.jar's dependencies. )
Tim Sparg replied on Mon, 2011/09/05 - 3:30am
Geoff Capper replied on Mon, 2011/09/05 - 4:52pm
in response to: eppleton
Toni Epple replied on Tue, 2011/09/06 - 2:02am
in response to: Geoffro
Right, but the package-appclient copies everything for you and you should be able to put it on the classpath using the endorsed mechanism. Unpack the jar created by that and add everything you need from there (the jars) to your application installer. Then you can use the endorsed (-J-Djava.endorsed.dirs=${GFCLIENT_PATH}) mechanism in your app.conf to put it on the application classpath. This way you should be able to deploy it together with your client.
Kazi Imran Aziz replied on Mon, 2011/09/26 - 6:08am
Hi Toni ,
Thank you very much for your post!
I tried to follow the example, but stilll I am getting the following error
SEVERE [org.openide.util.Exceptions]
java.lang.ClassNotFoundException: foo.bar.blubb.GreeterBeanRemote
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at com.sun.ejb.EJBUtils.getBusinessIntfClassLoader(EJBUtils.java:688)
at com.sun.ejb.EJBUtils.loadGeneratedRemoteBusinessClasses(EJBUtils.java:463)
at com.sun.ejb.EJBUtils.lookupRemote30BusinessObject(EJBUtils.java:414)
Caused: javax.naming.NamingException: ejb ref resolution error for remote business interfacefoo.bar.blubb.GreeterBeanRemote [Root exception is java.lang.ClassNotFoundException: foo.bar.blubb.GreeterBeanRemote]
at com.sun.ejb.EJBUtils.lookupRemote30BusinessObject(EJBUtils.java:434)
at com.sun.ejb.containers.RemoteBusinessObjectFactory.getObjectInstance(RemoteBusinessObjectFactory.java:75)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
at com.sun.enterprise.naming.impl.SerialContext.getObjectInstance(SerialContext.java:556)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:514)
Caused: javax.naming.NamingException: Lookup failed for 'foo.bar.blubb.GreeterBeanRemote' in SerialContext[myEnv={org.omg.CORBA.ORBInitialPort=3700, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, org.omg.CORBA.ORBInitialHost=localhost, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is javax.naming.NamingException: ejb ref resolution error for remote business interfacefoo.bar.blubb.GreeterBeanRemote [Root exception is java.lang.ClassNotFoundException: foo.bar.blubb.GreeterBeanRemote]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
[catch] at org.greeterclient.Installer.restored(Installer.java:35)
at org.netbeans.core.startup.NbInstaller.loadCode(NbInstaller.java:426)
at org.netbeans.core.startup.NbInstaller.load(NbInstaller.java:366)
at org.netbeans.ModuleManager.enable(ModuleManager.java:1025)
at org.netbeans.core.startup.ModuleList.installNew(ModuleList.java:318)
at org.netbeans.core.startup.ModuleList.trigger(ModuleList.java:254)
at org.netbeans.core.startup.ModuleSystem.restore(ModuleSystem.java:294)
at org.netbeans.core.startup.Main.getModuleSystem(Main.java:172)
at org.netbeans.core.startup.Main.start(Main.java:308)
at org.netbeans.core.startup.TopThreadGroup.run(TopThreadGroup.java:123)
at java.lang.Thread.run(Thread.java:662)
Any help would be highly appreciated!
Thanks in advance,
Kim
Toni Epple replied on Fri, 2011/10/07 - 8:45am
in response to: kim_berlin
Hi Kim,
which version of Glassfish and NetBeans do you use? Did you also follow the advice in the troubleshooting section?
Toni
Lee Hoo replied on Tue, 2011/10/11 - 6:43am
I like your post until I hit the last bit, the wall.
java.lang.ClassNotFoundException: com.sun.logging.LogDomains
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:262)
Caused: java.lang.ClassNotFoundException: com.sun.logging.LogDomains starting from ModuleCL@1192059[code.base.wahtyuownta] with possible defining loaders null and declared parents []
at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:264)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Caused: java.lang.NoClassDefFoundError: com/sun/logging/LogDomains
at com.sun.appserv.security.ProgrammaticLogin.<clinit>(ProgrammaticLogin.java:96)
at de.eppleton.ejbclient.Installer.restored(Installer.java:36)
at org.netbeans.core.startup.NbInstaller.loadCode(NbInstaller.java:426)
[catch] at org.netbeans.core.startup.NbInstaller.load(NbInstaller.java:366)
at org.netbeans.ModuleManager.enable(ModuleManager.java:1020)
at org.netbeans.core.startup.ModuleList.installNew(ModuleList.java:318)
at org.netbeans.core.startup.ModuleList.trigger(ModuleList.java:254)
at org.netbeans.core.startup.ModuleSystem.restore(ModuleSystem.java:294)
at org.netbeans.core.startup.Main.getModuleSystem(Main.java:172)
at org.netbeans.core.startup.Main.start(Main.java:308)
at org.netbeans.core.startup.TopThreadGroup.run(TopThreadGroup.java:123)
at java.lang.Thread.run(Thread.java:662)
My NetbeansIDE 7.0 (Build 201104080000); Java:1.6.0_26
Glassfish 3.1 Server.
I did try your Troubleshooting.
Thanks,
Lee
Toni Epple replied on Thu, 2011/12/15 - 4:23am
Hierarchical ClassLoaders are always sources of delight for developers. Especially when dealing with two independent classloader hierarchies, each aiming for world domination like here. I just got a mail from a user trying to use the above example from inside a TopComponent, and it doesn't work. Obviously the Module ClassLoader in NetBeans is updated in a way that conflicts with the example.
To fix it you need to switch to the EJBUtils classloader as explained in the TroubleShooting section:
Thread.currentThread().setContextClassLoader(com.sun.ejb.EJBUtils.class.getClassLoader());
This will solve the Lookup part of the problem and leave you with a new ClassNotFoundException, because EJBUtils classloader can't see the GreeterBeanRemote. To fix it, put your HelloWorldEJB.jar on the application classpath in the project.properties:
run.args.extra=-J-da -J-Dorg.omg.CORBA.ORBInitialHost=localhost -J-Dorg.omg.CORBA.ORBInitialPort=3700 \
-cp <path to your NetBeansProjects>/simple3tier/GreeterClientPlatform/HelloWorldEJB/release/modules/ext/HelloWorldEJB.jar:<path to yourglassfish-3.1.1>/glassfish/lib/gf-client.jar
Then it should work again...
Carla Brian replied on Fri, 2012/03/30 - 5:55pm