@Inject для передачи параметров в CDI @Named bean через URL

Если я не могу использовать аннотацию @ManagedProperty с @Named, потому что @ManagedProperty не работает в CDI(?), тогда как вы передаете параметры в URL-адресе клиенту facelets? В моем коде я хочу передать javax.почта.getMessageNumber () к деталям.xhtml через кнопки" назад "и" вперед".

Я понимаю, что @Inject должен использоваться, но что вводится и как, пожалуйста?

из журналов glassfish id всегда равен 0, что довольно странно. Даже когда "вперед" нажата, id никогда не становится выше 1 независимо от того, сколько раз нажата кнопка. Конечно, это всего лишь симптом проблемы. Желаемый результат, конечно, состоит в том, чтобы перейти к следующему сообщению.

возможно, поместите сообщение или, по крайней мере, int в сеанс?

клиент как так:

<?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:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="top">
        <h:form>
            <h:form>
                <h:outputLink id="link1" value="detail.xhtml">
                    <f:param name="id" value="#{detail.back()}" />
                    <h:outputText value="back" />
                </h:outputLink>
            </h:form>
        </h:form>
        <h:form>
            <h:outputLink id="link1" value="detail.xhtml">
                <f:param name="id" value="#{detail.forward()}" />
                <h:outputText value="forward" />
            </h:outputLink>
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:outputText value="#{detail.content}"></h:outputText>
    </ui:define>
</ui:composition>

а фасоль как таковая:

package net.bounceme.dur.nntp;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedProperty;
import javax.inject.Named;
import javax.mail.Message;

@Named
@RequestScoped
public class Detail {

    private static final Logger logger = Logger.getLogger(Detail.class.getName());
    private static final Level level = Level.INFO;
    @ManagedProperty(value = "#{param.id}")
    private Integer id = 0;
    private Message message = null;
    private SingletonNNTP nntp = SingletonNNTP.INSTANCE;

    public Detail() {
        message = nntp.getMessage(id);
    }

    public int forward() {
        logger.log(level, "Detail.forward.." + id);
        id = id + 1;
        logger.log(level, "..Detail.forward " + id);
        return id;
    }

    public int back() {
        logger.log(level, "Detail.back.." + id);
        id = id - 1;
        logger.log(level, "..Detail.back " + id);
        return id;
    }

    public Message getMessage() {
        return message;
    }

    public String getContent() throws Exception {
        return message.getContent().toString();
    }
}

3 ответов


JSF @ManagedProperty аннотация работает только в JSF @ManagedBean классы. Т. е. в экземплярах, которые управляются JSF. Он не работает в экземплярах, которые управляются CDI @Named. Кроме того, вы совершили еще одну ошибку: вы пытаетесь подготовить Message на основе управляемого свойства в конструкторе. Если бы это был настоящий @ManagedBean, это также не сработало бы. Управляемое свойство недоступно во время построения, просто потому, что невозможно вызвать метод setter до вызывается конструктор. Вы бы использовали @PostConstruct метод для этого. Но это не решение, как @ManagedProperty Не работайте в @Named в любом случае.

иметь реальную замену для @ManagedProperty, вам нужно будет создать пользовательскую аннотацию CDI. Конкретный пример размещен в этот блог. Вот выдержка из релевантности:

таможни @HttpParam аннотация:

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
    @NonBinding
    public String value() default "";
}

производитель значения аннотации:

public class HttpParamProducer {

    @Inject
    FacesContext facesContext;

    @Produces
    @HttpParam
    String getHttpParameter(InjectionPoint ip) {
        String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
        if ("".equals(name)) name = ip.getMember().getName();
        return facesContext.getExternalContext()
                .getRequestParameterMap()
                .get(name);
    }
}

An пример использования:

@Inject @HttpParam
private String id;

служебная библиотека JSF OmniFaces есть @Param для этой цели со встроенной поддержкой преобразования и проверки JSF.


кроме того, вы также можете вручную захватить параметр запроса от внешнего контекста в Detail управляемый Bean-компонент. Рекомендуемый способ инициализации управляемого компонента-использовать @PostConstruct метод, а не конструктор, как конструктор мог бы использоваться для совершенно иных целей, чем создание управляемых компонентов:

@PostConstruct
public void init() {
    String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
    // ...
}

другой способ, ИМО также более подходит для этого конкретного случая, использовать <f:viewParam> что также позволяет конвертировать ID в Message сразу изготовленным на заказ конвертером.

<f:metadata>
    <f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>

С

@Named
public class Detail {

    private Message message;

    // Getter+setter
}

и

@FacesConverter("messageConverter")
public class MessageConverter implements Converter {

    // Convert string id to Message object in getAsObject().
    // Convert Message object to string id in getAsString().

}

см. также


во - первых, чтобы объяснить чужеродную часть-Glassfish использует JBoss Weld в качестве своей реализации CDI, Oracle не разрабатывает собственную реализацию.

и относительно значения сообщения об ошибке: FacesContext просто не вводится через @Inject. Существует довольно старый запрос для этого, и я думаю, что шов или припой обеспечивают производителя. Но для этого нет необходимости интегрировать любую из библиотек. Доступ к контексту faces, как вы нормальный управляемый Боб, через FacesContext.getCurrentInstance().


Я спрашивал сложный способ сделать простую вещь. В CDI для передачи параметров вы не можете использовать @ManagedProperty, как описано выше BalusC. Вместо этого вы просто настраиваете свои файлы 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:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="top">
        <h:form>
            <h:commandButton action="#{messages.back()}" value="..back" />
        </h:form>
        <h:form>
            <h:commandButton action="#{messages.forward()}" value="forward.." />
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:dataTable value="#{messages.model}" var="m">
            <h:column>
                <f:facet name="id">
                    <h:outputText value="id" />
                </f:facet>
                <h:outputLink id="hmmm" value="detail.xhtml">
                    <f:param name="id" value="#{m.getMessageNumber()}" />
                    <h:outputText value="#{m.getMessageNumber()}" />
                </h:outputLink>
            </h:column>
            <h:column>
                <f:facet name="subject">
                    <h:outputText value="subject" />
                </f:facet>
                <h:outputText value="#{m.subject}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="content">
                    <h:outputText value="content" />
                </f:facet>
                <h:outputText value="#{m.sentDate}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="date">
                    <h:outputText value="date" />
                </f:facet>
                <h:outputLink value="#{messages.getUrl(m)}">#{messages.getUrl(m)}</h:outputLink>
            </h:column>
        </h:dataTable>
    </ui:define>
</ui:composition>

в:

<?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:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="top">
        <h:form>
            <h:outputLink id="back" value="detail.xhtml">
                <f:metadata>
                    <f:viewParam name="id" value="#{detail.id}"  />
                </f:metadata>
                <f:param name="id" value="#{detail.back()}" />
                <h:outputText value="back" />
            </h:outputLink>
        </h:form>
        <h:form>
            <h:outputLink id="forward" value="detail.xhtml">
                <f:metadata>
                    <f:viewParam name="id" value="#{detail.id}"  />
                </f:metadata>
                <f:param name="id" value="#{detail.forward()}" />
                <h:outputText value="forward" />
            </h:outputLink>
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:outputText value="#{detail.content}"></h:outputText>
    </ui:define>
</ui:composition>

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

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