如何在@EJB
中注入@PersistenceContext
,@Inject
,@AutoWired
,@FacesValidator
等依赖项?在我的具体情况下,我需要通过@AutoWired
注入一个Spring托管bean:
@FacesValidator("emailExistValidator")
public class EmailExistValidator implements Validator {
@Autowired
private UserDao userDao;
// ...
}
然而,它没有被注入,它仍然是null
,导致java.lang.NullPointerException
。
似乎@EJB
,@PersistenceContext
和@Inject
也不起作用。
如何在验证程序中注入服务依赖项以便我可以访问数据库?
答案 0 :(得分:62)
@FacesValidator
不由注入容器管理。您需要将其设置为托管bean。使用Spring的@Component
,CDI的@Named
或JSF的@ManagedBean
而不是@FacesValidator
,以使其成为托管bean,从而有资格进行依赖注入。
例如,假设您要使用JSF的@ManagedBean
:
@ManagedBean
@RequestScoped
public class EmailExistValidator implements Validator {
// ...
}
您还需要在EL中将#{name}
引用为托管bean,而不是硬编码字符串中的验证器ID。所以,所以
<h:inputText ... validator="#{emailExistValidator.validate}" />
或
<f:validator binding="#{emailExistValidator}" />
而不是
<h:inputText ... validator="emailExistValidator" />
或
<f:validator validatorId="emailExistValidator" />
这确实很尴尬。 JSF人员已经证实了这种令人尴尬的疏忽,他们会在即将到来的JSF 2.2 2.3中使@FacesValidator
(和@FacesConverter
)成为符合条件的注射目标,另请参阅JSF spec issue 763 。对于EJB,可以通过从JNDI手动获取它来解决此问题,另请参阅Getting an @EJB in @FacesConverter and @FacesValidator。如果您碰巧使用CDI扩展程序MyFaces CODI,那么您也可以通过在类上添加@Advanced
注释来解决它。
更新:如果您碰巧使用JSF实用程序库OmniFaces,因为版本1.6增加了对@Inject
和@EJB
@FacesValidator
的透明支持1}}没有任何附加配置或注释的类。另请参阅the CDI @FacesValidator
showcase example。
答案 1 :(得分:0)
现在,如果您使用的是Java EE 8和/或JSF 2.3,则可以注入JSF验证器。
使用Mojarra 2.3.9.payara-p2在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 {
}
应呈现以下内容:
在意识到需要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:
默认情况下,除非应用程序中包含带有注解@ javax.faces.annotation.FacesConfig的CDI托管Bean,否则JSF 2.3以与以前版本的JSF兼容的方式运行。要切换到JSF 2.3模式,您将需要一个如下所示的配置bean:(显示ConfigurationBean )
...
需要将JSF切换到“当前版本”这一事实引起了很大争议。几乎整个EG都对此表示反对,但是最终我们无法解决JCP为Java EE和规范负责人强制执行的向后兼容性要求。