Параметры CDI в @PostConstruct

Я думаю, что мой вопрос похож на этот, но не нашел его для работы

  <f:metadata>
  <f:viewParam id="id" name="id" value="#{detailsBean.id}"/>
 </f:metadata>

Почему я не могу это сделать с помощью @Named и использовать CDI:

@Named
@RequestScoped
public class DetailsBean {

    private Contacts detailsContact;
    @EJB
    ContactsFacade contactsEJB;
    private int id;

    public DetailsBean() {

        System.out.println("details bean called");
    }

    @PostConstruct
    public void onLoad() {
        detailsContact = contactsEJB.find(id);

}

Я не могу зарегистрировать идентификатор.

Конечно, @ManagedProperty несовместим с CDI.

***** ***** UPDATE

некоторый xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="../template.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:p="http://primefaces.prime.com.tr/ui"
                xmlns:f="http://java.sun.com/jsf/core">

    <ui:define name="head">
        <f:metadata>               
            <f:viewParam name="paginator" value="#{contactsBean.contactsTablePaginator}"/>
            <f:viewParam name="rows" value="#{contactsBean.contactsTableRows}"/>
        </f:metadata>
    </ui:define>

    <ui:define name="content">
        <p:growl id="growl" showDetail="true"/>

        <p:panel id="contactsPanel" >

            <h:form id ="contactsForm">

                <p:dataTable id="contactsTable" value="#{contactsBean.contacts}" selection="#{detailsBean.detailsContact}" var="contacts" widgetVar="contactsTable"
                             selectionMode="single" rowSelectListener="#{contactsBean.rowSelect}" rowUnselectListener="#{contactsBean.rowUnSelect}"
                             onRowUnselectUpdate="detailsForm" onRowSelectUpdate="detailsForm"
                             paginator="#{contactsBean.contactsTablePaginator}" rows="#{contactsBean.contactsTableRows}" rowsPerPageTemplate="5,10,15,25,50,100"
                             paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}">

                    <f:facet name="header">                     
                        <p:outputPanel>
                            <h:outputText value="Search:" />
                            <p:inputText id="globalFilter" onkeyup="contactsTable.filter()"  style="width:150px" />                
                        </p:outputPanel>
                    </f:facet>

                    <p:column filterStyle="display:none"  filterBy="#{contacts.name}" headerText="Name" style="width:200px">
                        <h:outputText value="#{contacts.name}" />
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.street}" headerText="Street" style="width:280px">
                        <h:outputText value="#{contacts.street}" />                     
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.city}" headerText="City" style="width:150px">
                        <h:outputText value="#{contacts.city}" />
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.state}" headerText="State" style="width:50px">
                        <h:outputText value="#{contacts.state}" />
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.zip}" headerText="Zip" style="width:100px">
                        <h:outputText value="#{contacts.zip}" />
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.country}" headerText="Country" style="width:150px">
                        <h:outputText value="#{contacts.country}" />
                    </p:column>

                    <p:column filterStyle="display:none" filterBy="#{contacts.sent}" headerText="Sent" style="width:50px">
                        <h:outputText value="#{contacts.sent}" />
                    </p:column>                 

                </p:dataTable>

                <p:ajaxStatus >

                    <f:facet name="start">
                        <h:graphicImage value="../resources/images/ajax-loader-bar.gif" />
                    </f:facet>

                    <f:facet name="complete">
                        <h:graphicImage value="../resources/images/ajax-loader-bar-still.gif" />
                    </f:facet>

                    <f:facet name="default">
                        <h:graphicImage value="../resources/images/ajax-loader-bar-still.gif" />
                    </f:facet>
                </p:ajaxStatus>
                <br />

                <p:commandLink value="View All" action="#{contactsBean.viewAll}"   /> &nbsp;
                <p:commandLink value="Default View" action="#{contactsBean.viewDefault}"  /> &nbsp;
                <p:commandLink value="Advanced Search" action="search?faces-redirect=true" />

                <br />           

            </h:form>

            <br />

        </p:panel>

        <br />
        <br />

        <h:form id="detailsForm">

            <p:panel id="detailsPanel" visible="#{detailsBean.visible}" >

                <h:panelGrid id="detailsPanelGrid" cellpadding="2" cellspacing="2" columns="3"   >

                    <h:outputText value="Name :" />
                    <p:inputText id="name" value="#{detailsBean.detailsContact.name}" style="width:400px" />
                    <p:message for="name" />

                    <h:outputText value="Email :" />
                    <p:inputText id="email" value="#{detailsBean.detailsContact.email}" style="width:400px" validatorMessage="Must be a valid email address. EX: [email protected]"  >
                        <f:validateRegex pattern="[a-zA-Z0-9][email protected][a-zA-Z0-9]+\.[a-zA-Z0-9]+"/>
                        <p:ajax event="blur" update="emailMsg" />
                    </p:inputText>
                    <p:message id="emailMsg" for="email" />

                    <h:outputText value="Street :" />
                    <p:inputText id="street" value="#{detailsBean.detailsContact.street}" style="width:400px" />
                    <p:message for="street" />

                    <h:outputText value="City :" />
                    <p:inputText id="city" value="#{detailsBean.detailsContact.city}" style="width:400px" />
                    <p:message for="city" />

                    <h:outputText value="State :" />
                    <p:inputText id="state" value="#{detailsBean.detailsContact.state}" style="width:400px" validatorMessage="Length is greater than 2" >
                        <f:validateLength maximum="2" />
                        <p:ajax event="blur" update="stateMsg" />
                    </p:inputText>
                    <p:message id="stateMsg" for="state" />

                    <h:outputText value="Country :" />
                    <p:inputText id="country" value="#{detailsBean.detailsContact.country}" style="width:400px" />
                    <p:message for="country" />

                    <h:outputText value="Phone :" />
                    <p:inputText id="phone" value="#{detailsBean.detailsContact.phone}" style="width:400px"/>
                    <p:message for="phone" />

                    <h:outputText value="Guests :" />
                    <p:inputText id="guests" value="#{detailsBean.detailsContact.guests}" style="width:400px"/>
                    <p:message for="guests" />

                    <h:outputText value="Arrival :" />
                    <p:calendar id="arrival" value="#{detailsBean.detailsContact.arrival}" showOn="button" />
                    <p:message for="arrival" />

                    <h:outputText value="Departure :" />
                    <p:calendar id="departure" value="#{detailsBean.detailsContact.departure}" showOn="button" />
                    <p:message for="departure" />

                    <h:outputText value="Message :" />
                    <p:inputTextarea id="message" effectDuration="30" style="width:400px;height:100px;" value="#{detailsBean.detailsContact.message}"  />
                    <p:message for="message" />

                    <h:outputText value="Departure :" />
                    <p:calendar id="inserted" value="#{detailsBean.detailsContact.inserted}" showOn="button"/>
                    <p:message for="inserted" />

                    <h:outputText value="Sent :" />
                    <h:selectBooleanCheckbox id="sent" value="#{detailsBean.detailsContact.sent}" />
                    <p:message for="sent" />
                    <br />

                </h:panelGrid>

                <p:commandButton value="Submit" action="#{detailsBean.updateContactDetails}"  update="contactsForm, growl, stateMsg" />
                <p:commandButton value="Close" action="#{detailsBean.handleClose}" update="contactsForm, detailsForm" />

            </p:panel>

        </h:form>

    </ui:define>

</ui:composition>

больше java-кода:

package com.atlanticpkg.view.beans;

import com.atlanticpkg.model.entities.Contacts;
import com.atlanticpkg.util.FacesUtils;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

@Named(value = "detailsBean")
@RequestScoped
public class EditBean {

    private Contacts detailsContact;
    private boolean visible = false;
    @Inject
    ContactsBean contactsBean;

    public EditBean() {
    }

    @PostConstruct
    public void onLoad() {
    }

    public void handleClose() {

        this.setVisible(false);
        this.setDetailsContact(new Contacts());
    }

    public void updateContactDetails() {

        try {

            contactsBean.getContactsEJB().edit(detailsContact);
            FacesUtils.addMessage(detailsContact.getName() + " was updated successfully!");

        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR", e.toString()));
        }

    }
}

и даже больше:

@Named(value = "contactsBean")
@RequestScoped
public class ContactsBean {

    @Inject
    EditBean editBean;
    @EJB
    private ContactsFacade contactsEJB;
    private List<Contacts> contacts = new ArrayList<Contacts>();
    private boolean contactsTablePaginator = true;
    private int contactsTableRows = 10;
    private Contacts selectedContact = new Contacts();

    public ContactsBean() {
    }

    @PostConstruct
    public void onLoad() {

        updateContactsList();
    }

    public String viewDefault() {

        contactsTablePaginator = true;
        contactsTableRows = 10;
        return "index?faces-redirect=true&includeViewParams=true";
    }

    public String viewAll() {

        contactsTablePaginator = false;
        contactsTableRows = 100;
        return "index?faces-redirect=true&includeViewParams=true";
    }

    public void updateContactsList() {

        contacts.clear();
        contacts = contactsEJB.findAll();
    }

    public void rowSelect(SelectEvent event) {

        editBean.setVisible(true);
        editBean.setDetailsContact((Contacts) event.getObject());
    }

    public void rowUnSelect(UnselectEvent event) {

        editBean.setVisible(false);
        editBean.setDetailsContact(new Contacts());

    }
}

Коды вводаText заполняются в порядке. Но вскоре, когда я попал в submit, он сказал, что значения равны нулю. Этот код отлично работает с SessionScope.

ПРЕДУПРЕЖДЕНИЕ:/admin/index.xhtml @104,109 value = "# {detailsBean.detailsContact.name}": Target Unreachable, 'null' возвращается null javax.el.PropertyNotFoundException:/admin/index.xhtml @104,109 value = "# {detailsBean.detailsContact.name}": Target Unreachable, 'null' null null

Я вижу, что он вызывает EditBean, когда я выбираю таблицу данных. Затем он называет это снова, когда я нажимаю кнопку отправки.

Ответы

Ответ 1

Жизненный цикл не позволяет использовать ваш подход.

Сначала создается bean (конструктор). После этого выполняется инъекция зависимостей, за которой следует метод @PostConstruct, после чего оценивается JSF файл. И viewParam находится в этом файле. Поэтому вам нужно зарегистрировать другого слушателя, который вызывается после заполнения параметров вида.

У меня есть решение для @RequestScope beans, но если область bean длиннее (например, View), то этот метод выполняется после каждого запроса (включая AJAX), который, вероятно, не нужен.

Используйте это для области запроса beans:

<f:metadata>
   <f:viewParam id="id" name="id" value="#{detailsBean.id}"/>
   <f:event type="preRenderView" listener="#{detailsBean.onLoad}" />
</f:metadata>

Для @ViewScope beans Я использую этот "хак", который работает, но, вероятно, это не лучшая практика. Он делает то же самое, но, вероятно, это не правильный подход.

#{detailsBean.onLoad()}
<f:metadata>
   <f:viewParam id="id" name="id" value="#{detailsBean.id}"/>
</f:metadata>

Я надеюсь, что это будет полезно для вас.


EDIT:

здесь вы используете много AJAX. Для этого нужно приземлиться как минимум ViewScoped beans. View Scope похож на RequestScope, но он занимает гораздо больше времени, пока страница не останется.

Но я не прочитал все это, есть много кода, и если ViewScope не поможет, возможно, вам следует предоставить небольшой фрагмент проблемного кода, чтобы он мог найти и сосредоточиться на реальной проблеме.

Ответ 2

Я столкнулся с той же проблемой, что и вы, и решил ее, используя внешний контекст (содержащий параметры GET) вместо f:viewParam.

В вашем методе @PostConstruct просто получите свой параметр с чем-то вроде

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();