web-dev-qa-db-ja.com

@ EJB、@ PersistenceContext、@ Inject、@ Autowiredを使用して@FacesValidatorに挿入する方法

@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にアクセスできるように、バリデーターにサービスの依存関係を挿入するにはどうすればよいですか?

32
Mahmoud Saleh

@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ショーケースの例 も参照してください。

63
BalusC

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 {
}

次のようにレンダリングする必要があります:

enter image description here

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およびスペックリードが実施する下位互換性要件を回避できませんでした。

0
DavidS