@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
も機能していないようです。
DBにアクセスできるように、バリデーターにサービスの依存関係を挿入するにはどうすればよいですか?
@FacesValidator
はインジェクションコンテナによって管理されていません。管理対象のBeanにする必要があります。 Springの@Component
、CDIの @Named
、またはJSFの @ManagedBean
を @FacesValidator
の代わりに使用して、マネージドBeanにし、依存性注入の対象にします。
たとえば、JSFの@ManagedBean
を使用するとします。
@ManagedBean
@RequestScoped
public class EmailExistValidator implements Validator {
// ...
}
また、ハードコードされた文字列のバリデータIDとしてではなく、ELの#{name}
によってマネージドBeanとして参照する必要があります。したがって、そう
<h:inputText ... validator="#{emailExistValidator.validate}" />
または
<f:validator binding="#{emailExistValidator}" />
の代わりに
<h:inputText ... validator="emailExistValidator" />
または
<f:validator validatorId="emailExistValidator" />
これは確かに厄介です。 JSFの連中は、この恥ずかしい見落としを確認しており、今後のJSFで@FacesValidator
(および@FacesConverter
)を適格な注入ターゲットにします。 2.2 2.3、 JSF仕様の問題76 も参照してください。 EJBについては、JNDIから手動で取得することによる回避策があります。 @ FacesConverterおよび@FacesValidatorで@EJBを取得する も参照してください。 CDI拡張機能 MyFaces CODI を使用している場合は、クラスに@Advanced
アノテーションを付けることで解決することもできます。
Update:JSFユーティリティライブラリを使用する場合 OmniFaces バージョン1.6では、@Inject
および@EJB
を使用するための透過的なサポートが追加されています追加の構成やアノテーションのない@FacesValidator
クラス。 CDI @FacesValidator
ショーケースの例 も参照してください。
Java EE8および/またはJSF2.3を使用している場合は、JSFバリデーターに挿入できるようになりました。
Payara Server 5.192#badassfishでMojarra2.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
の必要性に気付く前に、私は約1時間壁に頭をぶつけました。ドキュメントから:
FacesConfig.Version.JSF_2_3
この値は、セクション5.6.3「CDIfor ELResolution」およびセクション5.9「CDIIntegration」で指定されているように、CDIをEL解像度に使用し、JSFCDIインジェクションを有効にする必要があることを示します。
そして、このGitHubの問題から、 https://github.com/Eclipse-ee4j/glassfish/issues/22094 :
デフォルトでは、JSF 2.3は、以前のリリースのJSFとの互換モードで実行されます。ただし、CDIマネージドBeanがアノテーション@ javax.faces.annotation.FacesConfigでアプリケーションに含まれている場合を除きます。 JSF 2.3モードに切り替えるには、次のような構成Beanが必要です。(shows ConfigurationBean)
.。
JSFを「現在のバージョン」に切り替える必要があるという事実は非常に物議を醸しました。 EG全体がこれに反対票を投じましたが、最終的には、JCPがJava EEおよびスペックリードが実施する下位互換性要件を回避できませんでした。