With Glassfish V3 (or better with Java EE6 and EJB 3.1) it becomes way easier to test EJB’s, which is now possible to do with the embedded Glassfish. Lets have a quick and very basic walk-through and highlights some of the current issues and pitfalls.
Pre-Requirements:
- Netbeans 6.8
- Glassfish V3
- optional: a Hudson installation (at a remote server) with a local Glassfish V3 installation
Tutorial:
- Create a new Web Application WebTestEmb
Standard EE6 project with a local or remote GF, no frameworks
Activate local lib-folder and use dedicated lib folder for server libraries !Netbeans created the most simple possible web application for us, Hello World coming as a JSP file. Time to add something useful.
- Create a Session Bean MyBean in package bean
package bean; import javax.ejb.Stateless; @Stateless public class MyBean { // Add business logic below. (Right-click in editor and choose // "Insert Code > Add Business Method") }
- Add Business Method addNumbers
Right-click into the code | Insert Codepackage bean; import javax.ejb.Stateless; @Stateless public class MyBean { public int addNumbers(int numberA, int numberB) { return numberA + numberB; } }
- Create a Servlet AddServlet in package web
- Modify servlet to use sessionbean
Call Entprise Bean (Right-click inthe code | Call Enterprise Bean)Find the processRequest method and de-comment the out.println block
.. @WebServlet(name="AddServlet", urlPatterns={"/AddServlet"}) public class AddServlet extends HttpServlet { @EJB private MyBean myBean; .. protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet AddServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Servlet AddServlet at " + request.getContextPath () + "</h1>"); out.println(myBean.addNumbers(1, 2)); out.println("</body>"); out.println("</html>"); } finally { out.close(); } } ..
- Deploy and Run the Project
http://{your glassfish server}:8080/WebTestEmb/AddServletGreat ! Our web application just learned to count to 3 ! Lets make some sense and test the sessionbean in Netbeans.
- Add JUnit 4.0 Test Class
Right-click on MyBean.Java | Tools | Create JUnit Test (just leave all the defaults) - Modify the test method skeleton
You will notice we are using the embedded Glassfish per default... @Test public void testAddNumbers() throws Exception { System.out.println("addNumbers"); int numberA = 1; int numberB = 2; MyBean instance = (MyBean)javax.ejb.embeddable.EJBContainer.createEJBContainer().getContext().lookup("java:global/classes/MyBean"); int expResult = 3; int result = instance.addNumbers(numberA, numberB); assertEquals(expResult, result); } ..
- Execute the test
Right-click on the project | TestYou can verify by changing the expResult to 4 and execute the test again.
- Build and Test by Hudson
For those who dont know: Hudson is a continuous integration server that works well with Netbeans projects. More info and downloads at hudson-ci.org.
I skip the part of installing (or deploying) Hudson and performing the basic configuration. (You can refer to one of my earlier tutorials, link)
For a proper CI setup Hudson should retrieve the source code from a repository. You should import this project into your own svn repo because you need to tinker with the project settings later.
If you want to download myt at https://coffeeshop.svn.sourceforge.net/svnroot/coffeeshop/WebTestEmb
Setup a new freestyle software project, enter the svn path and add a ANT build stepAfter creating the new project and attempting to build it the first time, it will fail, due to some classpath error
.. BUILD FAILED /root/.hudson/jobs/WebTestEmb/workspace/WebTestEmb/nbproject/build-impl.xml:226: The Java EE server classpath is not correctly set up. Your active server type is gfv3ee6. Either open the project in the IDE and assign the server or setup the server classpath manually. For example like this: ant -Duser.properties.file=<path_to_property_file> (where you put the property "j2ee.platform.classpath" in a .properties file) or ant -Dj2ee.platform.classpath=<server_classpath> (where no properties file is used) Total time: 1 second Finished: FAILURE ..
- Fix the classpath and build again
Ant has an issue finding the embedded Glassfish library. Our local Netbeans will use the path to the library which might be different to the library path on the build server.
We need to play with the project properties (and its private sibling). Note: I dont like doing that because manual settings in the project.properties vaporate once you use again the project settings wizard again ! (I guess there will a better solution in future, today we just make it work!)
When you dig in the file-view of your project you find a project.properties file (which is commited to svn) and a private/project.properties (which is excluded from svn).
The private version show something similar to this (depending on your local Glassfish installation!).. j2ee.platform.embeddableejb.classpath=/home/sven/sges-v3/glassfish/lib/embedded/glassfish-embedded-static-shell.jar ..
You need to make 2 changes to your svn version
1. Add the above settings with the path to the library at the build-server
2. Add the j2ee.classpath.. j2ee.platform.classpath= j2ee.platform.embeddableejb.classpath=/home/user/glassfishv3rel/glassfish/lib/embedded/glassfish-embedded-static-shell.jar ..
After applying these changes and commiting them, try to build again with Hudson. Success, right ?
.. BUILD SUCCESSFUL Total time: 5 seconds Finished: SUCCESS ..
But certainly you notice, our tests went missing ! One more thing to fix !
- Add the test target
In Netbeans we can test because the IDE execute directly the test target. Hudson triggers ANT to build, but there is no dependency to the test target(s). Not quite sure if this is really a bug (by the IDE creating the build.xml file) or not.
Modify the build.xml (not the build-impl.xml!).. <project name="WebTestEmb" default="default" basedir="."> <description>Builds, tests, and runs the project WebTestEmb.</description> <import file="nbproject/build-impl.xml"/> <target depends="test,dist,javadoc" description="Build whole project." name="default"/> <!-- ..
Another round of committing and building should be more successful. You can see the embedded Glassfish is actually used !
But you will note the test is successful despite JUnit throwing severe errors.
.. -do-test-run: [junit] WARNING: multiple versions of ant detected in path for junit [junit]Â Â Â Â Â Â Â Â Â jar:file:/root/.hudson/tools/ANT/lib/ant.jar!/org/apache/tools/ant/Project.class [junit]Â Â Â Â Â and jar:file:/home/user/glassfishv3rel/glassfish/modules/ant.jar!/org/apache/tools/ant/Project.class [junit] Testsuite: bean.MyBeanTest [junit] addNumbers [junit] Feb 22, 2010 10:33:09 AM org.glassfish.ejb.embedded.EJBContainerProviderImpl getValidFile [junit] SEVERE: ejb.embedded.location_not_exists [junit] Feb 22, 2010 10:33:14 AM org.glassfish.flashlight.impl.provider.FlashlightProbeProviderFactory processXMLProbeProviders [junit] SEVERE: MNTG0301:Cannot process XML ProbeProvider, xml = META-INF/mojarra-jsf-api-probe-provider.xml [junit] java.lang.IllegalStateException: Provider already mapped glassfish:jsf:faces-servlet ..
This is a known issues, please check the ticket https://glassfish.dev.java.net/issues/show_bug.cgi?id=10954
Pingback: Quick Tutorial: Netbeans + Selenium + Hudson « The JavaDude Weblog
This has really helped me a lot. Kudos to you
Hi!
I used the tutorial to put together a stateless session bean and it works as advertised. Do you have more tutorials about using other types of EJBs?
-Nitin
PS: I skipped the test section
Your tutorial is so simple, clear and descriptive.
Thank you very much Sven.
I’m having problems using this in Netbeans 7.0
Just as described here: http://www.java.net/forum/topic/glassfish/glassfish/junit-test-embeddable-glassfish-fails-error-no-ejb-container-provider-available
Reinstalling hasn’t worked for me. what do you think? do you have any idea of how to configure the embeddable-ejb-container manually?