Search code examples
jpaviewjsf-2ejbstateless

how to navigate from one view to next in a JSF2/JPA/stateless EBJs (jsf managed controllers) and retain data


I have a web app using JSF2 with JPA Entities, Stateless ejb session beans as my facade/ejb objects, and managed beans (request and view scoped) as controllers exposing business methods, managed controllers are pulling data from the injected stateless session beans.

but i am confused how to navigate and retain data accross views in my controllers in this environment, for example:

I have a jsf2 view page (departmentView.xhtml) that displays a list of Department objects and each row has an edit item. Clicking edit I want to load a new page and display a list or Employee's for that department on the new page, so i invoke the Employee controller passing it the selected Department

action="#{employeeController.getEmployeeListForADepartment(ithDepartment)}" 

here is a snippet of my departmentView.xhtml

    <h:dataTable id="table" value="#{departmentController.departmentList}" 
            var="ithDepartment">
...
<h:column>              
<h:commandLink id="editId" value="Edit"
action="#{employeeController.getEmployeeListForADepartment(ithDepartment)}" />
</h:column>

and my employeeController is defined as

ManagedBean(name = "employeeController")
@ViewScoped
public class EmployeeController implements Serializable {
   ...
private List<Employee> employeeList = new ArrayList<Employee>();
   ...      

@EJB
private com.ejb.session.EmployeeFacade ejbEmployeeFacade;    
   ...

public List<Employee> getEmployeeListForADepartment(Department dept) 
{
    if(employeeList==null || employeeList.isEmpty())
          employeeList = ejbEmployeeFacade.findEmployeesByDepartment(dept);  

// now i want to navigate to the employee view showing these employees for the
// selected department.
// but this navigation below triggers creating a new EmployeeController 
// and i lose my employeeList 
    return "employeeView";
}

i really want to avoid using jsf session scope, and believe there is a way to do this, just not reading about it in any of my jsf/ejb books.

thinking outloud, maybe don't have EmployeeController.getEmployeeListForADepartment(..) do a lookup, just create a parameter from the department id and pass that along via return "employeeView?departmentId=X"; and have constructor then do a lookup if the id is present?

can somehelp me with the proper way to implement this in EJB/JSF2 environment

thanks


Solution

  • Use a simple GET <h:link> in the source view to pass the department ID and a <f:viewParam> in the target view to convert and set the department.

    E.g.

    <h:link id="editId" value="Edit" outcome="employeeView">
        <f:param name="departmentId" value="#{ithDepartment.id}" />
    </h:link>
    

    with

    <f:metadata>
        <f:viewParam name="id" value="#{editDepartmentBean.department}"
            converter="#{departmentConverter}" converterMessage="Bad request. Unknown department."
            required="true" requiredMessage="Bad request. Please use a link from within the system." />
    </f:metadata>
    

    and

    @ManagedBean
    @ViewScoped
    public class EditDepartmentBean {
    
        private Department department;
    
        // ...
    }
    

    See also: