1
votes

I have an issue with view scoped bean. I know it's common question but I didn't get right answer. I have a datatable that is responsible for showing search results upon user entered search some criteria. Here is xhtml:

<html   xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns="http://www.w3.org/1999/xhtml"

    xmlns:p="http://primefaces.org/ui">


<h:panelGroup id ="adminReportLogList">

<p:dataTable value="#{adminLogView.lazyModelReport}" var="model" id="reportLogList" lazy="true" paginator="true" rows="20" paginatorAlwaysVisible="false" paginatorPosition="bottom" emptyMessage="emppty list" styleClass="dtable" style="table-layout: fixed; width: 100%"
             paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15,20">

    <p:column headerText="Report number" sortBy="#{model.reportNumber}">
        <h:outputText value="#{model.reportLogId}"/>
    </p:column>
    <p:column headerText="Report date" sortBy="#{model.reportDate}">
            <h:outputText value="#{model.reportDate}">
                <f:convertDateTime pattern="yyyy/MM/dd hh:mm:ss"/>
            </h:outputText>
    </p:column>
    <p:column headerText="Search date" sortBy="#{model.searchLogId.searchDate}">
        <h:outputText value="#{model.searchLogId.searchdate}">
                <f:convertDateTime pattern="yyyy/MM/dd hh:mm:ss"/>
            </h:outputText>
    </p:column>
    <p:column headerText="User name" sortBy="#{model.searchLogId.loginLogId.username}">
        <h:outputText value="#{model.searchLogId.loginLogId.username}"/>
    </p:column>
    <p:column headerText="Customer number" sortBy="#{model.customerId}">
        <h:outputText value="#{model.customerId.registernumber}"/>
    </p:column>
    <p:column headerText="Customer name" sortBy="#{model.customerId}">
        <h:outputText value="#{model.customerId.name}"/>
    </p:column>
</p:dataTable>

</h:panelGroup>
<br/>

// SEARCH PANEL
<p:panel>
    <h:panelGrid columns="3" styleClass="insGrid" id="reportLogSearchPanel">
        <h:outputText value="User: "/>
        <p:inputText id="reportLogSearchByUserName" value="#{adminLogView.searchUserName}">
            <p:watermark for="reportLogSearchByUserName" value ="Customer name"/>
        </p:inputText>
        <h:message for="reportLogSearchByUserName" id="msgReportLogSearchByUserName" styleClass="errorMessage"/>

        <h:outputText value="Customer id number: "/>
        <p:inputText id="reportLogSearchByCustomerName" value="#{adminLogView.searchCustomerName}">
            <p:watermark for="reportLogSearchByCustomerName" value="Customer id number"/>
        </p:inputText>
        <h:message for="reportLogSearchByCustomerName" id="msgReportLogSearchBySearchDate" styleClass="errorMessage"/>

        <h:outputText value="Report date "/>
        <p:inputText id="reportLogSearchByReportDate" value="#{adminLogView.searchReportDate}">
            <p:watermark for="reportLogSearchByReportDate" value="Report date YYYY/MM/DD"/>
        </p:inputText>
        <h:message for="reportLogSearchByReportDate" id="msgReportLogSearchByReportDate" styleClass="errorMessage"/>

        <h:panelGroup/>
        <h:commandButton value="Search" styleClass="btn" action="#{adminLogView.searchReport()}">
            <f:ajax render =":form:adminReportLogList :form:reportLogList" execute=":form:reportLogSearchPanel"/>
        </h:commandButton>

    </h:panelGrid>

</p:panel>

which is used in tag in another xhtml which is: /I think it's not cause in this case/

<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./../templates/admin_main.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui">

    <ui:define name="content">
        <h:panelGroup id="include">
        <ui:include src="#{adminLogView.page}.xhtml"/>
        </h:panelGroup>
    </ui:define>

</ui:composition>

Here is my bean

@Named(value = "adminLogView")
@ViewScoped
public class AdminLogView implements Serializable{
    @EJB
    private LogServiceLocal logService;
    private List<Reportlog> ReportLogList;

    String page = "reportLog";
    LazyDataModel<Reportlog> lazyModelReport;
    LazyDataModel<Loginlog>  lazyModelLogin;
    LazyDataModel<Searchlog> lazyModelSearch;

    String searchCustomerName;
    String searchUserName;
    String searchReportDate;


    @PostConstruct
    public void init(){

        this.lazyModelReport = new LazyReportLogDataModel(this.logService);
    }

    public void searchReport(){
        Map<String, String> filter = new HashMap<String, String>();
        if(this.searchCustomerName != null && !this.searchCustomerName.isEmpty())
            filter.put("customerName", this.searchCustomerName);
        if(this.searchReportDate != null && !this.searchReportDate.isEmpty())
            filter.put("reportDate", this.searchReportDate);
        if(this.searchUserName != null && !this.searchUserName.isEmpty())
            filter.put("userName", this.searchUserName);



        this.lazyModelReport.load(0, 30, null, SortOrder.UNSORTED, filter);

    }
}

When we navigate to a page above then @postConstruct method called multiple times, even with sessionScoped. Even when we click search Button in same view, bean is initialized again. Only RequestScope works fine. Is there I misunderstand or forgot. PS. Thanks in advance.

2

2 Answers

2
votes

Do you have the correct SessionScoped? javax.enterprise.context.SessionScoped

Do you have Myfaces CODI or any other adapter on the classpath? Otherwise @ViewScoped has undocumented behavior since it is a JSF-2 scope.

If you have the correct @SessionScoped the behavior noted is completely unknown problem for me at least.

Also:

@Named(value = "adminLogView")

the value you give here is what it would default to. Might as well skip setting value like that.

Good luck

2
votes

@javax.faces.bean.ViewScoped can't work with CDI. for that reason you need to use SeamFaces or MyFaces CODI to benefit from the viewscope services.

CDI offers extensions to create your own scope so you can implement the context and use the @NormalScope to do this.

  • CDI fires an event AfterBeanDiscovery after each bean call
  • You can use CDI extension to @Observes this event and add your context implementation
  • In your scope implementation you can :
    1. Use Contextual to get your bean by its name from FacesContext ViewRoot Map and return it after each ajax call back
    2. Use CreationalContext if the bean name from first step is not found to create it in the FacesContext ViewRoot Map

for a more in-depth explanation i recommand this link : http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/