In this chapter we will create a SecurityApplication
built around a simple Voucher entity to persist travel information. This is a simplified version of an application that allows a user to submit a voucher and for a manager to approve or disapprove it. The voucher entity itself will hold only minimal information.
The illustration of security will be based on a series of classes:
Voucher
An entity holding travel-related informationVoucherFacade
A facade class for the entityAbstractFacade
The base class of the VoucherFacade
class as described in Chapter 4, Creating an entity facade recipeVoucherManager
A class used to manage vouchers and where most of the security techniques will be demonstratedSecurityServlet
A servlet used to drive the demonstrationsAll of these classes will be members of the packt
package in the EJB module except for the servlet which will be placed in the servlet
package of the WAR module.
Create a Java EE application called SecurityApplication
with an EJB and a WAR module. Add a packt
package to the EJB module and an entity called Voucher
to the package.
Add five private instance variables to hold a minimal amount of travel information: name, destination, amount, approved
, and an id
. Also, add a default and a three argument constructor to the class to initialize the name, destination
, and amount
fields. The approved
field is also set to false
. The intent of this field is to indicate whether the voucher has been approved or not. Though not shown below, also add getter and setter methods for these fields. You may want to add other methods such as a toString
method if desired.
@Entity public class Voucher implements Serializable { private String name; private String destination; private BigDecimal amount; private boolean approved; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; public Voucher() { } public Voucher(String name, String destination, BigDecimal amount) { this.name = name; this.destination = destination; this.amount = amount; this.approved = false; } ... }
Next, add an AbstractFacade
class described in Chapter 4, EJB Persistence and a VoucherFacade
class derived from it. The VoucherFacade
class is shown below. As with other facade classes found in previous chapters, the class provides a way of accessing an entity manager and the base class methods of the AbstractFacade
class.
@Stateless public class VoucherFacade extends AbstractFacade<Voucher> { @PersistenceContext(unitName = "SecurityApplication-ejbPU") private EntityManager em; protected EntityManager getEntityManager() { return em; } public VoucherFacade() { super(Voucher.class); } }
Next, add a stateful EJB called VoucherManager
. Inject an instance of the VoucherFacade
class using the @EJB annotation. Also add an instance variable for a Voucher
. We need a createVoucher
method that accepts a name, destination, and amount arguments, and then creates and subsequently persists the Voucher
. Also, add get methods to return the name, destination, and amount of the voucher.
@Stateful public class VoucherManager { @EJB VoucherFacade voucherFacade; Voucher voucher; public void createVoucher(String name, String destination, BigDecimal amount) { voucher = new Voucher(name, destination, amount);voucherFacade.create(voucher); } public String getName() { return voucher.getName(); } public String getDestination() { return voucher.getDestination(); } public BigDecimal getAmount() { return voucher.getAmount(); } ... }
Next add three methods:
submit
This method is intended to be used by an employee to submit a voucher for approval by a manager. To help explain the example, display a message showing when the method has been submitted. approve
This method is used by a manager to approve a voucher. It should set the approved
field to true
and return true
. reject
This method is used by a manager to reject a voucher. It should set the approved
field to false
and return false
.@Stateful public class VoucherManager { ... public void submit() { System.out.println("Voucher submitted"); } public boolean approve() { voucher.setApproved(true); return true; } public boolean reject() { voucher.setApproved(false); return false; } }
To complete the application framework, add a package called servlet
to the WAR module and a servlet called SecurityServlet
to the package. Use the @EJB annotation to inject a VoucherManager
instance field into the servlet.
In the try block of the processRequest
method, add code to create a new voucher and then use the submit
method to submit it. Next, display a message indicating the submission of the voucher.
public class SecurityServlet extends HttpServlet { @EJB VoucherManager voucherManager; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { voucherManager.createVoucher("Susan Billings", "SanFrancisco", BigDecimal.valueOf(2150.75)); voucherManager.submit(); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet SecurityServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h3>Voucher was submitted</h3>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } } ... }
Execute the SecurityServlet
. Its output should appear as shown in the following screenshot:
In the Voucher
entity, notice the use of BigDecimal
for the amount
field. This java.math
package class is a better choice for currency data than float
or double
. Its use avoids problems which can occur with rounding as discussed in Chapter 12, How to support currency recipe. The @GeneratedValue annotation, used with the id
field, is discussed in Chapter 4, Creating an entity facade recipe.
In the VoucherManager
class, notice the injection of the stateless VoucherFacade
session EJB into a stateful VoucherManager
EJB. Each invocation of a VoucherFacade
method may result in the method being executed against a different instance of VoucherManager
. This is the correct use of a stateless session EJB. The injection of a stateful EJB into a stateless EJB is not recommended.
3.149.240.196