My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

miercuri, 29 iulie 2015

JSF and EJBs Facade design pattern sample

Facade is a Structural Design Pattern with the following object structural:


The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as “providing a unified interface to a set of interfaces in a subsystem.

Mainly the Facade design pattern is meant to hide a complex code (as a system/subsystem code) and to provide an unique entry point for it via an interface. There are several purposes for implementing this design pattern, and one of them is for providing a rough‐grained access to available services. Services are combined in a business logic, and form a "unit of work" easy to access.


For example, let's suppose that we want to find out the final price of a product based on the following logic:

·         check the product availability and get the product initial price
·         check the discount availability and apply a discount
·         check the delivery availability and apply delivery taxes

For each of these tasks we have a separate stateless session bean, as follows (these are the EJBs services to combine):

·         check the product availability and get the product initial price - InventoryProduct:

@Stateless
public class InventoryProduct {

 public boolean productIsAvailable(String product) {
  // some business logic here
  return true;
 }

 public int productCost(String product) {
  // some business logic here
  return 120; // initial product cost is $120
 }
}

·         check the discount availability and apply a discount - DiscountProduct:

@Stateless
public class DiscountProduct {

 public boolean discountPeriodOfTheYear(){
  // some business logic here
  return true;
 }

 public int applyDiscount(String product){
  // some business logic here
  return 100; // after the discount the product price is $100
 }
}

·         check the delivery availability and apply delivery taxes - DeliveryProduct:

@Stateless
public class DeliveryProduct {

 public boolean freeDeliveryPeriodOfTheYear() {
  // some business logic here
  return false;
 }

 public int taxDelivery(int price){
  // some business logic here
  return 103; // for $100 we add $3 delivery costs
 }
}

Further these three services should be used to create the below business logic (this is the "unit of work"):

public int orderProduct(String product) {
 if (inventoryProduct.productIsAvailable(product)) {
     int price = inventoryProduct.productCost(product);
     int discount_price = discountProduct.discountPeriodOfTheYear() ? discountProduct.applyDiscount(product) : price;
     int final_price = deliveryProduct.freeDeliveryPeriodOfTheYear() ? discount_price : deliveryProduct.taxDelivery(discount_price);

     return final_price;
 }
 return -1;
}

We take this method and place it in another stateless session bean named, FacadeProduct. Basically, this bean is the design pattern implementation. Here, we inject our services and define the orderProduct(), so when the client order a product, he knows nothing about our subsystem:

@Stateless
public class FacadeProduct {

 @Inject
 private InventoryProduct inventoryProduct;

 @Inject
 private DeliveryProduct deliveryProduct;

 @Inject
 private DiscountProduct discountProduct;

 public int orderProduct(String product) {
  if (inventoryProduct.productIsAvailable(product)) {
      int price = inventoryProduct.productCost(product);
      int discount_price = discountProduct.discountPeriodOfTheYear() ? discountProduct.applyDiscount(product) : price;
      int final_price = deliveryProduct.freeDeliveryPeriodOfTheYear() ? discount_price : deliveryProduct.taxDelivery(discount_price);

      return final_price;
  }
  return -1;
 }
}

Now, the Facade design pattern was implemented and we simply inject it in a CDI managed bean:

Named
@RequestScoped
public class ProductBean implements Serializable {

 private int price;

 @Inject
 FacadeProduct facadeProduct;

 public int getPrice() {
  return price;
 }

 public void orderProductAction(String product) {
  price = facadeProduct.orderProduct(product);
 }
}

As you can see, the managed bean is not aware of the code complexity behind the #orderProduct() call and it doesn't contain complex business logic (it is a bad practice to define in this bean our "unit of work" - in some cases, this can be pretty large and complex).

A dummy JSF page can serve as a starting point:

<h:form>
 Price: $#{productBean.price}
 <h:commandButton value="'Nike LUNAR' Product Order" action="#{productBean.orderProductAction('Nike LUNAR')}" />
</h:form>

The complete code is available on GitHub.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors