1. 概要

この記事では、ビジネスロジックの実行をSpring Beanに委任する目的で、JSF管理対象BeanおよびJSFページ内からSpringで定義されたBeanにアクセスするためのレシピを見ていきます。

この記事は、読者がJSFとSpringの両方を別々に理解していることを前提としています。 この記事は、JSFのMojarra実装に基づいています。

2. 春に

Springで次のBeanを定義してみましょう。 UserManagementDAO beanは、ユーザー名をメモリ内ストアに追加します。これは、次のインターフェイスで定義されます。

public interface UserManagementDAO {
    boolean createUser(String newUserData);
}

Beanの実装は、次のJava構成を使用して構成されます。

public class SpringCoreConfig {
    @Bean
    public UserManagementDAO userManagementDAO() {
        return new UserManagementDAOImpl();
    }
}

または、次のXML構成を使用します。

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="com.baeldung.dao.UserManagementDAOImpl" id="userManagementDAO"/>

BeanをXMLで定義し、 CommonAnnotationBeanPostProcessor を登録して、@PostConstructアノテーションが確実に取得されるようにします。

3. 構成

次のセクションでは、SpringコンテキストとJSFコンテキストの統合を可能にする構成項目について説明します。

3.1. Java web.xmlなしの構成

を実装することによって WebApplicationInitializer プログラムで構成することができます ServletContext。 以下は始めるとき() 内部の実装 MainWebAppInitializer クラス:

public void onStartup(ServletContext sc) throws ServletException {
    AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
    root.register(SpringCoreConfig.class);
    sc.addListener(new ContextLoaderListener(root));
}

AnnotationConfigWebApplicationContext は、Spring’gコンテキストをブートストラップし、 SpringCoreConfigクラスを登録することでBeanを追加します。

同様に、Mojarraの実装には FacesInitializer を構成するクラス FacesServlet。 この構成を使用するには、 FacesInitializer。 の完全な実装 MainWebAppInitializer、 現在は次のとおりです。

public class MainWebAppInitializer extends FacesInitializer implements WebApplicationInitializer {
    public void onStartup(ServletContext sc) throws ServletException {
        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(SpringCoreConfig.class);
        sc.addListener(new ContextLoaderListener(root));
    }
}

3.2. web.xmlを使用

まず、アプリケーションのweb.xmlファイルでContextLoaderListenerを構成します。

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

このリスナーは、Webアプリケーションの起動時にSpringアプリケーションコンテキストを起動する役割を果たします。 このリスナーは、デフォルトでapplicationContext.xmlという名前のSpring構成ファイルを探します。

3.3. faces-config.xml

ここで、face-config.xmlファイルでSpringBeanFacesELResolverを構成します。

<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>

ELリゾルバーはJSFフレームワークでサポートされているプラグ可能なコンポーネントであり、式言語(EL)式を評価するときにJSFランタイムの動作をカスタマイズできます。 このELリゾルバーにより、JSFランタイムはJSFで定義されたEL式を介してSpringコンポーネントにアクセスできます。

4. JSFでのSpringBeansへのアクセス

この時点で、JSF Webアプリケーションは、JSFバッキングBeanまたはJSFページのいずれかからSpringBeanにアクセスできるように準備されています。

4.1. バッキングBeanJSF2.0から

Spring Beanは、JSFバッキングBeanからアクセスできるようになりました。 実行しているJSFのバージョンに応じて、2つの方法が考えられます。 JSF 2.0では、JSFマネージドBeanで@ManagedPropertyアノテーションを使用します。

@ManagedBean(name = "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
    @ManagedProperty(value = "#{userManagementDAO}")
    transient private IUserManagementDAO theUserDao;

    private String userName;
    // getters and setters
}

を使用する場合、ゲッターとセッターは必須であることに注意してください。 @ManagedProperty。 ここで、マネージドBeanからSpring Beanのアクセシビリティを主張するために、 createNewUser() 方法:

public void createNewUser() {
    FacesContext context = FacesContext.getCurrentInstance();
    boolean operationStatus = userDao.createUser(userName);
    context.isValidationFailed();
    if (operationStatus) {
        operationMessage = "User " + userName + " created";
    }
}

この方法の要点は、 userDao Spring Beanを使用し、その機能にアクセスすることです。

4.2. JSF2.2のバッキングBeanから

JSF2.2以降でのみ有効な別のアプローチは、CDIの@Injectアノテーションを使用することです。 これは、JSFマネージドBean( @ManagedBean アノテーション付き)およびCDIマネージドBean( @Named アノテーション付き)に適用されます。

実際、CDIアノテーションを使用すると、これがBeanを注入する唯一の有効な方法です。

@Named( "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
    @Inject
    UserManagementDAO theUserDao;
}

このアプローチでは、ゲッターとセッターは必要ありません。 EL式がないことにも注意してください。

4.3. JSFビューから

createNewUser()メソッドは、次のJSFページからトリガーされます。

<h:form>
    <h:panelGrid id="theGrid" columns="3">
        <h:outputText value="Username"/>
        <h:inputText id="firstName" binding="#{userName}" required="true"
          requiredMessage="#{msg['message.valueRequired']}" value="#{registration.userName}"/>
        <h:message for="firstName" style="color:red;"/>
        <h:commandButton value="#{msg['label.saveButton']}" action="#{registration.createNewUser}"
          process="@this"/>
        <h:outputText value="#{registration.operationMessage}" style="color:green;"/>
    </h:panelGrid>
</h:form>

ページをレンダリングするには、サーバーを起動して次の場所に移動します。

http://localhost:8080/jsf/index.jsf

JSFビューでELを使用して、SpringBeanにアクセスすることもできます。 テストするには、行番号7を以前に紹介したJSFページから次のように変更するだけで十分です。

<h:commandButton value="Save"
  action="#{registration.userDao.createUser(userName.value)}"/>

ここでは、SpringDAOでcreateUser メソッドを直接呼び出し、 userName のバインド値をJSFページ内からメソッドに渡し、マネージドBeanをまとめて回避します。

5. 結論

SpringコンテキストとJSFコンテキストの基本的な統合について検討しました。ここでは、JSFBeanとページでSpringBeanにアクセスできます。

JSFランタイムは、Springフレームワークが統合コンポーネントを提供できるようにするプラグイン可能なアーキテクチャーを提供しますが、SpringフレームワークからのアノテーションはJSFコンテキストでは使用できません。その逆も同様です。

これは、@Autowired@Componentなどの注釈を使用できないことを意味します。 JSFマネージドBeanで使用するか、SpringマネージドBeanで@ManagedBeanアノテーションを使用します。 ただし、JSF2.2+マネージドBeanとSpringBeanの両方で@Injectアノテーションを使用できます(SpringはJSR-330をサポートしているため)。

この記事に付属するソースコードは、GitHubで入手できます。