TOTD #82: Getting Started with Servlet 3.0 and EJB 3.1 in Java EE 6 using NetBeans 6.7


EJB 3.1 (JSR 318) and Servlet 3.0 (JSR 315) are the two new JSRs in Java EE 6 (JSR 316).

The EJB 3.1 specification provides multiple new features such as WAR packaging, Optional Local Business Interfaces, EJB.lite, Portable Global JNDI Names, Singleton Session Beans (Container-managed and Bean-managed concurrency), Application Initialization and Shutdown events, Timer Service enhancements, Simple/Light-weight Asynchrony, and many other features defined in the specification.

The Servlet 3.0 specification is an update to Servlet 2.5 and focuses on ease-of-use. It also adds several new features such as "web.xml" free deployment (mostly), Dynamic Registration of servlets/filters, Pluggability of frameworks using "web-fragment.xml", Asynchronous API, Security enhancements (Constraints via annotations, programmatic container authentication and logout), and several other miscellaneous additions like default error page, file upload, etc.

GlassFish v3 provides the most complete implementation of EJB 3.1 and Servlet 3.0 along with other Java EE 6 specifications. This Tip Of The Day (TOTD) will show how to create a simple EJB and invoke it from a Servlet, all in a deployment-descriptor free way.
  1. Enable support for v3 Preview in NetBeans
    1. Using NetBeans 6.7 latest nightly, enable support for recent GlassFish v3 builds either using the command-line switch or the marker module.
    2. Download and unzip GlassFish v3 Preview 47b. The latest promoted builds are always available here.
    3. In the "Services" tab, right-click on "Servers" and click on "Add Server". Select "GlassFish v3" as shown below:



      and click on "Next".
    4. Specify location of the previously unzipped bundle, click on "Next >", and press "Finish".
  2. Create a new Web project by right-click in the "Projects" pane, select "New Project", choose "Java Web" and "Web  Application" as categories and projects.
  3. Click on "Next >", choose "Java EE 5" as the Java EE version and click on "Finish". A future version of NetBeans will will provide direct support for Java EE 6.
  4. Add a POJO-based EJB
    1. Right-click on "Source Packages" and select "New", "Java Class..." as shown below:



      Give the class name as "HelloEJB" and package as "server" as shown below:



      and click on "Finish".
    2. Add "@Stateless" class-level annotation and press Shift+Command+I (default shortcut) to fix the imports. This annotation comes from the "javax.ejb" package.
    3. Add the following method:

          public String sayHello(String name) {
              return "Hello " + name;
          }

      to the class. And can you believe it, that's your complete EJB ready to be deployed and that too in a WAR file - the beauty of Java EE 6. The complete class looks like:


      package server;

      import javax.ejb.Stateless;

      /\*\*
       \* @author arungupta
       \*/
      @Stateless
      public class HelloEJB {
          public String sayHello(String name) {
              return "Hello " + name;
          }
      }
  5. Add a Servlet to invoke this EJB
    1. Add a new class "HelloServlet" in the "server" package as explained above.
    2. Add "@WebServlet" class-level annotation and Shift+Command+I to fix the imports. This annotation comes from the "javax.servlet.annotation" package. And specify a URL pattern as:

      @WebServlet(urlPatterns="/hello")
    3. According to the Servlet3 specification, the contract is inherited from the "javax.servlet.http.HttpServlet" interface. So add:

      extends HttpServlet

      to the class.
    4. Inject a local EJB reference using the code:

      @EJB HelloEJB ejbClient;
    5. Override the GET method as:

          @Override
          public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
              res.setContentType("text/html");
              res.getOutputStream().print("<h1>Hosted at: " + req.getContextPath() + "</h1>");
              res.getOutputStream().print("<h2>" + ejbClient.sayHello("Duke") + "</h2>");
          }

      and again Shift+Command+I to fix the imports. The complete class looks like:

      package server;

      import java.io.IOException;
      import javax.ejb.EJB;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      /\*\*
       \* @author arungupta
       \*/
      @WebServlet(urlPatterns="/hello")
      public class HelloServlet extends HttpServlet {
          @EJB HelloEJB ejbClient;

          @Override
          public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
              res.setContentType("text/html");
              res.getOutputStream().print("<h1>Hosted at: " + req.getContextPath() + "</h1>");
              res.getOutputStream().print("<h2>" + ejbClient.sayHello("Duke") + "</h2>");
          }
      }
That completes the project creation. Now lets make our application deployment descriptor free by expanding "WEB-INF" directory and deleting "sun-web.xml" and "web.xml". Java EE 6 makes the deployment descriptors optional by introducing equivalent annotations.

Lets run the project by right-click on the project and select "Run". The web application is deployed to GlassFish v3 Preview 47b and "http://localhost:8080/WebApplication1" shows the default "index.jsp" created by the IDE.

Our servlet is accessible at "http://localhost:8080/WebApplication1/hello" and shows the output as:



The directory of the generated WAR file looks like:



As evident "WEB-INF/classes" has only two POJO classes and yet this is a Java EE 6 application.

So we created a trivial Java EE 6 application using Servlet 3 and EJB 3.1 APIs and deployed successfully on GlassFish v3 Preview 47b using NetBeans 6.7.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish v3 javaee6 servlet3 ejb3.1 netbeans
Comments:

