Spring 如何使用@EJB、@PersistenceContext、@inject、@Autowired在@FacesValidator中注入
如何在@FacesValidator中注入像@EJB、@PersistenceContext、@inject、@AutoWired等依赖项?在我的特定情况下,我需要通过@AutoWired: 但是,它没有被注入,并且仍然为null,导致java.lang.NullPointerException。 似乎@EJB、@PersistenceContext和@Inject也不起作用 如何在验证器中注入服务依赖项以便访问DB?在JSF2.3之前,注入容器不管理服务依赖项。您需要使其成为托管bean。使用Spring的@Component、CDI或JSF代替,以使其成为托管bean,从而符合依赖注入的条件 例如,假设您想使用JSF的@ManagedBean: 您还需要在EL中通过{name}将其引用为托管bean,而不是硬编码字符串中的验证器ID。所以,所以Spring 如何使用@EJB、@PersistenceContext、@inject、@Autowired在@FacesValidator中注入,spring,validation,jsf-2,dependency-injection,service-layer,Spring,Validation,Jsf 2,Dependency Injection,Service Layer,如何在@FacesValidator中注入像@EJB、@PersistenceContext、@inject、@AutoWired等依赖项?在我的特定情况下,我需要通过@AutoWired: 但是,它没有被注入,并且仍然为null,导致java.lang.NullPointerException。 似乎@EJB、@PersistenceContext和@Inject也不起作用 如何在验证器中注入服务依赖项以便访问DB?在JSF2.3之前,注入容器不管理服务依赖项。您需要使其成为托管bean。使用
<h:inputText ... validator="#{emailExistValidator.validate}" />
或
而不是
<h:inputText ... validator="emailExistValidator" />
或
这确实很尴尬。JSF的人已经证实了这一令人尴尬的疏忽,他们自JSF2.3以来就将@FacesValidator和@FacesConverter作为合格的注入目标,另请参见。对于EJB,可以通过从JNDI手动获取它来解决问题,另请参见。如果您碰巧使用了CDI扩展,那么还可以通过在类上添加@Advanced注释来解决它
另见:
如果您碰巧使用了JSF实用程序库,那么由于版本1.6是透明的,因此添加了对在@FacesValidator类中使用@Inject和@EJB的透明支持,而无需任何额外的配置或注释。另请参见。如果您使用的是JavaEE8和/或JSF2.3,那么现在可以将其注入JSF验证器 在payara服务器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>
应该呈现如下内容:
在意识到配置Bean的必要性之前,我把头撞在墙上大约一个小时。从文件中:
FacesConfig.Version.JSF_2_3
该值表示应将CDI用于EL分辨率以及启用JSF CDI注入,如第5.6.3节“EL分辨率CDI”和第5.9节“CDI集成”所述
从这个GitHub问题来看:
默认情况下,JSF2.3以与JSF早期版本兼容的模式运行,除非应用程序中包含CDI管理的bean,并带有注释@javax.faces.annotation.FacesConfig。要切换到JSF2.3模式,您需要一个如下所示的配置bean:shows ConfigurationBean
JSF需要切换到当前版本这一事实引起了极大的争议。几乎整个EG都投了反对票,但最终我们无法绕过JCP为JavaEE设置的向后兼容性要求和spec lead强制执行的向后兼容性要求
对不起,我不做春季运动。我做EJB,对CDI有所了解。但我真的不能在春天的细节。2因为您不想在不同的请求之间共享DAO状态。3绑定要求EL范围中的任何位置都有一个具体实例,该实例由@ManagedBean或@Named准备。validatorId需要@FacesValidator id,但由于我们删除了它,它就不存在了。如果您的DAO类拥有一个状态,并且您将其设置为会话或应用程序范围,那么它将在多个请求或用户之间共享。这可能会导致不期望的结果/行为,即不安全。如果您的DAO类不包含任何状态,也不是来自您正在使用JPA的情况下的持久性上下文!,然后,您可以安全地将其设置为会话或应用程序范围。请举个小例子,您所说的保持状态是什么意思?一个对更改敏感的实例变量,被一个或多个方法使用。例如,公共类FooDAO{private Bar;}这里,Bar是FooDAO类的状态。如果它在会话或应用程序范围内,并且一个请求更改了它,那么它将反映回所有其他请求/会话。这可能是不可取的。在这种情况下,您应该将其保留在请求范围内,以便它不会被所有其他请求/会话共享。但是,如果DAO不保持状态,并且所有的工作都是基于同一个方法块中的变量完成的,那么您可以安全地将其放入会话/应用程序范围。如果DAO是无状态的,即没有任何字段/属性,那么您可以安全地将其保持在一个较宽的范围内。但如果它是有状态的,即有任何字段/属性对基于请求的更改敏感,那么您更愿意将其保留在请求范围内。有趣的是,注释@FacesConfigversion=FacesConfig.Version.JSF_2_3必须存在,即使faces-config.xml中已经设置了Version=2.3。这需要一些时间才能弄清楚。
<f:validator binding="#{emailExistValidator}" />
<h:inputText ... validator="emailExistValidator" />
<f:validator validatorId="emailExistValidator" />
<?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 {
}