Workshop for WebLogic 10.3 JEE 5 Trial and Error

Now that Workshop 10.3 is available, I test drove the new JEE 5 support with a very basic EJB 3 scenario.  Namely, create a remote stateless session bean and invoke it from a stand-alone java client.  I stumbled around at first since my first guesses for using the new Workshop JEE5 feature support worked were incorrect.  So I've decided to write up my experience in case it will help someone else.  It turns out that JEE 5 really does simplify things, and overall I think it is a big improvement.

Background

A few weeks ago WebLogic Server 10.3 (also known as WebLogic Server 10g Release 3) was released and Workshop for WebLogic 10.3 was also bundled with the full server installer.  You can download it separately on the Developer Tools section on the OTN download site.  Pieter Humphrey's entry on the tools blog that details lots of new features or Andrei Cioroianu's OTN article for a more thorough walk-through show-casing more features.  In previous releases of Workshop, the wizards/tooling only supported EJB 2.1 development with WebLogic's EJBGen (or EJBDoclet based on XDoclet) even though WebLogic Server 10.0 and newer support JEE 5 and EJB 3.

Old School EJB 2.x

For review and comparison, consider the way I was familiar with in Workshop 9.2 through 10.2 to  create a simple stateless session bean and client.  Click the image to enlarge the screen captures.

  1. Create a new EAR project (EAR facet version 1.4 and WebLogic EAR extensions facet versioned to the release of the app server you are deploying to).  j2ee1.4ear
  2. Create a new EJB project (with EJB Module facet version 2.1 and WebLogic EJBGen Support facet version for your WLS release).  On the next page in the wizard, do not select the client project option (in fact I do not think it will even let you).    ejbModule
  3. Go to the EJB project properties->WebLogic EJB->Jar settings - EJB client jar and indicate the location the client jar should be placed as an output of a build (try to use an absolute path here or it will place the jar relative to the current working directory). ejb21ClientJar
  4. Create a session bean - typically right-click on the "ejbModule" source folder and select New->WebLogic Session Bean.  This will open a wizard, which results in a stubbed out session bean.  The bean has annotations for the weblogic.ejbgen package.  newSessionBean
  5. During a project build (triggered by a deploy or an export), weblogic.EJBGen is invoked, which builds out all of the EJB plumbing for you (local, remote, home interfaces, classes, deployment descriptors, the ejb client jar, etc.).
  6. Develop a client class with a main method to invoke the session bean.

For an example of how to develop the the EJB 2.x client class, you can go look at the examples that ship with WLS.  <SERVER_HOME>\wlserver_10.3\samples\server\examples\src\examples\ejb\ejb20\basic\statelessSession\Client.java.  Essentially, it involves getting a JNDI context, finding the ejb home, creating an instance and narrowing that object....phew I'm tired just thinking about all of that.  However, this model is fairly well known to enterprise java developers now.

New School EJB 3

I assumed the steps would be similar for JEE 5 and EJB 3, but I was a little off.  I'll highlight the areas where it is different or non-intuitive in red.

  1. Create a new EAR project (EAR facet version 5.0 and WebLogic EAR extensions facet versioned to the release of the app server you are deploying to)
  2. Create a new EJB project (EJB Module facet version 3.0 and NO WebLogic EJBGen Support facet).  Since we are planning to use the client without EJBGen, this time select the client jar option on the next screen in the wizard.  This will result in another project being created just for the client interfaces and client code.ejb3 [2]   clientJar
  3. You do not create a session bean using the menu New-> and navigating to WebLogic Session Bean, rather you simply create a basic interface for your EJB in the EJB Client project.  You could place it somewhere else, such as the EJB Project, but since the EJB Client project is already on the classpath for the EJB project, putting the interface in the EJB Client is a nice way of packaging that interface so it can be easily referenced in other projects .  Not using the menu or a wizard to create the session bean surprised me, but since JEE 5 and EJB 3 is so simple, it makes sense that you would not need a wizard.
  4. Create a class implementing that interface and annotate the class with @Stateless and @Remote.  You could also annotate the interface with @Remote instead of the class.  It's up to you.  I prefer keeping all the EJB annotations in one file and keeping the interface clean.  I find it easy to just use code-completion Ctrl-Space on the annotation which adds the import statement.  In the @Stateless annotation, specify the mappedName attribute so you will know the JNDI name.  The formula for the JNDI name is documented here.  Basically it is mappedName#FullyQualifiedInterfaceName.  So in my example the JNDI name would be  HelloWorld#test.HelloWorld.  EJB3Classes
  5. Create the class with the main method that will invoke the session bean.  There is no sample of this for EJB 3 in the examples, probably because it is so easy.  I put this in it's own Java Project, but you could put it in the client project as well depending on your packaging structure.  The code to do the invocation is so simple, no more home interfaces and narrowing, simply cast the returned object from the lookup to the interface and perform the invocation.
  6. ic = getInitialContext();
    HelloWorld helloWorld = (HelloWorld) ic.lookup(HELLO_WORLD_JNDI_NAME);
    log(helloWorld.hello("James"));



