목요일, 3월 28
Shadow

#032 Java EE 6: DI (JSR 330) and CDI (JSR 299)

 

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

  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: @Inject simple usages

The container injects references to contextual instances to the following kinds of injection point:

  • Any injected field of a bean class
  • Any parameter of a bean constructor, initializer method, producer method or disposer method
  • Any parameter of an observer method, except for the event parameter
In this exercise, you are going to see simple usage of @Inject annotation.

 

 

(1.1) Inject a bean to a field: “inject_bean_to_field” sample application

1. Open inject_bean_to_field 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_injection/samples directory.
    • Windows: If you unzipped the 4531_javaee6_injection.zip file under C:\ directory, the directory to which you want to browse down should be C:\javaee6_injection\samples.
    • Solaris/Linux/Mac: If you unzipped the 4531_javaee6_injection.zip file under $HOME directory, the directory to which you want to browse down should be $HOME/javaee6_injection/samples.
  • Select inject_bean_to_field.
  • Click Open Project.
  • Observe that the inject_bean_to_field project node appears under Projects tab window.

2. Build and run inject_bean_to_field project.

  • Right-click inject_bean_to_field project and select Run.
  • Observe that the browser gets displayed.


Figure-1.11

(1.2)  Study the code of the project

1. Study HelloServlet.java.

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
public class HelloServlet extends HttpServlet {

// You need an empty beans.xml in the WEB-INF directory to enable Weld

// Inject Greeting object
@Inject Greeting greeting;

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>

}

HelloServlet.java

  • Display context senstive Javadoc on @Inject.


Figure-1.21


Figure-1.22

2. Study Greeting.java.

package mypackage;

public class Greeting {
public String greet(String name){
return “Hello ” + name;
}
}

Greeting.java

3. Study beans.xml.

An application that uses CDI must have a file named beans.xml. The file can be completely empty (it has content only in certain limited situations), but it must be present.  For a web application, the beans.xml file can be in either the WEB-INF directory or the WEB-INF/classes/META-INF directory. For EJB modules or JAR files, the beans.xml file must be in the META-INF directory.

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans/>

beans.xml


Figure-1.21

(1.3) Inject a bean via constructor method: “inject_bean_via_constructor” sample application

1. Open inject_bean_via_constructor NetBeans project.

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

2. Build and run inject_bean_via_constructor project.

  • Right-click inject_bean_via_constructor project and select Run.
  • Observe that the browser gets displayed.


Figure-1.31

(1.4) Study code

1. HelloServlet.java

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
public class HelloServlet extends HttpServlet {

private Greeting greeting;

// Use constructor method injection
@Inject
void HelloServlet(Greeting greeting){
this.greeting = greeting;
}

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>

}

(1.5) Inject a bean via init method: “inject_bean_via_init” sample application

1. Open inject_bean_via_init NetBeans project.

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

2. Build and run inject_bean_via_init project.

  • Right-click inject_bean_via_init project and select Run.
  • Observe that the browser gets displayed.

Figure-1.51

(1.6) Study code

1. Study the code – HelloServlet.java.

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
public class HelloServlet extends HttpServlet {

private Greeting greeting;

// Use initializer method injection
@Inject
void init(Greeting greeting){
this.greeting = greeting;
}

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>

}

(1.7) Inject a bean to a field:  “inject_bean_to_field_using_interface” sample application

In this exercise, you are going to inject a bean whose type is a Java interface.

1. Open inject_bean_to_field_using_interface NetBeans project.

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

2. Build and run inject_bean_to_field_using_interface project.

  • Right-click inject_bean_to_field_using_interface project and select Run.
  • Observe that the browser gets displayed.

Figure-1.71

(1.8) Study code

1. GreetingInterface.java

package mypackage;

public interface GreetingInterface {
public String greet(String name);
}

2. FormalGreeting.java

package mypackage;

public class FormalGreeting implements GreetingInterface {
public String greet(String name){
return “Formal Hello ” + name;
}
}

3. HelloServlet.java

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
public class HelloServlet extends HttpServlet {

// You need an empty beans.xml in the WEB-INF directory to enable Weld

// Inject GreetingInterface object
@Inject GreetingInterface greeting;

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>

}

(1.9) Inject an EJB to a field:  “inject_ejb_to_field” sample application

In this exercise, you are going to inject EJB object (instead of regular bean) into a field.   Given that you can inject an EJB through @Inject, you might have a question – “Is there any reason to use @Inject or @EJB when injecting EJB?”   The answer from Ken Saks (EJB 3.1 spec lead) is as following:

“Yes, @EJB provides a static mapping to the target EJB component based on Java type and any specific linking metadata like beanName() or lookup().   The result of the injection is the actual EJB reference.  (Note that this is still distinct from a
target bean *instance*)

@Inject adds an additional level of indirection by way of CDI, where the target EJB component is resolved via CDI’s type-safe resolution algorithm.  The result of injection is a CDI object that has an internal run-time mapping to a particular EJB reference. This allows whatever CDI scope is in context at the time of invocation to determine the target EJB reference.

Basically, if you want the additional CDI semantics to apply, use @Inject.  Otherwise, use @EJB.”

1. Open inject_ejb_to_field NetBeans project.

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

2. Build and run inject_ejb_to_field project.

  • Right-click inject_ejb_to_field project and select Run.
  • Observe that the browser gets displayed.

Figure-1.91

(1.10) Study code

1. Greeting.java.  Greeting is a stateless EJB.

