如何使用@EJB、@PersistenceContext、@Inject、@Autowired 注入@FacesValidator

发布于 2024-12-07 05:42:50 字数 535 浏览 1 评论 0原文

如何在 a 中注入 @EJB@PersistenceContext@Inject@AutoWired 等依赖项@FacesValidator?在我的具体情况下,我需要通过 @AutoWired 注入 Spring 托管 bean:

@FacesValidator("emailExistValidator")
public class EmailExistValidator implements Validator {

    @Autowired
    private UserDao userDao;

    // ...
}

但是,它没有被注入,并且仍然为 null,导致 java.util.concurrent.beans 被注入。 lang.NullPointerException。 看来@EJB、@PersistenceContext和@Inject也不起作用。

如何在验证器中注入服务依赖项以便可以访问数据库?

How can I inject a dependency like @EJB, @PersistenceContext, @Inject, @AutoWired, etc in a @FacesValidator? In my specific case I need to inject a Spring managed bean via @AutoWired:

@FacesValidator("emailExistValidator")
public class EmailExistValidator implements Validator {

    @Autowired
    private UserDao userDao;

    // ...
}

However, it didn't get injected and it remains null, resulting in java.lang.NullPointerException.
It seems that @EJB, @PersistenceContext and @Inject also doesn't work.

How do I inject a service dependency in my validator so that I can access the DB?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

木緿 2024-12-14 05:42:50

JSF 2.3+

如果您已经使用 JSF 2.3 或更高版本,并且想要通过例如 @EJB@PersistenceContext@Inject< 注入 CDI 支持的工件/code>,然后只需将 management=true 添加到 @FacesValidator 注释即可使其受 CDI 管理。

@FacesValidator(value="emailExistValidator", managed=true)

JSF 2.2 -

如果您还没有使用 JSF 2.3 或更高版本,那么您基本上需要将其设为托管 bean。使用 Spring 的 @Component 、 CDI 的 @Named 或 JSF 的 @ManagedBean 而不是 @FacesValidator 以便使其成为托管 bean,从而有资格进行依赖项注入。

例如,假设您想使用 CDI 的 @Named

@Named
@ApplicationScoped
public class EmailExistValidator implements Validator {
    // ...
}

您还需要在 EL 中通过 #{name} 将其引用为托管 Bean,而不是在 EL 中作为验证器 ID硬编码字符串。因此,

<h:inputText ... validator="#{emailExistValidator.validate}" />

对于

<h:inputText ... validator="emailExistValidator" />

EJB ,

<f:validator binding="#{emailExistValidator}" />

https://balusc.omnifaces.org/2011/09/communication-in-jsf-20.html

<f:validator validatorId="emailExistValidator" />

有一种解决方法,可以手动从 JNDI 获取它,另请参阅 在 @FacesConverter 中获取 @EJB 并@FacesValidator

如果您碰巧使用 JSF 实用程序库 OmniFaces,从版本 1.6 开始,它添加了对使用 @Inject 和 @EJB@FacesValidator 类中,无需任何额外的配置或注释。另请参阅CDI @FacesValidator 展示示例

另请参阅:


JSF 2.3+

If you're already on JSF 2.3 or newer, and want to inject CDI-supported artifacts via e.g. @EJB, @PersistenceContext or @Inject, then simply add managed=true to the @FacesValidator annotation to make it CDI-managed.

@FacesValidator(value="emailExistValidator", managed=true)

JSF 2.2-

If you're not on JSF 2.3 or newer yet, then you basically need to make it a managed bean. Use Spring's @Component, CDI's @Named or JSF's @ManagedBean instead of @FacesValidator in order to make it a managed bean and thus eligible for dependency injection.

E.g., assuming that you want to use CDI's @Named:

@Named
@ApplicationScoped
public class EmailExistValidator implements Validator {
    // ...
}

You also need to reference it as a managed bean by #{name} in EL instead of as a validator ID in hardcoded string. Thus, so

<h:inputText ... validator="#{emailExistValidator.validate}" />

instead of

<h:inputText ... validator="emailExistValidator" />

or

<f:validator binding="#{emailExistValidator}" />

instead of

<f:validator validatorId="emailExistValidator" />

For EJBs there's a workaround by manually grabbing it from JNDI, see also Getting an @EJB in @FacesConverter and @FacesValidator.

If you happen to use JSF utility library OmniFaces, since version 1.6 it adds transparent support for using @Inject and @EJB in a @FacesValidator class without any additional configuration or annotations. See also the CDI @FacesValidator showcase example.

See also:


水水月牙 2024-12-14 05:42:50

如果您使用的是 Java EE 8 和/或 JSF 2.3,现在可以注入 JSF 验证器。

在 Payara Server 5.192 #badassfish 上使用 Mojarra 2.3.9.payara-p2 进行测试。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:body>
        Hello from Facelets
        <h:form>
            <h:messages/>
            <h:inputText value="#{someBean.txtField}" validator="someValidator"/>
        </h:form>
    </h:body>
</html>
import javax.inject.Named;
import javax.enterprise.context.Dependent;

@Named(value = "someBean")
@Dependent
public class SomeBean {

  private String txtField;

  public String getTxtField() {
    return txtField;
  }

  public void setTxtField(String txtField) {
    this.txtField = txtField;
  }
}
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;