To actually run the Main method class in Workshop, I right click on the class in the Project Explorer and select Run As->Open Run Dialog.  In the classpath tab, be sure to add the wlclient.jar file located here <SERVER_HOME>\wlserver_10.3\server\lib to the User Entries section and remove the WebLogic System Libraries from the Bootstrap Entries section.  If you forget to remove the WebLogic System Libraries, you will get a stack like this: Exception in thread "Main Thread" java.lang.NoClassDefFoundError: weblogic/kernel/KernelStatus

If you put both the Main method and interface in the same jar file, you can invoke it with only 2 jars on the classpath, JEE doesn't get much simpler than this:


D:\TEMP\jeeclient>java -cp d:\wls103\wlserver_10.3\server\lib\wlclient.jar;HelloJava.jar test.TestClient
Hello James


Conclusion

There may be better ways to go about this, and I'd love to hear about it if you've found a better approach or have comments on the approach I've described above.  My Workshop 10.3 projects are available here with all my code.  Simply File->Import->General->Existing Projects into Workspace->From Archive and give it a shot and enjoy much improved support for JEE 5 and EJB 3 in Workshop. 

Comments:

Hi James, thanks for the nice kickstart!

Posted by John on December 30, 2008 at 04:10 PM PST #

I used the same formula as you have stated for getting the JNDI name but i am getting the below error. Exception in thread "Main Thread" javax.naming.NameNotFoundException: Exception in lookup.: `Calculator#com/test/Calculator' could not be found. [Root exception is weblogic.corba.cos.naming.NamingContextAnyPackage.NotFound: IDL:weblogic/corba/cos/naming/NamingContextAny/NotFound:1.0] at weblogic.corba.j2ee.naming.Utils.wrapNamingException(Utils.java:65) at weblogic.corba.j2ee.naming.ContextImpl.lookup(ContextImpl.java:230) at weblogic.corba.j2ee.naming.ContextImpl.lookup(ContextImpl.java:168) at javax.naming.InitialContext.lookup(InitialContext.java:392) at com.test.Client.main(Client.java:22) Caused by: weblogic.corba.cos.naming.NamingContextAnyPackage.NotFound: IDL:weblogic/corba/cos/naming/NamingContextAny/NotFound:1.0 at weblogic.corba.cos.naming.NamingContextAnyPackage.NotFoundHelper.read(NotFoundHelper.java:72) at weblogic.corba.cos.naming._NamingContextAnyStub.resolve_any(_NamingContextAnyStub.java:87) at weblogic.corba.j2ee.naming.ContextImpl.lookup(ContextImpl.java:208) ... 3 more My Client code is public class Client { private static String INITIAL_CONTEXT_NAME = "weblogic.jndi.WLInitialContextFactory"; private static String PROVIDER_URL = "t3://localhost:7001"; private static String JNDI_NAME = "Calculator#com/test.Calculator"; //private static String QUEUE_NAME = "app.queue.name"; //private static String CONNECTION_FACTORY = "app.connectionfactory.name"; public static void main(String[] args) throws Exception { Context ctx = getInitialContext(); Calculator calculator = (Calculator) ctx.lookup(JNDI_NAME); System.out.println("Addition 1 + 1 = " + calculator.add(1, 1)); System.out.println("Subration 1 - 1 = " + calculator.subtract(1, 1)); } private static Context getInitialContext() throws NamingException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_NAME); env.put(Context.PROVIDER_URL, PROVIDER_URL); return new InitialContext(env); } } Can you help me in resolving the error

Posted by Kunal Sharma on January 26, 2009 at 08:16 PM PST #

Kunal, Unfortunately I won't be able to help you. The first thing I recommend is to check the Server's JNDI tree in the WLS Console. If that doesn't yield any ideas, then I recommend that you open a support case and post in the WLS - EJB forum. http://forums.oracle.com/forums/forum.jspa?forumID=580 James

Posted by James Bayer on January 26, 2009 at 11:52 PM PST #

Hi Kunal, 1. check ur JNDI Tree in weblogic console. Check your EJB bound to the weblogic tree. (Environment>servers>YOURSERVER>view JNDI Tree 2. Hope ur your bean JNDI name is @Stateless(mappedName="Calculator") 3. in client Calculator calculator = (Calculator) ctx.lookup("Calculator#com.test.Calculator"); 4.Hope ur Calculator Interface in com.test package

Posted by Vijay on February 06, 2009 at 10:30 AM PST #

I kept both Main method and Interface in a same EJB project. Then I added wlclient.jar file in class path and removed weblogic system libraries from the class path. I am calling that ejb interface from my WEB project But I got the below error. The project was not built since its build path is incomplete. Cannot find the class file for javax.servlet.http.HttpServletRequest. So to fix this error I added javax.servlet_1.0.0.0_2-5.jar file into class path, and this error got fixed. But now i am getting below new error in one of my java file. Cannot find the class file for weblogic.logging.NonCatalogLogger. could you help me out to resolve this. Should I again add another jar for this? Kumarasamy

Posted by Kumarasamy on February 12, 2009 at 03:00 PM PST #

Kumarasamy, I don’t recommend keeping the main method class in the same EJB project. When you run the main method you need an altered classpath from the project’s normal one (because it has weblogic system libraries needed for building EJB’s, etc). I’d put it in it’s own java project and setting the wlclient jar on that project path without the weblogic system classpath. I also recommend posting in the forums as I am leaving for a few days and won’t be able to respond to email. There is one for WLS: http://forums.oracle.com/forums/forum.jspa?forumID=570 One for Workshop: http://forums.oracle.com/forums/forum.jspa?forumID=575 One for WLS EJB: http://forums.oracle.com/forums/forum.jspa?forumID=580

Posted by James Bayer on February 12, 2009 at 07:18 PM PST #

Hi there, the same issue has bugging me for more than 3 days, and I am glad to have visit this page and got some insights. Still, i have no clue on how it works... when I follow the article to create a test, and I do exactly what James say, it seems not working as follow:
D:\bea\workspace\ejbJAVAClient\bin>java -cp wlclient.jar;ejbTestClient.jar;ejbJavaClient.jar test.testClient
created ic
Feb 25, 2009 6:50:29 PM com.sun.corba.se.impl.encoding.CDRInputStream_1_0 read_value WARNING: "IOP00810257: (MARSHAL) Could not find class" org.omg.CORBA.MARSHAL: vmcid: SUN minor code: 257 completed: Maybe at com.sun.corba.se.impl.logging.ORBUtilSystemException.couldNotFindClass(ORBUtilSystemException.java:7784) at com.sun.corba.se.impl.encoding.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1013) at com.sun.corba.se.impl.encoding.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:879) at com.sun.corba.se.impl.encoding.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:873) at com.sun.corba.se.impl.encoding.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:863)
however, when I type this...
D:\bea\workspace\ejbJAVAClient\bin>java -cp weblogic.jar;ejbTestClient.jar;ejbJavaClient.jar test.testClient
created ic
Hello Test!

the difference for the same class library is the weblogic.jar vs wlclient.jar... Then it comes to my another concern, which is about the security... I added following line in the getInitialContext() func: h.put(Context.SECURITY_PRINCIPAL, "weblogic"); h.put(Context.SECURITY_CREDENTIALS, "weblogic");
D:\bea\workspace>java -cp weblogic.jar;ejbTestClient.jar;ejbJavaClient.jar test.testClient
Exception in thread "main" java.lang.NoClassDefFoundError: weblogic/security/subject/AbstractSubject at weblogic.jndi.WLInitialContextFactory.getInitialContext(WLInitialContextFactory.java:117) at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667) at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288) at javax.naming.InitialContext.init(InitialContext.java:223) at javax.naming.InitialContext.(InitialContext.java:197) at test.testClient.getInitialContext(testClient.java:77) at test.testClient.doTest(testClient.java:40) at test.testClient.main(testClient.java:32)
now, it said, missing the "weblogic/security/subject/AbstractSubject".... this would come to an endless story, as i can find that all the missing classes are packaged in more than 20 different jar files in server/lib/ or modules/ folder... However, all the missing classes are all inside the wlclient.jar. I do think that wlclient.jar is the right one for connecting EJB3, however, things just not working properly... strange...

Posted by Russell on February 24, 2009 at 05:38 PM PST #

Russell, I'm not sure why the wlclient.jar isn't working for you in the simple scenario. In any case, you may want to try with the "full client" also known as wlfullclient.jar, which has to built and the procedure and description is here: http://edocs.bea.com/wls/docs103/client/jarbuilder.html If you still have issues, I would recommend posting to the WLS EJB forum: http://forums.oracle.com/forums/forum.jspa?forumID=580 Thanks, James

Posted by James Bayer on February 24, 2009 at 10:25 PM PST #

Hello James, After using the wlfullclient.jar, it works! thanks for your advice. For the wlfullclient.jar probably integrating all the class that weblogic.jar and also wlclient.jar with all the dependency to a single jar file, it's big, around 55Mb big. Again, thanks! you solved my headache :-) Cheers, Russell

Posted by Russell on February 25, 2009 at 08:42 AM PST #

UGH- just this much: remove the WebLogic System Libraries from the Bootstrap Entries section. If you forget to remove the WebLogic System Libraries, you will get a stack like this: Exception in thread "Main Thread" java.lang.NoClassDefFoundError: weblogic/kernel/KernelStatus has caused so much frustration in our environment. I'm glade to see such a simple solution to the KernelStatus error when using Workshop. Thanks for posting! Bill

Posted by Bill Meyer on June 30, 2009 at 10:42 AM PDT #

thanks for your charm advice on remove WebLogic System Libraries. But I still have this error with my junit testcase. junit.framework.AssertionFailedError: Exception in constructor: testGetCategoryNames (java.lang.NoClassDefFoundError: weblogic/logging/WLLevel at weblogic.logging.commons.LogFactoryImpl.getInstance(LogFactoryImpl.java:21) at weblogic.logging.commons.LogFactoryImpl.getInstance(LogFactoryImpl.java:18) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351) at shared.controls.test.CategoryControlTestCase.(CategoryControlTestCase.java:19) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at junit.framework.TestSuite.createTest(TestSuite.java:55) at junit.framework.TestSuite.addTestMethod(TestSuite.java:280) at junit.framework.TestSuite.(TestSuite.java:140) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader.getTest(JUnit3TestLoader.java:102) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader.loadTests(JUnit3TestLoader.java:59) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:448) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:674) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:387) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) ) at junit.framework.Assert.fail(Assert.java:47) at junit.framework.TestSuite$1.runTest(TestSuite.java:90) at junit.framework.TestCase.runBare(TestCase.java:130) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:120) at junit.framework.TestSuite.runTest(TestSuite.java:230) at junit.framework.TestSuite.run(TestSuite.java:225) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

Posted by Thang Hoang on July 10, 2009 at 02:05 AM PDT #

Thang, when I use a tool like jarscan, I get the following result for that class. java -jar jarscan.jar -dir C:\Oracle\wls11gr1\wlserver_10.3\server\lib -class weblogic.logging.WLLevel =============================================== Found: weblogic.logging.WLLevel Class: weblogic.logging.WLLevel Package: weblogic.logging Library Name: weblogic.jar Library Path: C:\Oracle\wls11gr1\wlserver_10.3\server\lib\weblogic.jar =============================================== =============================================== Found: weblogic.logging.WLLevel Class: weblogic.logging.WLLevel Package: weblogic.logging Library Name: wls-api.jar Library Path: C:\Oracle\wls11gr1\wlserver_10.3\server\lib\wls-api.jar =============================================== Search took: 8907 milliseconds.

Posted by James Bayer on July 14, 2009 at 11:51 PM PDT #

I'm getting a "Bad version number in .class file" using a 1.5 client even if I use wlfullclient5.jar.

Posted by CinKo on September 08, 2009 at 06:15 AM PDT #

I'm not sure about that one, I suggest posting in the OTN forums, there is a special forum just for WLS EJB. Alternatively you could open a support case. Good luck, James

Posted by james.bayer on September 08, 2009 at 12:31 PM PDT #

With EJB3 you must use @Stateless/@Stateful in conjunction with the mappedName parameter. If you need additional parameters (eg. name), be sure to declare the mappedName first. Then append the other parameters. For a simple EJB call it works with the minimalistic wlclient.jar and iiop-protcol as well as t3.

Posted by Thomas Jarnot on November 05, 2009 at 07:36 PM PST #

Thanks for this posting. I happened upon here because of a problem with an internal application we were building. I was banging my head against a wall with a
Exception in thread "Main Thread" java.lang.NoClassDefFoundError: weblogic/kernel/KernelStatus
and couldn't figure out why. This post saved me a lot of time.

Posted by Keith on November 03, 2010 at 07:23 PM PDT #

HI James, Thanks for your input. wlfullclient.jar helped to resolve similar problem which i had been facing for last two days. Thanks again.

Posted by Chandran on December 04, 2010 at 01:35 AM PST #

Thanks for the great post. It helped me fix the classpath issues and test the MDB.

Posted by weblogic11g user on January 31, 2011 at 12:04 AM PST #

Post a Comment:
Comments are closed for this entry.
About

James Bayer Image
I was formerly a Product Manager on the WebLogic Server team based out of Oracle HQ. You can find my new blog at http://iamjambay.com.
Follow Me on Twitter
Oracle WebLogic

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today