package mypackage;

import javax.ejb.Stateless;

@Stateless
public class Greeting {
public String greet(String name){
return “Hello ” + name;
}

}

Summary

In this exercise,  you have learned how to inject a bean to a field, through constructor and init methods through @Inject annotation.  You also learned how to inject EJB through @EJB annotation.

 

Exercise 2: @Inject usage with @Qualifier

For a given bean type, there may be multiple beans which implement the type.  You can use qualifiers to provide different implementations of a particular bean type.  A qualifier is an annotation that you apply to a bean. A qualifier type is a Java annotation defined as @Target({METHOD, FIELD, PARAMETER, TYPE}) and @Retention(RUNTIME).

  1. Experience “ambiguity” error condition
  2. Use qualifier

(2.1) Experience “ambiguity” error condition

In this step, you are going to add InformalGreeting class which implements GreetingInterface to the inject_bean_to_field_using_interface project.  In other words, there are two classes, FormalGreeting and InformalGreeting classes which implement GreetingInterface interface.  This will cause ambiguity error condition.

1. Add InformalGreeting.java.   InformalGreeting class is added as the second class that implements GreetingInterface interface.


Figure-2.11


Figure-2.12

3. Modify the IDE generated InformalGreeting.java with the code below.  Note that InformalGreeting implements GreetingInterface.

package mypackage;

public class InformalGreeting implements GreetingInterface {
public String greet(String name){
return “Informal Hello ” + name;
}
}

4. Build and run and observe error condition.

  • Right click the project and select Run.
  • Observe the AmbiguousResolutionException occurred as expected.


Figure-2.13

Note: The completed version of this step is available as inject_qualifier_ambiguitycase project under <LAB_UNZIPPED_DIRECTORY>/javaee6_injection/samples directory. You can just build and run it to see the above result.

(2.2) User qualifier

In this step, you are going to define @Formal and @Informal qualifier types and apply them to FormalGreeting and InformalGreeting classes, which are the implementations of the GreetingInterface interface.

If you define a bean with no qualifier, it automatically has the qualifier @Default.

1. Add @Formal qualifier definition.  This is a marker interface that does not require a processor action.  If you are not sure how to define an annotation, please study Java Annotaiton.

package mypackage;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({
TYPE,
METHOD,
FIELD,
PARAMETER
})
public @interface Formal {
}

2. Add @Informal qualifier definition.

package mypackage;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({
TYPE,
METHOD,
FIELD,
PARAMETER
})
public @interface Informal {
}

3. Modify FormalGreeting class to get annotated with @Formal qualifier.

package mypackage;

@Formal
public class FormalGreeting implements GreetingInterface {
public String greet(String name){
return “Formal Hello ” + name;
}
}

4. Modify InformalGreeting class to get annotated with @Informal qualifier.

package mypackage;

@Informal
public class InformalGreeting implements GreetingInterface {
public String greet(String name){
return “Informal Hello ” + name;
}
}

5. Modify HelloServlet class to inject the Formal qualified type of the GreetingInterface

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name=”HelloServlet”, urlPatterns={“/HelloServlet”})
public class HelloServlet extends HttpServlet {

// You need an empty beans.xml in the WEB-INF directory to enable Weld

// Inject GreetingInterface object using qualifier
@Inject @Formal GreetingInterface greeting;

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>

}

6. Run the project.


Figure-2.21

Solution: The completed version is available as inject_qualifier project under <LAB_UNZIPPED_DIRECTORY>/javaee6_injection/samples directory. You can just build and run it to see the above result.

Summary

In this exercise, you have learned how to use qualifier when there are multiple implementations of a particular bean type.

 

Exercise 3: Scope

 

For a web application to use a bean that injects another bean class, the bean needs to be able to hold state over the duration of the user’s interaction with the application. The way to define this state is to give the bean a scope.  There are 5 scopes as following.  The first three scopes were originally defined by the Java Servlet specification. The last two are defined by JSR-299.

  • @RequestScoped
    • A user’s interaction with a web application in a single HTTP request
  • @SessionScoped
    • A user’s interaction with a web application across multiple HTTP requests
  • @ApplicationScoped
    • Shared state across all users’ interactions with a web application
  • @Dependent
    • The default scope if none is specified; it means that an object exists to serve exactly one client (bean), and has the same lifecycle as that client (bean)
  • @ConversationScoped
    • A user’s interaction with a JavaServer Faces application, within explicit boundaries controlled by the developer that extend the scope across multiple invocations of the JavaServer Faces life cycle. All long-running conversations are scoped to a particular HTTP servlet session and may not cross session boundaries.
  1. Use @RequestScoped
  2. Study code
  3. Use @ConversationScoped
  4. Study code

(3.1) Use @RequestScoped

In this exercise, you are going to see a bean – Printer bean – whose scope is defined with @RequestScoped annotation.

1. Open inject_scope_request 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_injection/samples directory.
  • Select inject_scope_request.
  • Click Open Project.
  • Observe that the inject_scope_request project node appears under Projects tab window.

2. Build and run inject_scope_request project.

  • Right-click inject_scope_request project and select Run.
  • Observe that the browser gets displayed.
  • For the Enter your name field, enter <your name>.
  • Click Say Hello button.

Figure-3.11


Figure-3.12

(3.2) Study the code

1. index.xhtml.  This is Facelet.

<?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”>
<ui:composition template=”/template.xhtml”>

