In this tutorial, we will understand how to use MVC Pattern when developing JSF Applications.
Agenda:
1) @ManagedBean: The Model
2) @ManagedProperty: The injection of model into controller and achieve loose coupling
3) @SessionScoped: The controller
4) Composite Views: Create reusable view components
5) The view page using primefaces and AJAX
Directory Structure:
1) Let’s get Start with Model Layer:
Interface:
public interface CalculatorIntf {
public int add(int a, int b);
public int sub(int a, int b);
}
Implementing Class:
@ManagedBean(name="calc")
@SessionScoped
public class Calculator implements CalculatorIntf{
@Override
public int add(int a, int b) { return a + b; }
@Override
public int sub(int a, int b) { return a - b; }
}
And the Value Object Class:
public class CalculatorVO {
private int a;
private int b;
private int c;
// getters and setters for a, b, c
}
2nd And 3rd steps)The controller Class with Dependency Injection
@ManagedBean
@SessionScoped
public class CalculatorController {
public void add() { calculatorVO.setC(calculatorIntf.add(calculatorVO.getA(), calculatorVO.getB())); }
public void sub() { calculatorVO.setC(calculatorIntf.sub(calculatorVO.getA(), calculatorVO.getB())); }
public CalculatorIntf getCalculatorIntf() { return calculatorIntf; }
public void setCalculatorIntf(CalculatorIntf calculatorIntf) { this.calculatorIntf = calculatorIntf; }
public CalculatorVO getCalculatorVO() {
if (calculatorVO == null) { calculatorVO = new CalculatorVO(); } return calculatorVO;
}
private CalculatorVO calculatorVO;
@ManagedProperty(value = "#{calc}") private CalculatorIntf calculatorIntf;}
@SessionScoped
public class CalculatorController {
public void add() { calculatorVO.setC(calculatorIntf.add(calculatorVO.getA(), calculatorVO.getB())); }
public void sub() { calculatorVO.setC(calculatorIntf.sub(calculatorVO.getA(), calculatorVO.getB())); }
public CalculatorIntf getCalculatorIntf() { return calculatorIntf; }
public void setCalculatorIntf(CalculatorIntf calculatorIntf) { this.calculatorIntf = calculatorIntf; }
public CalculatorVO getCalculatorVO() {
if (calculatorVO == null) { calculatorVO = new CalculatorVO(); } return calculatorVO;
}
private CalculatorVO calculatorVO;
@ManagedProperty(value = "#{calc}") private CalculatorIntf calculatorIntf;}
4) The Composite View component
<?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:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html">
<cc:attribute name="a" required="true" />
<cc:attribute name="b" required="true" />
<cc:attribute name="c" required="true" />
<cc:attribute name="add" required="true" method-signature="void add()"/>
<cc:attribute name="subtract" required="true" method-signature="void sub()"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<p:panel header="Maths Operations">
<p:panelGrid columns="2">
<h:outputText value="Num 1: " />
<h:inputText value="#{cc.attrs.a}">
<p:ajax event="blur" />
</h:inputText>
<h:outputText value="Num 2: " />
<h:inputText value="#{cc.attrs.b}">
<p:ajax event="blur" />
</h:inputText>
<h:commandButton value="Add" >
<p:ajax event="click" listener="#{cc.attrs.add}" update="result" />
</h:commandButton>
<h:commandButton value="Sub" >
<p:ajax event="click" listener="#{cc.attrs.subtract}" update="result" />
</h:commandButton>
<h:outputText value="Result: "/>
<h:outputText id="result" value="#{cc.attrs.c}"/>
</p:panelGrid>
</p:panel>
</cc:implementation>
</html>
Note: Do remember that <cc:attribute name="sub" .... ... /> will not work. so made it subtract
5) The View Page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:m="http://java.sun.com/jsf/composite/com/shared">
<h:head>
<title>Calculator App</title>
</h:head>
<h:body>
<h:form>
<m:mathsComponent a="#{calculatorController.calculatorVO.a}"
b="#{calculatorController.calculatorVO.b}"
c="#{calculatorController.calculatorVO.c}"
add="#{calculatorController.add}"
subtract="#{calculatorController.sub}"/>
</h:form>
</h:body>
</html>
Conclusion:
1) Controllers can depend upon interface references than direct implementations with the help of @ManagedProperty Attribute. Thus making our application Loosely coupled.
2) Do not use sub as attribute, because sub seems to be a reserved word in JSF
3) Creating composites will help us reuse the components at many places.