@FacesValidator(value = "someValidator", managed = true)
public class CustomValidator implements Validator<String> {

  @Inject
  NewClass newClass;

  @Override
  public void validate(FacesContext context, UIComponent component, String value)
      throws ValidatorException {

    System.out.println("validator running");
    System.out.println("injected bean: " + newClass);

    if (value != null && value.equals("badvalue")) {
      throw new ValidatorException(new FacesMessage(newClass.getMessage()));
    }
  }
}
public class NewClass {

  public String getMessage() {
    return "secret message";
  }
}
import javax.faces.annotation.FacesConfig;

// WITHOUT THIS INJECTION WILL NOT WORK!
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
public class ConfigurationBean {
}

应该呈现如下内容:

在此处输入图像描述

在意识到需要 ConfigurationBean 之前,我把头撞在墙上大约一个小时。从文档中:

FacesConfig.Version.JSF_2_3
该值指示 CDI 应用于 EL 解析以及启用 JSF CDI 注入,如第 5.6.3 节“用于 EL 解析的 CDI”和第 5.9 节“CDI 集成”中指定的

,并且从此 GitHub 问题中,https://github.com/eclipse-ee4j/glassfish/issues/22094

默认情况下,JSF 2.3 以与之前版本的 JSF 兼容的模式运行,除非应用程序中包含带有注释 @javax.faces.annotation.FacesConfig 的 CDI 托管 Bean。要切换到 JSF 2.3 模式,您需要一个如下所示的配置 bean:(显示 ConfigurationBean

...

JSF 需要切换到“当前版本”这一事实引起了很大争议。几乎整个 EG 都投了反对票,但最终我们无法绕过 JCP 为 Java EE 设定的向后兼容性要求以及规范负责人强制执行的要求。

You can now inject into JSF validators if you're using Java EE 8 and/or JSF 2.3.

Tested using Mojarra 2.3.9.payara-p2 on Payara Server 5.192 #badassfish.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:body>
        Hello from Facelets
        <h:form>
            <h:messages/>
            <h:inputText value="#{someBean.txtField}" validator="someValidator"/>
        </h:form>
    </h:body>
</html>
import javax.inject.Named;
import javax.enterprise.context.Dependent;

@Named(value = "someBean")
@Dependent
public class SomeBean {

  private String txtField;

  public String getTxtField() {
    return txtField;
  }

  public void setTxtField(String txtField) {
    this.txtField = txtField;
  }
}
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;

@FacesValidator(value = "someValidator", managed = true)
public class CustomValidator implements Validator<String> {

  @Inject
  NewClass newClass;

  @Override
  public void validate(FacesContext context, UIComponent component, String value)
      throws ValidatorException {

    System.out.println("validator running");
    System.out.println("injected bean: " + newClass);

    if (value != null && value.equals("badvalue")) {
      throw new ValidatorException(new FacesMessage(newClass.getMessage()));
    }
  }
}
public class NewClass {

  public String getMessage() {
    return "secret message";
  }
}
import javax.faces.annotation.FacesConfig;

// WITHOUT THIS INJECTION WILL NOT WORK!
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
public class ConfigurationBean {
}

Should render something like:

enter image description here

I banged my head on the wall for about an hour before realizing the need for ConfigurationBean. From the documentation:

FacesConfig.Version.JSF_2_3
This value indicates CDI should be used for EL resolution as well as enabling JSF CDI injection, as specified in Section 5.6.3 "CDI for EL Resolution" and Section 5.9 "CDI Integration"

And from this GitHub issue, https://github.com/eclipse-ee4j/glassfish/issues/22094:

By default, JSF 2.3 runs in a compatibility mode with previous releases of JSF, unless a CDI managed bean is included in the application with the annotation @javax.faces.annotation.FacesConfig. To switch into a JSF 2.3 mode you will need a configuration bean like below: (shows ConfigurationBean)

...

The fact that JSF needs to be switched into the "current version" was highly controversial. Pretty much the entire EG voted against that, but eventually we could not get around the backwards compatibility requirements that the JCP sets for Java EE and the spec lead enforces.

ぺ禁宫浮华殁 2024-12-14 05:42:50

我的方法是在构造函数中手动触发注入:

import jakarta.faces.context.FacesContext;
import jakarta.faces.validator.FacesValidator;
import org.joinfaces.FacesContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

@FacesValidator
public class PatientIdValidator implements Validator<String> { 

    @Autowired
    private MyBean beany;

    @Value("${my.property}")
    private String myText;

    public PatientIdValidator() {
        // inject spring managed beans and @Values into this JSF managed class
        FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance())
                .getAutowireCapableBeanFactory()
                .autowireBean(this);
    }
}

这是基于此博客文章: http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely

My approach is to trigger the injection by hand in the constructor:

import jakarta.faces.context.FacesContext;
import jakarta.faces.validator.FacesValidator;
import org.joinfaces.FacesContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

@FacesValidator
public class PatientIdValidator implements Validator<String> { 

    @Autowired
    private MyBean beany;

    @Value("${my.property}")
    private String myText;

    public PatientIdValidator() {
        // inject spring managed beans and @Values into this JSF managed class
        FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance())
                .getAutowireCapableBeanFactory()
                .autowireBean(this);
    }
}

This is based on this blog post: http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文