수요일, 8월 5
Shadow

#034 Java EE 6 – EJB 3.1

Lab Exercises

For the sake of the simplicity of the lab, most exercises are provided in the form of “ready-to-open-and-run” NetBeans projects.  (Many of them are borrowed from “glassfish-samples” and “Java EE 6 tutorial“.)  Please feel free to create them from scratch if you want to.

It is strongly encouraged, leveraging what is provided in this lab, you do your own experimentation meaning creating/adding your own code as much as you can.

If you have written some code that might help everyone else, please feel free to share them on this codecamp email alias or directly send them to the instructors.  Your name will be recognized in this lab if your sample code is chosen to be included.  For the tasks that need to be done, please see the “Things to be done” section above.)

 

  • Exercise 1: EJB in a war packaging (step by step) (20 minutes)
  • Exercise 2: Singleton (20 minutes)
  • Exercise 3: Timer (20 minutes)
  • Exercise 4: Asynchronous method invocation (30 minutes)
  • Exercise 5: EJB embedded (30 minutes)
  • Exercise 6: EJB with REST (30 minutes)
  • Homework Exercise
      Before you start this lab, you have to get sample applications from “glassfish-samples” and “Java EE tutorial” as described in LAB-4530: Java EE 6 – Examples.

    Exercise 1: EJB in a war packaging (step by step)

    In this exercise, you are going to build a Web application step by step in which a servlet invokes a method of an EJB.  You will see both servlet and EJB beans are included in a single war file.

     

    (1.1) Create a new project

    0. Start NetBeans IDE.
    1. Create a new Web project.


    Figure-1.11

    • For the Project Name field, enter EJB-in-a-war (or whatever project name of your choice).
    • Click Next.

     


    Figure-1.12

    • Click Finish.

     


    Figure-1.13

    (1.2) Create a Session bean

    1. Create a new Session bean.

    • Right click project and New->Other. (If you see Session Bean in the pop-up menu, select it.)

     


    Figure-1.21

     


    Figure-1.21a

    • For the EJB Name field, enter MySessionBean (or whatever name of your choice).
    • For the Package field, enter server (or whatever package name of your choice).
    • Click Finish.

     


    Figure-1.22

    2. Modify IDE generated MySessionBean.java as shown below.  The modification is to add a simple business method called sayHello(..) to the bean.

    package server;

    import javax.ejb.Stateless;

    /**
    *
    * @author sang
    */
    @Stateless
    public class MySessionBean {

    // Add business logic below. (Right-click in editor and choose
    // “Insert Code > Add Business Method”)
    public String sayHello(String name){
    return “Hello ” + name + “!”;
    }

    }

    MySessionBean.java

     


    Figure-1.23

    (1.3) Create a Servlet

    In this step, you are going to create a servlet, which invokes sayHello() method of the MySessionBean you created above.

    1. Create a new Servlet.

     


    Figure-1.31

    • For the Class Name field, enter HelloServlet (or whatever class name of your choice).
    • For the package field, enter client (or whatever package name of your choice).
    • Click Finish.

     


    Figure-1.32

    2. Inject MySessionBean into the servlet.

    • Type @EJB My and observe code completion feature kicks in. (If the code completion does not appear, press CTRL+Space or CTRL+CMD+Backslash on Mac OS X.)
    • Select MySessionBean  (server).
    • Type client;


    Figure-1.33

    • Observe that you have added the line in bold and red-colored font below.
     …
    @WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
    public class HelloServlet extends HttpServlet {

    @EJB MySessionBean client;

    /**
    * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    * @throws ServletException if a servlet-specific error occurs
    * @throws IOException if an I/O error occurs
    */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

     

     

    3. Fix imports.

    • Right click any spot in the editor window and select Fix Imports.

     


    Figure-1.34

    4. Call the EJB.

    • Remove comments on the statements within try{..} block.
    • Modify the code as shown below. The modification is to invoke sayHello() method of the EJB.


    Figure-1.35

     NetBeans Tip: You can leverage code-completion feature of the IDE as shown below.  When you type client. and press CTRL+SPACE ( CTRL+Space or CTRL+CMD+Backslash on Mac OS X.), observe that sayHello(String name) is one of the selections.


    Figure-1.36

    (1.4) Build and run the application

    1. Change Relative URL of the project.  This is so that when you run the application, the Relative URL is automatically attached to the URL.

     


    Figure-1.41

    • Select Run under Categories on the left.
    • For the Relative URL field, enter /HelloServlet.  The value of the Relative URL is appended to the context path when the application is accessed for the first time.
    • Click OK.

     


    Figure-1.42

    2. Build and run the application.


    Figure-1.43

    • Observe that “Calling EJB Hello Sang Shin!” gets displayed.  This verifies that sayHello() method of the EJB is invoked successfully.

     


    Figure-1.44

    (1.5) Check the war file

    In this step, you are going to see that both EJB and Servlet classes are in the same war file.

    1.  Verify that a single war file contains both HelloServlet.class and MySessionBean.class.

    • Select Files tab.  The Files window show the files from local file system point of view.
    • Expand build->web->WEB-INF->classes.
    • Observe that the MySessionBean EJB is part of the war file.

    Figure-1.51

     

    Solution: The solution of this exercise is provided as “ready to build and run” NetBeans project as EJB-in-a-war under <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/solutions directory.

     

     

    Summary

    In this exercise,  you built a Web application in which EJB is used.  You observed that you don’t need to create EJB module jar file and you don’t have to create EAR file.  Instead, the war file contains the EJB.

     

     

    Exercise 2: Singleton

    Singletons are POJOs just like our Session beans, and the container is guaranteed to maintain a single shared instance of this Singleton. These Singletons are thread safe and also transactional. Like all other EJB’s, singletons have all the services such as security, remoting, dependency injection, web services, interceptors and so on.

    In this exercise, you are going to use a singleton-based counter, which is used as an application-wide counter.  You are also going to use @Startup annotation, which provides life-cycle methods.

    1. Singleton based counter: “counter” sample application.
    2. Study the code
    3. Application Startup/Shutdown callbacks through @Startup

    (2.1) Singleton-based counter: “counter” sample application

    1. Open counter NetBeans project (from “Java EE 6 tutorial”).

    • Select File->Open Project (Ctrl+Shift+O, Cmd+Shift+O on a Mac).
    • Observe that the Open Project dialog box appears.
    • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/docs/javaee-tutorial/examples/ejb directory.  (“Java EE 6 tutorial”)
    • Select counter.
    • Click Open Project.
    • Observe that the counter project node appears under Projects tab window.

    2. Build and run counter project.

    • Right-click counter project and select Run.
    • Browser gets displayed.
    • Observe that “This page has been accessed 1 time(s).” message gets displayed.


    Figure-2.11

    • Click Refresh button to access the page again.
    • Observe that the counter has been changed to 2 (from 1).


    Figure-2.12

    3. Access the application from a different user – the 2nd user.  Since the counter is application-wide scope, accessing the page from the second user should increase the counter’s value to 3.


    Figure-2.13

    • Observe that the value of the counter is increased to 3 as expected.


    Figure-2.14

    4. Access the application from the first user.  Now accessing the counter from the first user should increase the counter to 4.


    Figure-2.15

    • Observe that the counter is increased to 4 as expected.


    Figure-2.16

     

    (2.2) Study code

    Note: We have not covered the “template” concept and “Facelets” of JSF 2.0 yet in this codecamp.  Just consider template-client.xhtml and template.xhtml are used to display #{count.hitCount} for now.

    1. template-client.xhtml.  This is a JSF display page using the template called template.xhtml.

    <?xml version=’1.0′ encoding=’UTF-8′ ?>
    <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
    <html xmlns=”http://www.w3.org/1999/xhtml”
    xmlns:ui=”http://java.sun.com/jsf/facelets”
    xmlns:h=”http://java.sun.com/jsf/html”>
    <body>

    This text above will not be displayed.

    <ui:composition template=”/template.xhtml”>

    This text will not be displayed.

    <ui:define name=”title”>
    This page has been accessed #{count.hitCount} time(s).
    </ui:define>

    This text will also not be displayed.

    <ui:define name=”body”>
    Hooray!
    </ui:define>

    This text will not be displayed.

    </ui:composition>

    This text below will also not be displayed.

    </body>
    </html>

    template-client.xhtml.

    2. template.xhtml.  This is the template.

    <?xml version=’1.0′ encoding=’UTF-8′ ?>
    <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
    <html xmlns=”http://www.w3.org/1999/xhtml”
    xmlns:ui=”http://java.sun.com/jsf/facelets”>
    <head>
    <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
    <title>counter – A singleton session bean example.</title>
    <link href=”./css/default.css” rel=”stylesheet” type=”text/css” />
    </head>

    <body>
    <h1>
    <ui:insert name=”title”Default Title</ui:insert>
    </h1>
    <p>
    <ui:insert name=”body”Default Body</ui:insert>
    </p>
    </body>

    </html>

    template.xhtml.

    3. CounterBean.java.  Note that CounterBean is a Singleton bean.

    package counter.ejb;

    import javax.ejb.Singleton;

    /**
    *
    * @author ian
    * CounterBean is a simple singleton session bean that records the number
    * of hits to a web page.
    */
    @Singleton
    public class CounterBean {
    private int hits = 1;

    // Increment and return the number of hits
    public int getHits() {
    return hits++;
    }
    }

    CounterBean.java

    4. Counter.java.

    package counter.web;

    import counter.ejb.CounterBean;
    import javax.ejb.EJB;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;

    /**
    *
    * @author ian
    */
    @ManagedBean
    @SessionScoped
    public class Count {
    @EJB
    private CounterBean counterBean;
    private int hitCount;

    public Count() {
    this.hitCount = 0;
    }

    public int getHitCount() {
    hitCount = counterBean.getHits();

    return hitCount;
    }

    public void setHitCount(int newHits) {
    this.hitCount = newHits;
    }
    }

    Count.java

    (2.3) Application Startup/Shutdown callbacks

    The introduction of singletons also provides a convenient way for EJB applications to receive callbacks during application initialization or shutdown. By default, the container decides when to instantiate the singleton instance. However, you can force the container to instantiate the singleton instance during application initialization by using the @Startup annotation. This allows the bean to define a @PostConstruct method that is guaranteed to be called at startup time. In addition, any @PreDestroy method for a singleton is guaranteed to be called when the application is shutting down, regardless of whether the singleton was instantiated using lazy instantiation or eager instantiation. In lazy instantiation, the singleton isn’t instantiated until it’s method’s are first needed. In eager instantiation, the singleton is instantiated at startup time whether or not it gets used.

    1. Add MyStartupBean.java to the project.

    package counter.ejb;

    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import javax.ejb.Singleton;
    import javax.ejb.Startup;

    @Singleton
    @Startup
    public class MyStartupBean {

    @PostConstruct
    private void startup() {
    System.out.println(“—-startup() method of MyStartupBean is called”);
    }

    @PreDestroy
    private void shutdown() {
    System.out.println(“—-shutdown() method of MyStartupBean is called”);
    }
    }

    MyStartupBean.java


    Figure-2.31

    2. Build and run the application.

    • Right-click counter project and select Run.
    • Browser gets displayed.
    • Observe that “This page has been accessed 1 time(s).” message gets displayed.


    Figure-2.32

    3. Observe the message “—-startup() method of MyStartupBean is called” in the GlassFish v3 Domain system.log.


    Figure-2.33

      Note: if you do the exercise 2 in sequence, you will see several instances of “—-startup() method of MyStartupBean is called”
    and “—-shutdown() method of MyStartupBean is called” because the project is redeployed before it is run or because you close the browser window inbetween.

    4. Undeploy the application.


    Figure-2.34

    5. Observe the message “—-shutdown() method of MyStartupBean is called” in the GlassFish v3 Domain system.log.


    Figure-2.35

    Summary

    In this exercise, you learned how to use @Singleton annotation.  You have also used @Startup annotation, which provides life-cycle methods.

    Exercise 3: Timer

    The Timer feature of EJB 3.1 provides an ability to declaratively create cron-like schedules to trigger EJB methods. All that is needed is to annotate an EJB method with the @Schedule annotation to implement the timer.

    1. Open, build, and run “timersession” sample application (from “Java EE tutorial”)
    2. Study the code
    3. Open, build, and run “automatic-timer” sample application (from “glassfish-samples”)
    4. Study the code

    (3.1) Open, build, and run “timersession” sample application (from “Java EE 6 tutorial”)

    1. Open timersession NetBeans project.

    • Select File->Open Project (Ctrl+Shift+O).
    • Observe that the Open Project dialog box appears.
    • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/docs/javaee-tutorial/examples/ejb directory.
    • Select timersession.
    • Click Open Project.
    • Observe that the timersession project node appears under Projects tab window.

    2. Build and run timersession project.

    • Right-click timersession project and select Run.
    • Browser gets displayed.


    Figure-3.11


    Figure-3.12


    Figure-3.13


    Figure-3.14

    • Observe in the GlassFish log that the Timers are first restored from the Timer Service.
    • Then an automatic timeout occurs which denotes the scheduling start.
    • Then the programmatic timeouts comes from the user’s actions.
    • The remaining automatic timeouts occur as long as the application is running.


    Figure-3.14a

     

    (3.2) Study code

    1. timer-client.xhtml.

    <?xml version=’1.0′ encoding=’UTF-8′ ?>
    <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
    <html xmlns=”http://www.w3.org/1999/xhtml”
    xmlns:f=”http://java.sun.com/jsf/core”
    xmlns:h=”http://java.sun.com/jsf/html”
    xmlns:ui=”http://java.sun.com/jsf/facelets”>
    <body>
    <ui:composition template=”/timer.xhtml”>
    <ui:define name=”title”>
    Timer page
    </ui:define>

    <ui:define name=”body”>
    <p>The last programmatic timeout was: #{timerManager.lastProgrammaticTimeout}.</p>

    <p>The last automatic timeout was: #{timerManager.lastAutomaticTimeout}</p>

    <p>Set a programmatic timer here.</p>
    <h:form>
    <h:commandButton value=”Set Timer” action=”#{timerManager.setTimer}” />
    <h:commandButton value=”Refresh” action=”timer-client”/>
    </h:form>
    </ui:define>
    </ui:composition>
    </body>
    </html>

    2. TimerManager.java.

    package timersession.web;

    import javax.ejb.EJB;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import timersession.ejb.TimerSessionBean;

    /**
    *
    * @author ian
    */
    @ManagedBean
    @SessionScoped
    public class TimerManager {
    private String lastAutomaticTimeout;
    private String lastProgrammaticTimeout;
    @EJB
    private TimerSessionBean timerSession;

    /** Creates a new instance of TimerManager */
    public TimerManager() {
    this.lastProgrammaticTimeout = “never”;
    this.lastAutomaticTimeout = “never”;
    }

    /**
    * @return the lastTimeout
    */
    public String getLastProgrammaticTimeout() {
    lastProgrammaticTimeout = timerSession.getLastProgrammaticTimeout();

    return lastProgrammaticTimeout;
    }

    /**
    * @param lastTimeout the lastTimeout to set
    */
    public void setLastProgrammaticTimeout(String lastTimeout) {
    this.lastProgrammaticTimeout = lastTimeout;
    }

    public void setTimer() {
    long timeoutDuration = 8000;
    timerSession.setTimer(timeoutDuration);
    }

    /**
    * @return the lastAutomaticTimeout
    */
    public String getLastAutomaticTimeout() {
    lastAutomaticTimeout = timerSession.getLastAutomaticTimeout();

    return lastAutomaticTimeout;
    }

    /**
    * @param lastAutomaticTimeout the lastAutomaticTimeout to set
    */
    public void setLastAutomaticTimeout(String lastAutomaticTimeout) {
    this.lastAutomaticTimeout = lastAutomaticTimeout;
    }
    }

    3. TimerSessionBean.java

    /*
    * Copyright 2009 Sun Microsystems, Inc.
    * All rights reserved.  You may not modify, use,
    * reproduce, or distribute this software except in
    * compliance with  the terms of the License at:
    * http://developer.sun.com/berkeley_license.html
    */

    package timersession.ejb;

    import java.util.Date;
    import java.util.logging.Logger;
    import javax.annotation.Resource;
    import javax.ejb.Schedule;
    import javax.ejb.Singleton;
    import javax.ejb.Startup;
    import javax.ejb.Timeout;
    import javax.ejb.Timer;
    import javax.ejb.TimerService;

    /**
    * TimerBean is a singleton session bean that creates a timer and prints out a
    * message when a timeout occurs.
    * Created March 3, 2009 12:38 PM PST
    * @author ian
    */
    @Singleton
    @Startup
    public class TimerSessionBean {
    @Resource
    TimerService timerService;
    private Date lastAutomaticTimeout;
    private Date lastProgrammaticTimeout;
    private Logger logger = Logger.getLogger(
    “com.sun.tutorial.javaee.ejb.timersession.TimerSessionBean”);

    public void setTimer(long intervalDuration) {
    logger.info(
    “Setting a programmatic timeout for ” + intervalDuration
    + ” milliseconds from now.”);

    // Create a single-action timer that expires after a specified duration.
    Timer timer = timerService.createTimer(
    intervalDuration,
    “Created new programmatic timer”);
    }

    // Designates a method that should receive EJB timer expiration
    @Timeout
    public void programmaticTimeout(Timer timer) {
    this.setLastProgrammaticTimeout(new Date());
    logger.info(“Programmatic timeout occurred.”);
    }

    // Schedule a timer for automatic creation with a timeout schedule based
    // on a cron-like time expression. The annotated method is used as the
    // timeout callback method.
    //
    // Invoke the method every minute in every hour.
    @Schedule(minute = “*/1”, hour = “*”)
    public void automaticTimeout() {
    this.setLastAutomaticTimeout(new Date());
    logger.info(“Automatic timeout occured”);
    }

    /**
    * @return the lastTimeout
    */
    public String getLastProgrammaticTimeout() {
    if (lastProgrammaticTimeout != null) {
    return lastProgrammaticTimeout.toString();
    } else {
    return “never”;
    }
    }

    /**
    * @param lastTimeout the lastTimeout to set
    */
    public void setLastProgrammaticTimeout(Date lastTimeout) {
    this.lastProgrammaticTimeout = lastTimeout;
    }

    /**
    * @return the lastAutomaticTimeout
    */
    public String getLastAutomaticTimeout() {
    if (lastAutomaticTimeout != null) {
    return lastAutomaticTimeout.toString();
    } else {
    return “never”;
    }
    }

    /**
    * @param lastAutomaticTimeout the lastAutomaticTimeout to set
    */
    public void setLastAutomaticTimeout(Date lastAutomaticTimeout) {
    this.lastAutomaticTimeout = lastAutomaticTimeout;
    }
    }

    (3.3) Open, build, and run “automatic-timer” sample application (from “glassfish-samples”)

    1. Open automatic-timer NetBeans project.

    • Select File->Open Project (Ctrl+Shift+O).
    • Observe that the Open Project dialog box appears.
    • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/samples/javaee6/ejb directory.
    • Select automatic-timer.
    • Click Open Project.
    • Observe that the automatic-timer-ejb project node appears under Projects tab window.

    2. Build and run automatic-timer-ejb project.

    • Right-click automatic-timer-ejb project and select Run.
    • Observe the result in the Output window.

     

    (3.4) Study the code

    1. StatelessSession.java

    package enterprise.automatic_timer_ejb;

    import java.util.List;

    import javax.ejb.Remote;

    @Remote
    public interface StatelessSession {

    public List<String> getRecords();

    }

    2. StatelessSessionBean.java

    package enterprise.automatic_timer_ejb;

    import java.util.Date;
    import java.util.List;

    import javax.ejb.Stateless;
    import javax.ejb.Schedule;
    import javax.ejb.Timer;
    import javax.persistence.EntityManager;
    import javax.persistence.Query;
    import javax.persistence.PersistenceContext;

    import enterprise.automatic_timer_ejb.persistence.LogRecord;

    @Stateless
    public class StatelessSessionBean implements StatelessSession {

    @PersistenceContext EntityManager em;

    @Schedule(second=”*/3″, minute=”*”, hour=”*”, info=”Automatic Timer Test”)
    public void test_automatic_timer(Timer t) {
    long count = (Long)em.createNamedQuery(“LogRecord.countLoggedTimeouts”).getSingleResult();

    System.out.println(“Call # ” + (count + 1));
    if (count > 10) {
    throw new IllegalStateException(“Too many timeouts received: ” + count);
    } else if (count == 10) {
    LogRecord lr = new LogRecord(“Canceling timer ” + t.getInfo() + ” at ” + new Date());
    em.persist(lr);
    t.cancel();
    System.out.println(“Done”);
    } else {
    LogRecord lr = new LogRecord(“” + t.getInfo() + ” timeout received at ” + new Date());
    em.persist(lr);
    }
    }

    public List<String> getRecords() {
    return (List<String>)em.createNamedQuery(“LogRecord.findAllRecords”).getResultList();
    }
    }

    3. LogRecord.java

    package enterprise.automatic_timer_ejb.persistence;

    import javax.persistence.*;

    //name defaults to the unqualified entity class name.
    //default access is property.
    @Entity
    @NamedQueries({
    @NamedQuery(name = “LogRecord.countLoggedTimeouts”, query = “select count(l) from LogRecord l where l.record NOT LIKE \”Canceling timer%\””),
    @NamedQuery(name = “LogRecord.findAllRecords”, query = “select l.record from LogRecord l”)
    })
    public class LogRecord {

    @Id
    @GeneratedValue
    private int id;
    private String record;

    public LogRecord(String record) {
    setRecord(record);
    }

    public LogRecord() {
    }

    public String getRecord() {
    return record;
    }
    public void setRecord(String record) {
    this.record = record;
    }

    }

    Summary

    In this exercise, you have learned the Timer feature of EJB 3.1, which provides an ability to declaratively create cron-like schedules to trigger EJB methods.

    Exercise 4: Asynchronous method invocation using @Asynchronous

    In previous version of EJB, the only way to accomplish asynchronous processing was by using Message Driven Beans.  Even though writing MDBs was very trivial, configuring all the necessary server resources like connection factories, topics and queues made it a little bit of a chore, especially since all I needed was an asynchronous method invocation.

    With EJB 3.1 these issues are easily solved by a simple annotation placed on the Session Bean: @Asynchronous. Under normal circumstances, a Session bean method call blocks the client for the duration of that call. With this annotation in place, the container returns control to the client and executes the method on a separate thread.

    The Session bean method call which is annotated with the @ Asynchronous annotation can return a java.util.Future object that allows the client to retrieve a result value, check for exceptions, or attempt to cancel an in-progress invocation.

    1. Asynchronous method
    2. Study the code.
    3. Asynchronous method with Future
    4. Study the code

    (4.1) Asynchronous method

    In this exercise, a method, which performs a potentially long-ruuning database operration,  in ItemEJB is called with @Asynchronous.  The method returns void.

    1. Open ejb3.1_asynch NetBeans project (from “Lab samples”).

    • Select File->Open Project (Ctrl+Shift+O).
    • Observe that the Open Project dialog box appears.
    • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/samples directory directory.
    • Select ejb3.1_asynch.
    • Click Open Project.
    • Observe that the ejb3.1_asynch project node appears under Projects tab window.

    2. Build and run ejb3.1_asynch project.

    • Right-click ejb3.1_asynch project and select Run.
    • Browser gets displayed.
    • For the Title field, enter Life is good! (or whatever book title of your choice).
    • Click Submit Query button.


    Figure-4.11

    • Observe that the name of the Book title gets displayed.


    Figure-4.12

     

    (4.2) Study code

    1. index.html.

    <html>
    <head><title>Create a Book</title></head>
    <body>
    <h1>Create a new book</h1>
    <hr/>
    <form action=”BookServlet”>
    <table border=”0″>
    <tr>
    <td>Title :</td>
    <td><input type=”text” name=”title”/></td>
    </tr>
    </table>

    <input type=”submit” name=”Create a book”/>

    </form>
    <hr/>

    </body>
    </html>

    2. BookServlet.java.

    package mypackage;

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

    @WebServlet(loadOnStartup = 1, urlPatterns = “/BookServlet”)
    public class BookServlet extends HttpServlet {

    // Inject ItemEJB instance
    @EJB
    private ItemEJB itemEJB;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // Creates an instance of book
    Book book = new Book();
    book.setTitle(request.getParameter(“title”));

    // Call EJB method asynchronously
    itemEJB.createBookAsynch(book);
    try {
    // Sleep for 2000 ms to give async. thread to finish the task
    Thread.sleep(2000);

    response.setContentType(“text/html”);
    PrintWriter out = response.getWriter();

    // Displays the books
    out.println(“<h1>====== All books ======</h1>”);
    //List<Book> books = em.createNamedQuery(“findAllBooks”).getResultList();
    List<Book> books = itemEJB.findAllBooks();
    for (int i = 0; i < books.size(); i++) {
    Book b = books.get(i);
    out.println(“Book title: ” + b.getTitle() + “<br/>”);
    }
    } catch (Exception ie) {
    }

    }
    }

    BookServlet.java

    3. ItemEJB.java

    package mypackage;

    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;
    import java.util.concurrent.Future;
    import javax.ejb.AsyncResult;
    import javax.ejb.Asynchronous;

    @Stateless
    public class ItemEJB {

    @PersistenceContext
    private EntityManager em;

    public Book createBook(Book book) {
    em.persist(book);
    return book;
    }

    @Asynchronous
    public void createBookAsynch(Book book) {
    em.persist(book);
    }

    @Asynchronous
    public Future<Book> createBookAsynchUsingFuture(Book book) {
    em.persist(book);
    return new AsyncResult<Book>(book);
    }

    public List<Book> findAllBooks() {
    return em.createNamedQuery(“findAllBooks”).getResultList();
    }
    }

    ItemEJB.java

    4. Book.java

    package mypackage;

    import javax.persistence.*;

    @Entity
    @NamedQueries({
    @NamedQuery(name = “findAllBooks”, query = “SELECT b FROM Book b”)
    })
    public class Book {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

    public Long getId() {
    return id;
    }

    public String getTitle() {
    return title;
    }

    public void setTitle(String title) {
    this.title = title;
    }
    }

    Book.java

    (4.3) Open, build, and run “ejb3.1_asynch_using_Future” sample application (from “Hands-on lab samples”)

    In this exercise, a method, which performs a potentially long-ruuning database operration,  in ItemEJB is called with @Asynchronous.  The method returns Future object.

    1. Open ejb3.1_asynch_using_Future NetBeans project.

    • Select File->Open Project (Ctrl+Shift+O).
    • Observe that the Open Project dialog box appears.
    • Browse down to Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/samples directory.
    • Select ejb3.1_asynch_using_Future.
    • Click Open Project.
    • Observe that the ejb3.1_asynch_using_Future project node appears under Projects tab window.

    2. Build and run ejb3.1_asynch_using_Future project.

    • Right-click ejb3.1_asynch_using_Future project and select Run.
    • Browser gets displayed.
    • For the Title field, enter Life is good! (or whatever book title of your choice).
    • Click Submit Query button.


    Figure-4.31


    Figure-4.32

    (4.4) Study code

    1. BookServlet.java

    package mypackage;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.concurrent.Future;
    import javax.ejb.EJB;

    @WebServlet(loadOnStartup = 1, urlPatterns = “/BookServlet”)
    public class BookServlet extends HttpServlet {

    // Inject ItemEJB instance
    @EJB
    private ItemEJB itemEJB;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // Creates an instance of book
    Book book = new Book();
    book.setTitle(request.getParameter(“title”));

    // Call EJB method asynchronously
    Future<Book> future = itemEJB.createBookAsynchUsingFuture(book);
    try {
    // Sleep for 2000 ms to give async. thread to finish the task
    Thread.sleep(2000);

    response.setContentType(“text/html”);
    PrintWriter out = response.getWriter();

    // Display the newly created book
    out.println(“<h1>====== Book that has been created asynchronously</h1>”);
    Book b = future.get();
    out.println(“Book title: ” + b.getTitle() + “<br/>”);

    } catch (Exception ie) {
    }
    }
    }

    BookServlet.java

    2. ItemEJB.java.

    package mypackage;

    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;
    import java.util.concurrent.Future;
    import javax.ejb.AsyncResult;
    import javax.ejb.Asynchronous;

    @Stateless
    public class ItemEJB {

    @PersistenceContext
    private EntityManager em;

    public Book createBook(Book book) {
    em.persist(book);
    return book;
    }

    @Asynchronous
    public void createBookAsynch(Book book) {
    em.persist(book);
    }

    @Asynchronous
    public Future<Book> createBookAsynchUsingFuture(Book book) {
    em.persist(book);
    return new AsyncResult<Book>(book);
    }

    public List<Book> findAllBooks() {
    return em.createNamedQuery(“findAllBooks”).getResultList();
    }
    }

    ItemEJB.java

    Summary

    In this exercise, you have learned how to use @Asynchronous annotation to invoke a EJB method in asynchronous manner.

     

    Exercise 5: EJB Embedded (Building Embeddable EJB app step by step)

    Testing EJBs was a herculean task all these years. It isn’t anymore with the timely and useful innovation of the embeddable container. The embeddable container allows you to use JPA and EJB 3.1 outside a container including testing.

    In this exercise, you are going to build a standalone Java SE application in which you are going to test EJB-based application logic step by step.

    1. Create a new “Java Application” (Java SE) project
    2. Create EJB beans
    3. Add libraries
    4. Create persistence unit
    5. Add testing code
    6. Build a jar file (that contains EJB beans)
    7. Run the testing
    8. Use APP_NAME JNDI name

    (5.1) Create a new “Java Application” (Java SE) project

    1. Create a new Java Application project.


    Figure-5.11


    Figure-5.12

    2. Give a name to the project.

    • For the Project Name field, enter ejb3.1_embedded.
    • Uncheck Create Main Class.  (We don’t need to create Main class.)
    • Click Finish.


    Figure-5.13

    (5.2) Add EJB beans

    In this step, you are going to add a simple Book entity class and ItemBook Stateless bean class.

    1. Add Book entity class.

    • Right click project and select New->Entity Class.  (If you don’t see Entity class from the pop-up menu, select Other, select Persistence on the left.)


    Figure-5.21

    • For the Class Name field, enter Book.
    • For the Package field, enter mypackage.
    • Click Finish.


    Figure-5.22

    2. Modify the IDE generated Book.java as shown below.

    package mypackage;

    import java.io.Serializable;
    import javax.persistence.*;

    @Entity
    @NamedQueries({
    @NamedQuery(name = “findAllBooks”, query = “SELECT b FROM Book b”)
    })
    public class Book implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

    public Long getId() {
    return id;
    }

    public String getTitle() {
    return title;
    }

    public void setTitle(String title) {
    this.title = title;
    }
    }


    Figure-5.23

    3. Create ItemEJB Stateless bean.


    Figure-5.24

    • For the Class Name field, enter ItemEJB.
    • Click Finish.

     


    Figure-5.25

    4. Modify IDE generated ItemEJB.java as shown below.

    package mypackage;

    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;

    @Stateless
    public class ItemEJB {

    @PersistenceContext
    private EntityManager em;

    public Book createBook(Book book) {
    em.persist(book);
    return book;
    }

    public List<Book> findAllBooks() {
    return em.createNamedQuery(“findAllBooks”).getResultList();
    }

    }


    Figure-5.26

    return to top of exercise

    (5.3) Add libraries

    In this step you are going add the following library jar files.

    • From the <GlassFish-v3-Installation-Directory>/glassfish/modules directory.
    • gf-ejb-connector.jar
    • glassfish-api.jar
    • javax.ejb.jar
    • javax.persistence.jar
    • From <GlassFish-v3-Installation-Directory>/glassfish/modules/endorsed directory
    • javax.annotation.jar
    • From the <GlassFish-v3-Installation-Directory>/glassfish/lib/embedded directory.
    • glassfish-embedded-static-shell.jar

    1. Add jar files from <GlassFish-v3-Installation-Directory>/glassfish/modules directory.


    Figure-5.31


    Figure-5.32


    Figure-5.33

    2. Add library files from <GlassFish-v3-Installation-Directory>/glassfish/modules/endorsed directory


    Figure-5.34

    3. Add library files from <GlassFish-v3-Installation-Directory>/glassfish/lib/embedded directory.


    Figure-5.35

     

    4. Verify that the library files are added.


    Figure-5.36

    return to top of exercise

    (5.4) Create persistence unit

    1. Create persistence unit.


    Figure-5.41

    2. Set the values of the persistence unit.

    • For the Persistence Unit Name field, take the value given by the IDE.
    • For the Database Connection field, select jdbc:derby://localhost:1527/sample [app on APP].
    • For the Table Generation Strategy, select Drop and Create.
    • Click Finish.

     


    Figure-5.42

    3. Add entity class to the persistence unit.

    • Click Add Class button for the Include Entity Classes section.

     


    Figure-5.43

    • Select mypackage.Book.
    • Click OK.

     


    Figure-5.44

    4. Change Transaction Type to JTA.

    • Select XML tab.
    • Change the value of the transaction-type attribute to JTA.

     


    Figure-5.45

    (5.5) Add testing code

    In this step, you are going to add testing code in which EJBContainer gets created, EJB are deployed and tested.

    1. Create ItemEJBTest.java.

    • Right click Test Packages and select New->Java Class.


    Figure-5.51

    • For the Class Name field, enter ItemEJBTest.
    • For the Package field, enter testpackage.
    • Click Finish.


    Figure-5.52

    2. Modify IDE generated code with the one below.

    package testpackage;

    import mypackage.Book;
    import javax.ejb.embeddable.EJBContainer;
    import javax.naming.Context;
    import mypackage.ItemEJB;
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    import static org.junit.Assert.*;

    public class ItemEJBTest {

    private static EJBContainer ec;
    private static Context ctx;

    @BeforeClass
    public static void initContainer() throws Exception {
    System.out.println(“—-Creating EJBContainer…”);
    ec = EJBContainer.createEJBContainer();
    ctx = ec.getContext();
    }

    @AfterClass
    public static void closeContainer() throws Exception {
    if (ec != null) {
    System.out.println(“—-Closing EJBContainer…”);
    ec.close();
    }
    }

    @Test
    public void createBook() throws Exception {
    System.out.println(“—-Looking up EJB…”);
    ItemEJB itemEJB = (ItemEJB) ctx.lookup(“java:global/classes/ItemEJB”);
    // ItemEJB itemEJB = new ItemEJB();

    // Counts all the books in the database
    int nbBooks = itemEJB.findAllBooks().size();

    // Creates a new book
    Book book = new Book();
    book.setTitle(“Passion”);

    // Persists the book to the database
    System.out.println(“—-Creating a book…”);
    book = itemEJB.createBook(book);
    assertNotNull(“ID should not be null”, book.getId());

    // Checks that there is an extra book in the database
    assertEquals(“Should have an extra book”, itemEJB.findAllBooks().size(), nbBooks + 1);
    }
    }


    Figure-5.53

    (5.6) Build a jar file that contains EJB

    1. Do the clean build.


    Figure-5.61

    2. Verify that the build was successful.


    Figure-5.62

    (5.7) Run the testing

    1. Right click ItemEJBTest.java under Test Packages->testpackages and select either Run File or Test File.


    Figure-5.71

    2. Observe the debugging messages from the testing.


    Figure-5.72

    3. Observe the testing result.

    • If you don’t see the Testing Results window, select Window from the top-level menu and select Output->Test Results.

     


    Figure-5.73

    • Observe that the test passed.

     


    Figure-5.74

    • Observe the debugging messages.

     


    Figure-5.75

    Solution: The solution is available as “ready to open and build” NetBeans project as ejb3.1_embedded under <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/solution directory.

    (5.8) Use APP_NAME JNDI name

    1. Modify the ItemEJBTest.java as shown below.

    package testpackage;

    import java.util.HashMap;
    import java.util.Map;
    import mypackage.Book;
    import javax.ejb.embeddable.EJBContainer;
    import javax.naming.Context;
    import mypackage.ItemEJB;
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    import static org.junit.Assert.*;

    public class ItemEJBTest {

    private static EJBContainer ec;
    private static Context ctx;

    @BeforeClass
    public static void initContainer() throws Exception {
    System.out.println(“—-Creating EJBContainer…”);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put(EJBContainer.APP_NAME, “myapp”);
    ec = EJBContainer.createEJBContainer(map);
    ctx = ec.getContext();
    }

    @AfterClass
    public static void closeContainer() throws Exception {
    if (ec != null) {
    System.out.println(“—-Closing EJBContainer…”);
    ec.close();
    }
    }

    @Test
    public void createBook() throws Exception {
    System.out.println(“—-Looking up EJB…”);
    ItemEJB itemEJB = (ItemEJB) ctx.lookup(“java:global/myapp/ItemEJB”);
    // ItemEJB itemEJB = new ItemEJB();

    // Counts all the books in the database
    int nbBooks = itemEJB.findAllBooks().size();

    // Creates a new book
    Book book = new Book();
    book.setTitle(“Passion”);

    // Persists the book to the database
    System.out.println(“—-Creating a book…”);
    book = itemEJB.createBook(book);
    assertNotNull(“ID should not be null”, book.getId());

    // Checks that there is an extra book in the database
    assertEquals(“Should have an extra book”, itemEJB.findAllBooks().size(), nbBooks + 1);
    }
    }

    2. Do the clean build.


    Figure-5.81

    3. Run the testing.

    • Observe that the testing is successful.

    Solution: The solution is available as “ready to open and build” NetBeans project as ejb3.1_embedded_jndi_APP_NAME under <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/solutions directory.

    Summary

    In this exercise,  you have learned how to test EJB through “Embeddable EJB container” feature of EJB 3.1, in which EJB container can be created programmatically and EJB are deployed and tested.

    Exercise 6: EJB and RESTful service

    In JAX-RS 1.1, EJB can be exposed as RESTful web service.

    1. Verify a simple EJB application is working
    2. Expose EJB as restful web service
    3. Use “Curl” to test response format
    4. Use @ApplicationPath annotation

    (6.1) Verify a simple EJB application is working

    In this step, you are going to verify a simple EJB application is working as expected.  We are going to expose Session bean as RESTful services.

    1. Open ejb3.1_rest_base NetBeans project (from “Lab samples”).

    • Select File->Open Project (Ctrl+Shift+O).
    • Observe that the Open Project dialog box appears.
    • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/samples directory directory.
    • Select ejb3.1_rest_base.
    • Click Open Project.
    • Observe that the ejb3.1_rest_base project node appears under Projects tab window.

    2. Build and run ejb3.1_rest_base project.

    • Right-click ejb3.1_rest_base project and select Run.
    • Browser gets displayed.


    Figure-6.11

    • Observe that the newly created book title is displayed.  This verifies the sample app is a working EJB application.


    Figure-6.12

    (6.2) Make the Session bean as RESTful service

    1. Modify ItemEJB.java as shown below. The code fragments that need to be added are highlighted in bold and red-colored font.

    package mypackage;

    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;

    @Stateless
    @Path(“/items”)
    public class ItemEJB {

    @PersistenceContext
    private EntityManager em;

    public Book createBook(Book book) {
    em.persist(book);
    return book;
    }

    @GET
    @Path(“{bookKey}”)
    @Produces({“application/xml”, “application/json”})
    public Book getBook(@PathParam(“bookKey”) String key) {
    Book theBook = em.find(Book.class, new Long(key));
    return theBook;
    }

    @GET
    public List<Book> findAllBooks() {
    return em.createNamedQuery(“findAllBooks”).getResultList();
    }
    }


    Figure-6.21

    2. Modify Book.java as shown below.

    package mypackage;

    import java.io.Serializable;
    import javax.persistence.*;
    import javax.xml.bind.annotation.XmlRootElement;

    @Entity
    @NamedQueries({
    @NamedQuery(name = “findAllBooks”, query = “SELECT b FROM Book b”)
    })
    @XmlRootElement
    public class Book implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

    public Long getId() {
    return id;
    }

    public String getTitle() {
    return title;
    }

    public void setTitle(String title) {
    this.title = title;
    }
    }


    Figure-6.22

    3. Build and run the application and add two Book items into Book table.


    Figure-6.23


    Figure-6.24


    Figure-6.25


    Figure-6.26

    4. Verify that the BOOK table has two entries.

    5. Test the ItemEJB RESTful web service.

    • Observe that the browser gets displayed.

    6. Access ItemEJB as RESTful web services using browser.


    Figure-6.27

     Trouble-shooting: If you are using Safari over MacOS, the response might not be prorperly formated in XML.  Please use Firefox instead..


    Figure-6.28

    (6.3) Use “Curl” utility

    0. Install “Curl” utility only if you are running Windows or OpenSolaris.  For MacOS or other Linux OS’es, “Curl” utility comes with the OS.  Reinstallation of “Curl” might cause some mal-functioning behavior on Mac OS X or other Linux OS’es.

    1. Retrieve the response in JSON format.
    The command to type in the terminal is highlighted in red color, the answer in blue color.

    curl -H “Accept:application/json” http://localhost:8080/ejb3.1_rest_base/resources/items
    {“book”:[{“title”:”Life is passion!”},{“title”:”2nd book title”}]}


    Figure-6.31

    2. Retrieve the response in XML format
    The command to type in the terminal is highlighted in red color, the answer in blue color.

    curl -H “Accept:application/xml” http://localhost:8080/ejb3.1_rest_base/resources/items
    <?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?><books><book><title>Life is passion!</title></book><book><title>2nd book title</title></book></books>


    Figure-6.32

    Solution: The solution is available as “ready to open and build” NetBeans project as ejb3.1_rest under <LAB_UNZIPPED_DIRECTORY>/javaee6_ejb3.1/solutions directory. (You will have to use ejb3.1_rest rather than ejb3.1_rest_base as application context.)

    (6.4) Use @ApplicationPath annotation

    1. Add ApplicationConfig.java.  Note that the value of the Application path is et to resources1.

    package mypackage;

    @javax.ws.rs.ApplicationPath(“resources1”)
    public class ApplicationConfig  extends javax.ws.rs.core.Application {

    }


    Figure-6.41

    2. Build and run the application and add two Book items into Book table.

    3. Now observe that you can use resources1 application path.


    Figure-6.42


    Figure-6.43

    Summary

    In this exercise, you have learned how to use JAX-RS annotations to expose EJB as RESTful web service.

    Homework Exercise

    1. The homework #1 is to modify EJB-in-a-war project you did in Exercise 1 above as following.   (You might want to create a new project by copying my_ejb3.1 project.  You can name the newly copied project in any way you want.  Here it is referred to as my_ejb3.1.)

    • Exercise point: EJB in a war packaging
      • Add another stateless bean called YourSessionBean with the following two methods.
        • add(int x, int y)
        • multiply(int x, int y)
      • From the HelloServlet, call these two methods using x value 10 and y value 6 and display the result
    • Exercise point: Singleton
      • Create a Singleton EJB which has the following two variables, which are used as a total values of the addition and multiplication
        • int total_addition
        • int total_multiplication
    • Exercise point: Timer
      • Use timer to display the value of total_addition and total_multiplication every hour of the day at the GlassFish v3 server log. (Basically use System.out.println(..) method.)

    2. The homework #2 is to create my_ejb3.1_embedded project as following.

    • Exercise point: EJB embedded
      • Create Java SE application in which the add(..) and multiply(..) methods are tested
    3. Send the following files to javaee6-homeworks@sun.com with Subject as homework_javaee6_ejb3.1.
    • Zip file of the the my_ejb3.1 and my_ejb3.1_embedded NetBeans projects.  (Someone else should be able to open and runthem as NetBeans projects.)  You can use your favorite zip utility or you can use “jar” utility that comes with JDK as following.
      • cd <parent directory that contains my_ejb3.1 directory> (assuming you named your project as my_ejb3.1)
      • jar cvf my_ejb3.1.zip my_ejb3.1 (my_ejb3.1 should contain nbproject directory)
    Please reduce the size of the zip file by right clicking the project and then selecting Clean before zipping the file.
    • Captured output screen  – name it as homework_javaee6_ejb3.1.gif or homework_javaee6_ejb3.1_embedded.jpg (or homework_javaee6_ejb3.1.<whatever graphics format>) and as homework_javaee6_ejb3.1_embedded.gif or homework_javaee6_ejb3.1_embedded.jpg (or homework_javaee6_ejb3.1_embedded.<whatever graphics format>)
      • Any screen capture that shows that your program is working is good enough.

     

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다