Miles to go …

May 19, 2009

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

Filed under: general, netbeans, totd — arungupta @ 10:57 am

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; r>
      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

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #94: A simple Java Server Faces 2.0 + JPA 2.0 application – Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3
  2. TOTD #93: Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3 – A simple Servlet 3.0 + JPA 2.0 app
  3. TOTD #95: EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application – Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3
  4. TOTD #99: Creating a Java EE 6 application using MySQL, JPA 2.0 and Servlet 3.0 with GlassFish Tools Bundle for Eclipse
  5. TOTD #102: Java EE 6 (Servlet 3.0 and EJB 3.1) wizards in Eclipse

12 Comments »

  1. 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’?

    Comment by keith — July 7, 2009 @ 8:21 am

  2. 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)
    |#]

    Comment by Anonymous — August 10, 2009 @ 5:24 pm

  3. Which GlassFish build did you try ?

    Comment by Arun Gupta — August 10, 2009 @ 9:41 pm

  4. Glassfish v3.0 Preview (build 47.4)

    Comment by Keith — August 11, 2009 @ 2:42 am

  5. 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)

    Comment by Keith — August 11, 2009 @ 3:18 am

  6. 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.

    Comment by Arun Gupta — August 11, 2009 @ 5:39 am

  7. 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.

    Comment by Keith — August 12, 2009 @ 4:27 am

  8. 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.

    Comment by Arun Gupta — August 12, 2009 @ 6:16 am

  9. 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.

    Comment by Arun Gupta — August 12, 2009 @ 11:12 am

  10. 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.

    Comment by Keith — August 12, 2009 @ 11:16 am

  11. Congratulations!

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

    Comment by Arun Gupta — August 12, 2009 @ 11:31 am

  12. [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…

    Comment by Arun Gupta's Blog — August 13, 2009 @ 5:43 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress