@ManagedProperty(value = #{param.id}) в компоненте Scope Bean без запроса

Мне нужно передать параметр (POST) в @managedBean, я использовал такие управляемые свойства:

@ManagedProperty(value = "#{param.id}")
private int id;

И областью действия Bean является ViewScope.

Я получаю эту ошибку:

Не удалось создать квитанцию ​​управляемого компонента. Были обнаружены следующие проблемы: - Область действия объекта, на который ссылается выражение #{param.id}, request, короче, чем область представления ссылающихся управляемых компонентов.

Что я могу сделать?

Аржан взгляните:

Моя страница: Facelet Название

<form method="post" action="faces/index.xhtml">
  <input name="id" value="4" />
  <input type="submit" value="submit" />
</form>

<h:form>
  <h:commandLink value="click" action="index">
    <f:param id="id" name="id" value="20"/>
  </h:commandLink>
</h:form>


person ehsun7b    schedule 02.01.2011    source источник


Ответы (2)


Два пути:

  1. Сделайте запрос bean-компонента ограниченным и внедрите представление, ограниченное одним как другое @ManagedProperty.

    @ManagedBean
    @RequestScoped
    public class RequestBean {
    
        @ManagedProperty(value="#{param.id}")
        private Integer id;
    
        @ManagedProperty(value="#{viewBean}")
        private ViewBean viewBean;
    }
    

    Компонент с областью видимости доступен во время @PostConstruct и методов действия компонента с областью действия запроса. Вам нужно только иметь в виду, что id может потеряться, когда вы выполняете обратную передачу в то же представление без параметра.

  2. Или возьмите его вручную из карты параметров запроса во время инициализации компонента.

    @ManagedBean
    @ViewScoped
    public class ViewBean {
    
        private Integer id;
    
        @PostConstruct
        public void init() {
            id = Integer.valueOf(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id"));       
        }
    }
    

    Таким образом, начальный id доступен во всей области просмотра.

person BalusC    schedule 02.01.2011
comment
Спасибо, первое решение (внедрение bean-компонента viewScoped в requestScoped) является хорошей и популярной практикой??? - person ehsun7b; 02.01.2011
comment
Мое приложение обслуживается GlassFish, и я тоже могу использовать CDI-бины, но я решил сделать какой-то проект с использованием JSF-бинов, потому что я очень новичок в JSF, это хорошая идея? - person ehsun7b; 02.01.2011
comment
Зависит от цели id. Вы хотите обновлять его при каждом запросе? Идите по пути 1. Или вы хотите использовать начальное значение во всей области просмотра? Идите по пути 2. - person BalusC; 02.01.2011
comment
Спасибо, очень полное описание. - person ehsun7b; 02.01.2011
comment
Не могли бы вы прочитать другой ответ, который был опубликован на мой вопрос, и дать мне свою идею? - person ehsun7b; 02.01.2011
comment
Это третий способ (о котором я не подумал), который фактически делает то же самое, что и первый способ, но без bean-компонента с областью запроса. Это также более декларативно, чем второй способ. - person BalusC; 03.01.2011
comment
Привет, почему-то я не могу проанализировать параметр Get в конструкторе компонентов, мне нужно добавить @PostConstruct, кто-нибудь знает, почему? - person Heetola; 13.08.2012
comment
@Eildosa: ты говоришь о @ManagedProperty? Это довольно логично. Как бы вы вызывали метод установки для экземпляра перед его конструктором? - person BalusC; 13.08.2012
comment
нет, речь идет об id = Integer.valueOf(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(id)); это будет работать только в @PostConstruct - person Heetola; 13.08.2012
comment
@Eildosa: это ненормально. Ваша конкретная проблема вызвана другим. - person BalusC; 13.08.2012
comment
@BalusC спасибо за ваши ответы, нормально ли, что вы не добавили сеттеры для управляемых свойств, или это просто потому, что это не цель вопроса ОП? - person Tarik; 05.02.2015
comment
@Tarik: я всегда опускаю очевидность фрагментов кода, чтобы сделать ответ более целенаправленным. Учитывая то, как формулируется вопрос, ОП очень хорошо знает о необходимости геттеров/сеттеров. Если бы ОП не знал, я бы предпочел добавить комментарий вроде // +getter+setter вместо того, чтобы добавлять целую кучу очевидности. Просто позвольте вашей IDE автоматически сгенерировать геттеры/сеттеры и спрятать их в нижней части класса. - person BalusC; 05.02.2015
comment
@Tarik Или ты можешь использовать Ломбок для этой цели. - person alexander; 04.12.2015

В качестве альтернативы получению параметров непосредственно из запроса в вашем bean-компоненте вы можете использовать view parameters.

Они должны быть объявлены на Facelet, где вы используете управляемый компонент, следующим образом:

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

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

    <!-- Rest of Facelet here -->   

    </h:body>
</html>

Если вы сейчас запросите эту страницу, будет вызван установщик вспомогательного компонента со значением запроса, указанным для параметра id. Это работает как для GET, так и для (не лиц) POST запросов.

Преимущество в том, что здесь можно использовать стандартные конвертеры и валидаторы JSF. Конечно, если ваш управляемый компонент не привязан к конкретному представлению, это решение менее идеально.

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

Чтобы проверить, работает ли это, я использовал следующий управляемый компонент:

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;

@ManagedBean
@ViewScoped
public class MyBean {

    Long id;

    @PostConstruct
    public void test() {
        System.out.println("post construct called");
    }

    public void actionMethod(ActionEvent event) {       
        System.out.println("action called");        
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

И следующий Facelet:

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

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

        <h:outputText value="#{myBean.id}"/>

        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>

        <form method="post">
            <input name="id" value="4" />
            <input type="submit" value="submit" />
        </form>

    </h:body>
</html>

Введите число в поле ввода и нажмите кнопку отправки. Если число снова отображается на экране, значит тест прошел успешно. Обратите внимание, что вторая форма является обычной формой и не публикует никакого состояния JSF. Я проверил это на JBoss AS 6, и это работает. Доказательство параметра id в качестве параметра GET также работает.

person Arjan Tijms    schedule 02.01.2011
comment
Насколько я нахожу в книгах и руководствах, они работают только с параметрами Get, вы уверены, что их можно использовать с параметрами Post????... - person ehsun7b; 02.01.2011
comment
Хм, хотя я не являюсь авторитетным источником в этом, я почти уверен, что использовал это раньше с параметрами POST. Я проверю это еще раз и обновлю свой ответ. - person Arjan Tijms; 02.01.2011
comment
Я снова проверил и обновил свой ответ. Это всего лишь два файла, поэтому вам будет легко их скопировать. - person Arjan Tijms; 02.01.2011
comment
Я также просмотрел исходный код Mojarra, чтобы увидеть, как в конечном итоге разрешаются эти параметры. В Mojarra 2.03 это находится в строке 217 UIViewParameter: String paramValue = context.getExternalContext().getRequestParameterMap().get(getName()); поскольку карта параметров запроса всегда содержит параметры как из запросов POST, так и из GET, это, таким образом, автоматически объясняет, что он должен работать. Однако в спецификации JSF нет явного заявления о том, что должны поддерживаться ОБА POST и GET. Спецификация просто не говорит об этом явно. - person Arjan Tijms; 02.01.2011
comment
Спасибо за время, которое вы потратили на меня. Удачи :). Java-программисты так же хороши, как и язык программирования. - person ehsun7b; 03.01.2011
comment
Я протестировал его, как вы говорите, он отлично работает с ‹from method=post›, но не работает с тегом ‹h:commandLink›, я обновил свой вопрос, вы можете взглянуть на него? - person ehsun7b; 03.01.2011
comment
То, что вы пробовали до сих пор, и то, на что вы получили ответы, в основном предназначено для захвата параметров запроса из внешнего запроса (запрос без лиц). С помощью командной ссылки у вас есть некоторые другие параметры, как описано здесь: stackoverflow.com/questions/3599948/jsf2-action-parameter или в нескольких других статьях и ответах BalusC. - person Arjan Tijms; 03.01.2011
comment
@ArjanTijms arjam Я использовал ManagedProperty, чтобы получить param.id. Теперь я использую это в одном методе для получения запроса, связанного с этим идентификатором, но в следующий раз, когда я попытаюсь его использовать, он будет нулевым, то есть частным идентификатором строки. есть идеи, почему он очистил значение? - person sys_debug; 19.12.2011