<ui:define name=”title”>Simple Greeting</ui:define>
<ui:define name=”head”>Simple Greeting</ui:define>
<ui:define name=”content”>
<h:form id=”greetme”>
<p><h:outputLabel value=”Enter your name: ” for=”name”/>
<h:inputText id=”name” value=”#{printer.name}”/></p>
<p><h:commandButton value=”Say Hello” action=”#{printer.createSalutation}”/></p>
<p><h:outputText value=”printer.salutation = #{printer.salutation}”/> </p>
</h:form>
</ui:define>

</ui:composition>
</html>

index.xhtml

2. Printer.java.

import javax.inject.Inject;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class Printer {
@Inject
@Informal
Greeting greeting;
private String name;
private String salutation = “nothing yet!”;

public void createSalutation() {
this.salutation = greeting.greet(name);
}

public String getSalutation() {
return salutation;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

Printer.java

(3.3) Use @ConversationScoped

1. Open inject_scope_conversation 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_injection/samples directory.
  • Select inject_scope_conversation.
  • Click Open Project.
  • Observe that the inject_scope_conversation project node appears under Projects tab window.

2. Build and run inject_scope_conversation project.

  • Right-click inject_scope_conversation project and select Run.
  • Observe that the browser gets displayed.
3. Run the application without starting a conversation.  What this means is the Printer object is in @RequestScoped scope.


Figure-3.31


Figure-3.32


Figure-3.33


Figure-3.34

4. Run the application in Conversation scope.

  • Click Start Conversation button.  This will start the conversation scope.


Figure-3.35

  • Observe that the conversation scope is on.


Figure-3.36

  • For the Enter your name field, enter a name.
  • Click Say Hello button.


Figure-3.37


Figure-3.38


Figure-3.39


Figure-3.40

5. Turn off the conversation.


Figure-3.41


Figure-3.42


Figure-3.43


Figure-3.44

(3.4) Study code

1. index.html

<?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”>
<ui:composition template=”/template.xhtml”>

<ui:define name=”title”>Simple Greeting</ui:define>
<ui:define name=”head”>Simple Greeting</ui:define>
<ui:define name=”content”>
<h:form id=”greetme”>
<p><h:outputLabel value=”Enter your name: ” for=”name”/>
<h:inputText id=”name” value=”#{printer.name}”/></p>
<p><h:commandButton value=”Say Hello” action=”#{printer.createSalutation}”/></p>
<p><h:commandButton value=”Start conversation” action=”#{printer.startConversation}”/></p>
<p><h:commandButton value=”End conversation” action=”#{printer.endConversation}”/></p>
<p><h:outputText value=”printer.salutation = #{printer.salutation}”/> </p>
<p><h:outputText value=”printer.old_salutation = #{printer.old_salutation}”/> </p>
<p><h:outputText value=”myConversationStatus.conversationSattus = #{myConversationStatus.conversationSattus}”/> </p>
</h:form>
</ui:define>

</ui:composition>
</html>

2. Printer.java

package greetings;

import java.io.Serializable;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@ConversationScoped
public class Printer implements Serializable {

@Inject
@Informal
Greeting greeting;
@Inject
Conversation conversation;
@Inject
MyConversationStatus cstatus;
private String name;
private String salutation = “nothing yet!”;
private String old_salutation = “nothing yet!”;

public void startConversation() {
cstatus.setConversationSattus(“on”);
conversation.begin();
}

public void endConversation() {
cstatus.setConversationSattus(“off”);
conversation.end();
}

public void createSalutation() {
this.old_salutation = salutation;
this.salutation = greeting.greet(name);
}

public String getSalutation() {
return salutation;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

/**
* @return the old_salutation
*/
public String getOld_salutation() {
return old_salutation;
}

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

Printer.java

Summary

In this exercise, you have learned, for a web application to use a bean that injects another bean class, how to use scope for holding state over the duration of the user’s interaction with the application.

 

Exercise 4: Producer Methods

Producer methods provide a way to inject objects that are not beans, objects whose values may vary at run time, and objects that require custom initialization.

(4.1) Open, build, and run “inject_producer_businesslogic” sample application

1. Open inject_producer_businesslogic NetBeans project.

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

2. Build and run inject_producer_businesslogic project.

  • Right-click inject_producer_businesslogic project and select Run.
  • Observe that the browser gets displayed.

Figure-4.11

(4.2) Study code

1. HelloServlet.java

package mypackage;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = “HelloServlet”, urlPatterns = {“/HelloServlet”})
public class HelloServlet extends HttpServlet {

@Inject @Formal
String greetingMessage;

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
//
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet HelloServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
//out.println(“<h1>Calling a method of an injected class: ” + greeting.greet(“Codecamper!”) + “</h1>”);
out.println(“<h1>” + new Date() + “: ” + greetingMessage + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
//
} finally {
out.close();
}
}

// <editor-fold defaultstate=”collapsed” desc=”HttpServlet methods. Click on the + sign on the left to edit the code.”>
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>
}

HelloServlet.java

2. FormalGreeting.java.  Note that the @Formal annotation is used not with the FormalGreeting class but with the getFormalGreeting() method, in which you can produce and return an object of @Formal type.

package mypackage;

import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.enterprise.inject.Produces;

public class FormalGreeting {

String formalGreeting;

// Produces greeting message based on business logic.
@Produces
@Formal
public String getFormalGreeting() {
GregorianCalendar todaysDate = new GregorianCalendar();
int hour_of_day = todaysDate.get(Calendar.HOUR_OF_DAY);
if (hour_of_day < 12) {
formalGreeting = “Good morning!”;
}
if (hour_of_day > 11 && hour_of_day < 17) {
formalGreeting = “Good afternoon!”;
}
if (hour_of_day >= 17 && hour_of_day < 22) {
formalGreeting = “Good evening!”;
}
if (hour_of_day >= 22) {
formalGreeting = “Good night!”;
}
return formalGreeting;
}
}

FormalGreeting.java

Summary

In this exercise,  you have learned how to  provide a way to inject objects whose values may vary at run time based on business logic through @Produces annotation.

Exercise 5: Managed Bean with Lifecycle methods

The ManagedBean annotation marks a POJO (Plain Old Java Object) as a ManagedBean.  A ManagedBean supports a small set of basic services such as resource injection, lifecycle callbacks and interceptors.

  1. Open, build, and run “managedbean_lifecycle_defaultscope” sample application
  2. Study the code
  3. Open, build, and run “managedbean_lifecycle_requestscope” sample application
  4. Study the code
  5. Open, build, and run “managedbean_interceptor” sample application
  6. Study the code

 

(5.1) Open, build, and run “managedbean_lifecycle_defaultscope” sample application (from “Lab samples”)

1. Open managedbean_lifecycle_defaultscope NetBeans project.

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

2. Build and run managedbean_lifecycle_defaultscope project.

  • Right-click managedbean_lifecycle_defaultscope project and select Run.
  • Observe that the browser gets displayed.

Figure-5.11


Figure-5.12


Figure-5.13


Figure-5.14

(5.2) Study code

1. Greeting.java

package mypackage;

import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@ManagedBean
public class Greeting {

public String greet(String name) {
return “Hello ” + name;
}

@PostConstruct
private void init() {
System.out.println(“\n=======> init() method is called as PostConstruct”);
}

@PreDestroy
private void release() {
System.out.println(“=======> release() method is called as PreDestroy”);
}
}

(5.3) Open, build, and run “managedbean_lifecycle_requestscope” sample application

1. Open managedbean_lifecycle_requestscope NetBeans project.

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

2. Build and run managedbean_lifecycle_requestscope project.

  • Right-click managedbean_lifecycle_requestscope project and select Run.
  • Observe that the browser gets displayed.

Figure-5.31

(5.4) Study code

1. Greeting.java.

package mypackage;

import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.RequestScoped;

@ManagedBean
@RequestScoped
public class Greeting {

public String greet(String name) {
return “Hello ” + name;
}

@PostConstruct
private void init() {
System.out.println(“\n=======> init() method is called as PostConstruct”);
}

@PreDestroy
private void release() {
System.out.println(“=======> release() method is called as PreDestroy”);
}
}

(5.5) Open, build, and run “managedbean_interceptor” sample application

1. Open managedbean_interceptor NetBeans project.

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

2. Build and run managedbean_interceptor project.

  • Right-click managedbean_interceptor project and select Run.
  • Observe that the browser gets displayed.

Figure-5.51

(5.6) Study code

1. Greeting.java

package mypackage;

import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.RequestScoped;
import javax.interceptor.Interceptors;

@ManagedBean
@RequestScoped
@Interceptors(LoggingInterceptor.class)
public class Greeting {

public String greet(String name) {
return “Hello ” + name;
}

@PostConstruct
private void init() {
System.out.println(“\n=======> init() method is called as PostConstruct”);
}

@PreDestroy
private void release() {
System.out.println(“=======> release() method is called as PreDestroy”);
}
}

Greeting.java

2. LoggingInterceptor.java

package mypackage;

import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

// This class will be used as an interceptor.
public class LoggingInterceptor {

private Logger logger = Logger.getLogger(“mypackage”);

@AroundInvoke
public Object logMethod(InvocationContext ic) throws Exception {
logger.info(“——> ” + ic.getTarget().getClass() + “, method name: ” + ic.getMethod().getName());
try {
return ic.proceed();
} finally {
logger.info(“<—— ” + ic.getTarget().getClass() + “, method name: ” + ic.getMethod().getName());
}
}
}

LoggingInterceptor.java

Summary

In this exercise,  you have learned how to use managed bean with lifecycle methods.  You also leraned how to use interceptor with a managed bean.

Exercise 6: Build and run “weld-servlet” sample application

The “weld-servlet” sample application is provided as a sample application from “glassfish-samples”.   The description of this sample application is available from “Context and Dependency Injection And Servlets” blog by Roger Kitain.

  1. Open, build, and run “weld-servlet” sample application
  2. Study the code

(6.1) Open, build, and run “weld-servlet” sample application (from “glassfish-samples”)

1. Open weld-servlet 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/weld directory.
  • Select weld-servlet.
  • Click Open Project.


Figure-6.11

  • Observe that the weld-servlet project node appears under Projects tab window.

2. Build and run weld-servlet project.

  • Right-click weld-servlet project and select Run.
  • Observe that the browser gets displayed.
  • For the User Name field, enter <your name>.
  • For the Password field, enter whatever password of your choice.
  • Click Submit button.

 


Figure-6.12

  • Observe that “Successfully Logged In As: <your name>” message gets displayed at the bottom.


Figure-6.13

(6.2)  Study the code

1. web.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app version=”2.5″ xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”>

<session-config>
<session-timeout>
30
</session-timeout>
</session-config>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

web.xml

2. index.jsp

<%@page contentType=”text/html” pageEncoding=”UTF-8″%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
“http://www.w3.org/TR/html4/loose.dtd”>

<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Weld Servlet Injection</title>
<script type=”text/javascript” src=”resources/ajax.js”>
</script>
<link type=”text/css” rel=”stylesheet” href=”/weld-servlet/resources/stylesheet.css” />
</head>
<body>
<form name=”myForm” method=”POST” action=”LoginServlet”>
<table>
<tbody>
<tr>
<td><span>Login Servlet</span></td>
</tr>
<tr>
<td><span>Powered By Servlet 3.0 and Weld</span></td>
</tr>
</tbody>
</table>
<table height=”30″ style=”font-size: 16px”>
<tr>
<td>Enter any value for user name and password.</td>
</tr>
</table>
<table style=”font-size: 16px”>
<tr>
<td style=”color:red”>*</td>
<td>Denotes required entry.</td>
</tr>
</table>
<table height=”30″>
<table border=”1″ style=”font-size: 18px”>
<tr>
<td>User Name:</td>
<td><input type=”text” name=”username” id=”username” /></td>
<td style=”color:red”>*</td>
</tr>
<tr>
<td>Password:</td>
<td><input type=”password” name=”password” id=”password” /></td>
<td style=”color:red”>*</td>
</tr>
</table>
<table border=”1″>
<tr>
<td colspan=”2″><input type=”button” value=”Submit”  onclick=”ajaxFunction();” /></td>
<td colspan=”2″><input type=”button” value=”Reset”  onclick=”resetFunction();” /></td>
</tr>
</table>
</table>
<table height=”20″>
<tr>
<td><div id=”message” style=”color:red;font-size: 14px”></td>
</tr>
</table>

</form>
</body>
</html>

index.jsp

3. LoginServlet.java

package weldservlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* This Servlet class demonstrates Weld injection.
*/
@WebServlet(name=”LoginServlet”, urlPatterns={“/LoginServlet”})
public class LoginServlet extends HttpServlet {

// BeanManager interface allows a portable extension to interact directly with
// the container. Provides operations for obtaining contextual references for
// beans, along with many other operations of use to portable extensions.
// It is not used in this application.
// Inject Weld Bean Manager.
@Inject BeanManager m;

// Inject The Credentials Weld bean.
@Inject Credentials credentials;

// Inject the Login Weld bean.
@Inject Login login;

/**
* 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 {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();

// Because credentials variable is injected with Credentials object by the container,
// you can use it here without yourself assigning it.
credentials.setUsername(request.getParameter(“username”));
credentials.setPassword(request.getParameter(“password”));

// Because login variable is injected with Login object by the container,
// you can use it here without yourself assigning it.
login.login();

try {
if (login.isLoggedIn()) {
out.println(“Successfully Logged In As: ” + credentials.getUsername());
} else {
out.println(“Login Failed: Check username and/or password.”);
}
} finally {
out.close();
}
}

/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return “Short description”;
}

}

LoginServlet.java

4. Credentials.java.

package weldservlet;

import java.io.Serializable;

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Default;
import javax.inject.Named;

/**
* This is just a simple container class Weld bean for the username
* and password entry values.
*/
@Named
@RequestScoped
@Default
public class Credentials implements Serializable {

private String username = null;

private String password = null;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

}

Credentials.java

5.  Login.java.

package weldservlet;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.inject.Named;

/**
* A simple Weld Bean that performs a login operation with user’s
* credentials.
*/
@Named
@SessionScoped
@Default
public class Login implements Serializable {

// Credential object is already initialized with
// username and password input parameters
// is placed in the request scope object.
@Inject Credentials credentials;

private boolean loggedIn = false;

/**
* This is where you could potentially access a database.
*/
public void login() {
if ((credentials.getUsername() != null &&
credentials.getUsername().trim().length() > 0) &&
(credentials.getPassword() != null &&
credentials.getPassword().trim().length() > 0)) {
loggedIn = true;
}
}

public boolean isLoggedIn() {
return loggedIn;
}

}

Login.java

Summary

In this exercise,  you have played with a sample application that uses dependency injection.


Exercise 7: Build and run “weld-guess” sample application

The description of of this example is provided as part of Java EE 6 tutorial.

  1. Open, build, and run “weld-guess” sample application
  2. Study the code

(7.1) Open, build, and run “weld-guess” sample application (from “glassfish-samples”)

1. Open weld-guess 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/weld directory.
  • Select weld-guess.
  • Click Open Project.
  • Observe that the weld-guess project node appears under Projects tab window.

2. Build and run weld-guess project.

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


Figure-7.11


Figure-7.12


Figure-7.13

(7.2)  Study the code

1. index.html

<html>
<head>
<meta http-equiv=”Refresh” content=”0; URL=home.jsf”>
</head>
</html>

index.html

2. home.xhtml

<!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”
xmlns:f=”http://java.sun.com/jsf/core”>

<h:head>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″ />
<title>JSF 2.0 Weld Example</title>
</h:head>

<h:body>
<h:form id=”NumberGuessMain”>
<h:panelGrid styleClass=”title-panel”>
<h:outputText value=”Guess Number” styleClass=”title-panel-text”/>
<h:outputText value=”Powered By JavaServer Faces 2.0 and Weld” styleClass=”title-panel-subtext”/>
</h:panelGrid>

<div style=”color: black; font-size: 24px;”>
I’m thinking of a number between <span style=”color: blue”>#{game.smallest}</span> and <span style=”color: blue”>#{game.biggest}</span>. You have <span style=”color: blue”>#{game.remainingGuesses}</span> guesses.
</div>

<h:panelGrid border=”1″ columns=”5″ style=”font-size: 18px;”>
Number:
<h:inputText id=”inputGuess” value=”#{game.guess}” required=”true” size=”3″ disabled=”#{game.number eq game.guess}”
validator=”#{game.validateNumberRange}”>
</h:inputText>
<h:commandButton id=”GuessButton” value=”Guess” action=”#{game.check}” disabled=”#{game.number eq game.guess}”/>
<h:commandButton id=”RestartButton” value=”Reset” action=”#{game.reset}” immediate=”true” />
<h:outputText id=”Higher” value=”Higher!” rendered=”#{game.number gt game.guess and game.guess ne 0}” style=”color: red”/>
<h:outputText id=”Lower” value=”Lower!” rendered=”#{game.number lt game.guess and game.guess ne 0}” style=”color: red”/>
</h:panelGrid>

<div style=”color: red; font-size: 14px;”>
<h:messages id=”messages” globalOnly=”false”/>
</div>

<h:outputStylesheet name=”stylesheet.css” />
</h:form>
</h:body>

</html>

3. Game.java.

package weldguess;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Named;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

@Named
@SessionScoped
public class Game implements Serializable
{
private static final long serialVersionUID = 1L;

private int number;

private int guess;
private int smallest;

// Inject an object which is qualified with
// @MaxNumber qualifier.
@MaxNumber @Inject
private int maxNumber;

private int biggest;
private int remainingGuesses;

// Inject an object which is qualified with
// @Random qualifier.
@Random @Inject
Instance<Integer> randomNumber;

public Game()
{
}

public int getNumber()
{
return number;
}

public int getGuess()
{
return guess;
}

public void setGuess(int guess)
{
this.guess = guess;
}

public int getSmallest()
{
return smallest;
}

public int getBiggest()
{
return biggest;
}

public int getRemainingGuesses()
{
return remainingGuesses;
}

public String check() throws InterruptedException
{
if (guess>number)
{
biggest = guess – 1;
}
if (guess<number)
{
smallest = guess + 1;
}
if (guess == number)
{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(“Correct!”));
}
remainingGuesses–;
return null;
}

@PostConstruct
public void reset()
{
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
this.biggest = maxNumber;
this.number = randomNumber.get();
}

public void validateNumberRange(FacesContext context,  UIComponent toValidate, Object value)
{
if (remainingGuesses <= 0)
{
FacesMessage message = new FacesMessage(“No guesses left!”);
context.addMessage(toValidate.getClientId(context), message);
((UIInput)toValidate).setValid(false);
return;
}
int input = (Integer) value;

if (input < smallest || input > biggest)
{
((UIInput)toValidate).setValid(false);

FacesMessage message = new FacesMessage(“Invalid guess”);
context.addMessage(toValidate.getClientId(context), message);
}
}
}

Game.java

4. Generator.java.

package weldguess;

import java.io.Serializable;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

@ApplicationScoped
public class Generator implements Serializable
{

private static final long serialVersionUID = -7213673465118041882L;

private java.util.Random random = new java.util.Random( System.currentTimeMillis() );

private int maxNumber = 100;

java.util.Random getRandom()
{
return random;
}

@Produces @Random
int next() {
return getRandom().nextInt(maxNumber);
}

@Produces @MaxNumber int getMaxNumber()
{
return maxNumber;
}

}

Generator.java

5.  MaxNumber.java.

package weldguess;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

// Define @MaxNumber qualifier annotation
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface MaxNumber
{

}

MaxNumber.java

6. Random.java.

package weldguess;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

// Define @Random qualifier annotation
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface Random
{

}

Random.java

Summary

In this exercise,  you have played with a sample application that uses dependency injection.

Exercise 8: Event

Beans may produce and consume events. This facility allows beans to interact in a completely decoupled fashion, with no
compile-time dependency between the interacting beans. Most importantly, it allows stateful beans in one architectural tier
of the application to synchronize their internal state with state changes that occur in a different tier.

An event comprises:

  • A Java object—the event object
  • A (possibly empty) set of instances of qualifier types—the event qualifiers

The event object acts as a payload, to propagate state from producer to consumer. The event qualifiers act as topic selectors,
allowing the consumer to narrow the set of events it observes.

An observer method acts as event consumer, observing events of a specific type—the observed event type—with a specific
set of qualifiers—the observed event qualifiers. An observer method will be notified of an event if the event object is assignable
to the observed event type, and if all the observed event qualifiers are event qualifiers of the event.

  1. Open, build, and run “weld-servlet-event” sample application
  2. Study the code
  3. Add more event handlers
  4. Fire @Admin qualified event

(8.1) Open, build, and run “weld-servlet-event” sample application

1. Open weld-servlet-event 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_injection/samples directory.
  • Select weld-servlet-event.
  • Click Open Project.
  • Observe that the weld-servlet-event project node appears under Projects tab window.

2. Build and run weld-servlet-event project.

  • Right-click weld-servlet-event project and select Run.
  • Browser gets displayed.
  • For the User Name field, enter sangshin (or whatever user name of your choce).
  • For the Password field, enter whatever password of your choice.
  • Click Submit button.

 


Figure-8.11

  • Observe that “Successfully Logged In As: <your user name>” message gets displayed at the bottom.


Figure-8.12

3. Observe that the event handler is invoked.

  • Click GlassFish v3 Domain tab under Outout window.
  • Observe that “INFO: —-afterLogin() method is called, ..” message is displayed.


Figure-8.13

(8.2) Study code

1. Login.java

package weldservlet;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.inject.Named;

/**
* A simple Weld Bean that performs a login operation with user’s
* credentials.
*/
@Named
@SessionScoped
@Default
public class Login implements Serializable {

@Inject
Credentials credentials;

// Inject LoggedEvent
@Inject
@Any
Event<LoggedInEvent> loggedInEvent;

private boolean loggedIn = false;

/**
* This is where you could potentially access a database.
*/
public void login() {
if ((credentials.getUsername() != null
&& credentials.getUsername().trim().length() > 0)
&& (credentials.getPassword() != null
&& credentials.getPassword().trim().length() > 0)) {
loggedIn = true;

// Fire an event when successful login
loggedInEvent.fire(new LoggedInEvent(credentials.getUsername()));
}
}

public boolean isLoggedIn() {
return loggedIn;
}

// This methog gets invoked when LoggedInEvent is fired
public void afterLogin(@Observes LoggedInEvent event) {
System.out.println(“—-afterLogin() method is called, event = ” + event);
}
}

Login.java

2. LoggedInEvent.java

package weldservlet;

public class LoggedInEvent {
private String user;

public LoggedInEvent(String user) {
this.user = user;
}
}

LoggedInEvent.java

(8.3) Add more event handlers

In this step, you are going to add two more event handlers.   Just to leave the existing application as it is, a new project called weld-servlet-event-qualifier is createed by copying weld-servlet-event.

1.  Add Admin.java.  This is to define @Admin qualifier marker annotation.

package weldservlet;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface Admin
{

}


Figure-8.31

2. Modify Login.java as shown below.  The modification is to add two extra event handlers.  The code fragments that need to be added are highlighted in bold and red-colored font.

package weldservlet;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.inject.Named;

/**
* A simple Weld Bean that performs a login operation with user’s
* credentials.
*/
@Named
@SessionScoped
@Default
public class Login implements Serializable {

@Inject
Credentials credentials;

// Inject LoggedEvent
@Inject
@Any
Event<LoggedInEvent> loggedInEvent;
private boolean loggedIn = false;

/**
* This is where you could potentially access a database.
*/
public void login() {
if ((credentials.getUsername() != null
&& credentials.getUsername().trim().length() > 0)
&& (credentials.getPassword() != null
&& credentials.getPassword().trim().length() > 0)) {
loggedIn = true;

// Fire an event when successful login
loggedInEvent.fire(new LoggedInEvent(credentials.getUsername()));
}
}

public boolean isLoggedIn() {
return loggedIn;
}

// This methog gets invoked when LoggedInEvent is fired
public void afterLogin(@Observes LoggedInEvent event) {
System.out.println(“—-afterLogin() method is called, event = ” + event);
}

// Capture any event (same as above)
public void afterAnyLogin(@Observes @Any LoggedInEvent event) {
System.out.println(“—-afterAnyLogin() method is called, event = ” + event);
}

// Capture only @Admin qualified event
public void afterAdminLogin(@Observes @Admin LoggedInEvent event) {
System.out.println(“—-afterAdminLogin() method is called, event = ” + event);
}
}

Login.java


Figure-8.32

3. Build and run the application.

  • Right-click weld-servlet-event-qualifier project and select Run.
  • Browser gets displayed.
  • For the User Name field, enter sangshin (or whatever user name of your choce).
  • For the Password field, enter whatever password of your choice.
  • Click Submit button.
  • Observe that “Successfully Logged In As: <your user name>” message gets displayed at the bottom.

4. Observe that the two event handlers are invoked.

  • Click GlassFish v3 Domain tab under Outout window.
  • Observe that “INFO: —-afterLogin() method is called, ..” message is displayed.
  • Observe that “INFO: —-afterAnyLogin() method is called, ..” message is displayed.


Figure-8.33

(8.4) Fire qualified event

In this step, you are going to fire qualified event.

1.  Modify Login.java as shown below.  The modification is to fire @Admin qualified event.

package weldservlet;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.inject.Named;

/**
* A simple Weld Bean that performs a login operation with user’s
* credentials.
*/
@Named
@SessionScoped
@Default
public class Login implements Serializable {

@Inject
Credentials credentials;

// Inject LoggedEvent
@Inject
@Admin
Event<LoggedInEvent> loggedInEvent;

private boolean loggedIn = false;

/**
* This is where you could potentially access a database.
*/
public void login() {
if ((credentials.getUsername() != null
&& credentials.getUsername().trim().length() > 0)
&& (credentials.getPassword() != null
&& credentials.getPassword().trim().length() > 0)) {
loggedIn = true;

// Fire an event when successful login
loggedInEvent.fire(new LoggedInEvent(credentials.getUsername()));
}
}

public boolean isLoggedIn() {
return loggedIn;
}

// This methog gets invoked when LoggedInEvent is fired
public void afterLogin(@Observes LoggedInEvent event) {
System.out.println(“—-afterLogin() method is called, event = ” + event);
}

// Capture any event (same as above)
public void afterAnyLogin(@Observes @Any LoggedInEvent event) {
System.out.println(“—-afterAnyLogin() method is called, event = ” + event);
}

// Capture only @Admin qualified event
public void afterAdminLogin(@Observes @Admin LoggedInEvent event) {
System.out.println(“—-afterAdminLogin() method is called, event = ” + event);
}
}

Login.java

2. Build and run the application.
  • Right-click weld-servlet-event-qualifier project and select Run.
  • Browser gets displayed.
  • For the User Name field, enter sangshin (or whatever user name of your choce).
  • For the Password field, enter whatever password of your choice.
  • Click Submit button.
  • Observe that “Successfully Logged In As: <your user name>” message gets displayed at the bottom.

3. Observe that the two event handlers are invoked.

  • Click GlassFish v3 Domain tab under Outout window.
  • Observe that “INFO: —-afterAdminLogin() method is called, ..” message is also displayed along with the other two.  This shows that afterAdminLogin(@Observes @Admin LoggedInEvent event) event handler gets called only when @Admin qualified event is fired.


Figure-8.41

Solution: The solution up to this step is captured as “ready to open and build” NetBeans project as weld-servlet-event-qualifer project under <LAB_UNZIPPED_DIRECTORY>/javaee6_injection/solutions directory.

Summary

In this exercise,  you have learned how beans may produce and consume events.  You also learned how to use qualifer.

Homework Exercise

 

1. The first part of homework is to modify inject_qualifier project you worked on in Exercise 2 above as following.  (You might want to create a new project by copying inject_qualifier project.  You can name the newly copied project in any way you want.  Here it is referred to as my_inject_qualifier.)

  • Goal: Exercising qualifier
    • Define another qualifier called @SemiFormal.
    • Define SemiFormalGreeting class with @SemiFormal annotation
    • Modify HelloServlet class to inject @SemiFormal greeting object.

2. The second part of homework is to modify inject_scope_conversation project you worked on in Exercise 3 above as following.  (You might want to create a new project by copying inject_scope_conversation project.  You can name the newly copied project in any way you want.  Here it is referred to as my_inject_scope_conversation.)  – If you already submitted homework or would use to use a single project as a base as in the original homework, that is perfectly fine as well.

  • Goal: Exercising scope
    • Create a bean called my_application_scope_bean with application scope, which has a field called my_application_scope_counter.  Use the my_application_scope_counter to keep track of how many times the Say Hello button was clicked.
    • Display the value of my_application_scope_counter.
    • Create another bean called my_conversation_scope_bean with conversation scope, which has a field called my_conversation_scope_counter.  Now every time my_application_scope_counter hits multiple of 5, for example, 5, 10, 15, …, start a conversation.  Every time my_application_scope_counter hits multiple of 5 plus 4, for example, 9, 14, 19, …, stop the conversation.
    • The my_conversation_scope_counter gets incremented each time the Say Hello button is clicked but starting from a new random number whenever a new coversation scope gets started.
    • Display the value of my_conversation_scope_counter.
  • Goal: Exercising event handling
    • Every time my_application_scope_bean hits the prime numbers up to 20, fire a event.  The event handler should display a message “Prime number x is hit!”. This message can be displayed either HTML response message or system log.

Hint: Given that we have not covered how to use JSF/Facelets yet, the following hint shows how to display things in the index.xhtml file – make sure you copy resources directory and template.xhtml as well as seen in inject_scope_conversation project.  The “Prime number x is hit!” can be printed out on system log through sysem.out.println(…);

<?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”>
<ui:composition template=”/template.xhtml”>

<ui:define name=”title”>Simple Greeting</ui:define>
<ui:define name=”head”>Simple Greeting</ui:define>
<ui:define name=”content”>
<h:form id=”greetme”>
<p><h:outputLabel value=”Enter your name: ” for=”name”/>
<h:inputText id=”name” value=”#{printer.name}”/></p>
<p><h:commandButton value=”Say Hello” action=”#{printer.createSalutation}”/></p>
<p><h:commandButton value=”Start conversation” action=”#{printer.startConversation}”/></p>
<p><h:commandButton value=”End conversation” action=”#{printer.endConversation}”/></p>
<p><h:outputText value=”printer.salutation = #{printer.salutation}”/> </p>
<p><h:outputText value=”printer.old_salutation = #{printer.old_salutation}”/> </p>
<p><h:outputText value=”myConversationStatus.conversationSattus = #{myConversationStatus.conversationSattus}”/> </p>
<p><h:outputText value=”my_application_scope_bean.my_application_scope_counter = #{my_application_scope_bean.my_application_scope_counter}”/> </p>
<p><h:outputText value=”my_conversation_scope_bean.my_conversation_scope_counter = #{my_conversation_scope_bean.my_conversation_scope_counter}”/> </p>
</h:form>
</ui:define>

</ui:composition>
</html>

2. Send the following files to javaee6-homeworks@sun.com with Subject as homework_javaee6_injection.
  • Zip files of the the my_inject_qualifier and my_inject_scope_conversation NetBeans projects.  (Someone else should be able to open and run them 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_inject_qualifier directory> (assuming you named your project as my_inject_qualifier)
    • jar cvf my_inject_qualifier.zip my_inject_qualifier (my_inject_qualifier should contain nbproject directory)
  • Captured output screens  – name it as homework_javaee6_injection1.gif orhomework_javaee6_injection1.jpg (or homework_javaee6_injection1.<whatver graphics format>) for the first part and homework_javaee6_injection2.gif orhomework_javaee6_injection2.jpg (or homework_javaee6_injection2.<whatver graphics format>)
    • Any screen capture that shows that your program is working is good enough.

 

 

 

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.