Just wonder, is it considered good or bad practice for a Servlet to have direct contact to a EJB Session bean?

I was creating an App with JSP>Servlet>Bean the bean then connected to the EjbSessionBean which connected to the Persistant class (Entity).

Then got to thinking, why have I got this standard Bean at all? Would it be OK to connect directly to the EjbSessionBean?

Or as I say, is this 'bad practice'?

Posted by keith on July 07, 2009 at 01:21 AM PDT #

This doesn't work, I just get the following error:

[#|2009-08-11T01:16:41.659+0100|SEVERE|glassfish|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=14;_ThreadName=Thread-1;|StandardWrapperValve[com.myproject.servlets.TestServlet]: PWC1406: Servlet.service() for servlet com.myproject.servlets.TestServlet threw exception
javax.ejb.AccessLocalException: Client not authorized for this invocation.
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1680)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:185)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:82)
at $Proxy93.sayHello(Unknown Source)
at com.myproject.servlets.__EJB31_Generated__TestService__Intf____Bean__.sayHello(Unknown Source)
at com.myproject.servlets.TestServlet.doPost(TestServlet.java:24)
at com.myproject.servlets.TestServlet.doGet(TestServlet.java:19)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1461)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:293)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:187)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:647)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:351)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:249)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:146)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:746)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:655)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:905)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:161)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:136)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:103)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:89)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
|#]

Posted by guest on August 10, 2009 at 10:24 AM PDT #

Which GlassFish build did you try ?

Posted by Arun Gupta on August 10, 2009 at 02:41 PM PDT #

Glassfish v3.0 Preview (build 47.4)

Posted by Keith on August 10, 2009 at 07:42 PM PDT #

madness, complete madness!

Cleared out all my deployed apps, restarted the PC, rebuilt the EAR and redeployed and now it works...
Was up 'til 2am last night with this, now after 30 mins it just decides it feels like working!

:-D

I do find this v3 GlassFish very flakey, I knows it's a preview version, but there are a lot of issues with the 'undeploy', 'redeploy' and sometimes just deploying funtionality (got a NullPointer the first time I tried to deploy the EAR, second time it was fine)

Posted by Keith on August 10, 2009 at 08:18 PM PDT #

Keith,

Sorry for the frustration. Can you please file a bug if you are able to reproduce the issue ?

With GlassFish v3, you can just remove the "glassfishv3" directory and it's as if it was never installed.

Posted by Arun Gupta on August 10, 2009 at 10:39 PM PDT #

Glassfish v3 is only a preview version so I can cope with the flakey bits,
The issue I had has returned, it's an issue with my persistent layer and the DB by the looks of it.
I had this working running on a previous version of Glassfish but for v3 it's a no goer.

I have my persistence.xml using Toplink for now with a datasource called JDBC/Test.

I have the connpool and JDBC conn created in Glassfish and a test of the 'ping' function works.

I have the mysql-connector-java-5.0.5-bin.jar in the //glassfish/domains/domain1/lib/ext

but as soon as I get to method to execute the persistent layer I get this error.

Posted by Keith on August 11, 2009 at 09:27 PM PDT #

Keith,

GlassFish v3 comes bundled with EclipseLink and your application is using TopLink. Could that be a problem ? It may be a fake error message.

I'll try something similar on the lines you mentioned above and describe in a blog.

Posted by Arun Gupta on August 11, 2009 at 11:16 PM PDT #

Keith,

Scheduled a blog for tomorrow morning showing how to create a simple JPA/EclipseLink application using NetBeans 6.8 M1 and deploy on GlassFish build 58. Let me know if that'll be helpful.

Posted by Arun Gupta on August 12, 2009 at 04:12 AM PDT #

Good news!

Dropped build build 47.4 and replaced it with GlassFish v3.0-b58 (build 58) and it worked!

Same app, same config as I've mentioned above works under this build.

Posted by Keith on August 12, 2009 at 04:16 AM PDT #

Congratulations!

I was pretty amazed that my simple app worked without any issue as well :)

Posted by Arun Gupta on August 12, 2009 at 04:31 AM PDT #

[Trackback] NetBeans 6.8 M1 introduces support for creating Java EE 6 applications ... cool! This Tip Of The Day (TOTD) shows how to create a simple web application using JPA 2.0 and Servlet 3.0 and deploy on GlassFish v3 latest...

Posted by Arun Gupta's Blog on August 12, 2009 at 10:43 PM PDT #

Hi Arun,
Thatnks for your help on all this, however I have another question.
I recently had to replace my HD as the last died, I have reinstalled GF b_58 and have an old copy of my previous EAR file, but now when I deploy I get the folowing error:

# Cannot load com.sun.enterprise.webservice.apt.WebServiceRefAp$ServiceRefVisitor reason : com.sun.enterprise.webservice.apt.WebServiceRefAp$ServiceRefVisitor
# java.lang.ClassNotFoundException: com.sun.enterprise.webservice.apt.WebServiceRefAp$ServiceRefVisitor

What could be causing this, do you know?

Thanks

Posted by Keith on September 02, 2009 at 12:38 AM PDT #

Scrap that last question, using the b58 exe rather than b58 zip and have now got it working.

Posted by Keith on September 02, 2009 at 08:36 AM PDT #

Cool!

Posted by Arun Gupta on September 02, 2009 at 08:40 AM PDT #

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

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

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