Spring2.5とICEFaces開発Java EE


ICEFacesはJSFコンポーネントのクラスライブラリであり、これに基づいてAJAX特有の処理方法を追加した.サーバ側にDOMをバインドし、AJAXのプッシュ技術によってサーバ側の変更をclientに伝える.これは,サーバ側が様々なバックエンドデータサービスとインタラクションした後,表示層がどのように変化すべきかを示す情報を取得し,プッシュ技術を用いて,ユーザの介入を必要とせずに直ちに動的データをユーザインタフェースに非同期で送信できることを意味する.
ICEFacesコンポーネントセットは、通常のJSFのコンポーネントをAJAXをサポートするいくつかの特性に改造するなど、かなり完全です.例えば、JSFにHTMLタグをバインドしたinputTextコンポーネントは、ICEFacesによって現在感知され、入力されたデータを「ローカル」にコミットすることができる.サーバが得たのは、さっき入力したデータのほんの一部であり、ページ全体がコミットされてから処理する必要はありません.
ICEFacesコンポーネントキットにはstyling,a menu bar,a connection status widget,effects(highlights,pulses,fades),a progress bar,a file upload widget,charts,and a capable set of panelsも含まれる.
価格は高いが、JavaEE自体は上記のコンポーネントのサポートが不完全であり、ICEFacesとJSF 1を用いる.2開発に来たのもJSFの不足を補ったと言える.ICEFacesがJavaEEコンテナにどのように配置されているか、EJB 3の下でEJB 3を必要としないで簡単に開発と構成されているかを見てみましょう.
ICEFacesの1.6,1.7バージョンは、以前のJavaEE仕様、すなわちサーブレット2を使用する必要がある.2.5ではなく4です.JavaEE仕様では、サーブレット2.4資源を注入できない以外、違いは大きくない.つまりサーブレット2.4回のEJB訪問は従来の方法しか使えず、注入によるメリットは楽しめません.
以下、サーブレット2.5で、StatelessセッションEJBの例を使用します.
MyManagedBean.java:
Javaコード

   import com.tss.ejb.SLSBLocal;   
  
   public class MyManagedBean {   
     @EJB  
     SLSBLocal slsblocal;   
     public String getValueFromEJB() {   
         return slsblocal.getValue();   
     }   
 }  

import com.tss.ejb.SLSBLocal;

public class MyManagedBean {
	@EJB
	SLSBLocal slsblocal;
	public String getValueFromEJB() {
		return slsblocal.getValue();
	}
}

サーブレット2.4でannotationは無視されます.これは確かにうるさいが、仕方がないわけではない.この時SpringはEJBなしで管理してくれます
まず、webを構築します.xmlはICEFacesを構成し、同時に確立されたWebアプリケーションJSFは1.2バージョンでなければならない.下に建てられたwebを見てください.xml:
web.xml:
Xmlコード

    <?xml version="1.0" encoding="UTF-8"?>  
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
             version="2.4">  
        <servlet>  
            <servlet-name>Faces Servlet</servlet-name>  
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
            <load-on-startup>1</load-on-startup>  
       </servlet>  
     
       <servlet>  
           <servlet-name>Persistent Faces Servlet</servlet-name>  
           <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>  
           <load-on-startup>1</load-on-startup>  
       </servlet>  
     
       <servlet>  
           <servlet-name>Blocking Servlet</servlet-name>  
           <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>  
           <load-on-startup>1</load-on-startup>  
       </servlet>  
     
       <servlet-mapping>  
           <servlet-name>Faces Servlet</servlet-name>  
           <url-pattern>*.jspx</url-pattern>  
       </servlet-mapping>  
     
       <servlet-mapping>  
           <servlet-name>Persistent Faces Servlet</servlet-name>  
           <url-pattern>*.iface</url-pattern>  
       </servlet-mapping>  
     
       <servlet-mapping>  
           <servlet-name>Persistent Faces Servlet</servlet-name>  
           <url-pattern>/xmlhttp/*</url-pattern>  
       </servlet-mapping>  
     
       <servlet-mapping>  
           <servlet-name>Blocking Servlet</servlet-name>  
           <url-pattern>/block/*</url-pattern>  
       </servlet-mapping>  
     
       <servlet-mapping>  
           <servlet-name>Faces Servlet</servlet-name>  
           <url-pattern>/faces/*</url-pattern>  
       </servlet-mapping>  
     
       <servlet-mapping>  
           <servlet-name>Faces Servlet</servlet-name>  
           <url-pattern>*.faces</url-pattern>  
       </servlet-mapping>  
     
       <listener>  
           <listener-class>  
           com.icesoft.faces.util.event.servlet.ContextEventRepeater   
       </listener-class>  
       </listener>  
   </web-app>  

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>Blocking Servlet</servlet-name>
        <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>*.iface</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Persistent Faces Servlet</servlet-name>
        <url-pattern>/xmlhttp/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Blocking Servlet</servlet-name>
        <url-pattern>/block/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>
		com.icesoft.faces.util.event.servlet.ContextEventRepeater
	</listener-class>
    </listener>
</web-app>
 

DOMを更新し続けるBeanを構築する必要があります.この例では、1つのoutputTextを使用してクロックを表示し(java.util.Dateで実現)、別のoutputTextを使用してリフレッシュの回数を表示します.詳細については、ICEFaces開発ガイドで、faces-config.xmlとTimeBean.JAvaのソースファイル:
faces-config.xml:
Xmlコード

    <?xml version='1.0' encoding='UTF-8'?>  
    <faces-config xmlns="http://java.sun.com/xml/ns/javaee"  
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
                  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"  
                  version="1.2">  
      
        <managed-bean>  
            <managed-bean-name>renderManager</managed-bean-name>  
            <managed-bean-class>com.icesoft.faces.async.render.RenderManager</managed-bean-class>  
           <managed-bean-scope>application</managed-bean-scope>  
       </managed-bean>  
     
       <managed-bean>  
           <managed-bean-name>timebean</managed-bean-name>  
           <managed-bean-class>com.tss.beans.TimeBean</managed-bean-class>  
           <managed-bean-scope>request</managed-bean-scope>  
           <managed-property>  
               <property-name>renderManager</property-name>  
               <value>#{renderManager}</value>  
           </managed-property>  
       </managed-bean>  
     
   </faces-config>  

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">

    <managed-bean>
        <managed-bean-name>renderManager</managed-bean-name>
        <managed-bean-class>com.icesoft.faces.async.render.RenderManager</managed-bean-class>
        <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>

    <managed-bean>
        <managed-bean-name>timebean</managed-bean-name>
        <managed-bean-class>com.tss.beans.TimeBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>renderManager</property-name>
            <value>#{renderManager}</value>
        </managed-property>
    </managed-bean>

</faces-config>

 

TimeBean.java:
Javaコード

    package com.tss.beans;   
      
    import com.icesoft.faces.async.render.IntervalRenderer;   
    import com.icesoft.faces.async.render.RenderManager;   
    import com.icesoft.faces.async.render.Renderable;   
    import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;   
    import com.icesoft.faces.webapp.xmlhttp.RenderingException;   
      
    import java.util.Date;   
     
   public class TimeBean implements Renderable {   
       static int refreshCount = 0;   
       int interval = 1000;   
       PersistentFacesState state;   
       IntervalRenderer clock;   
     
       public TimeBean() {   
           init();   
       }   
     
       private void init() {   
           state = PersistentFacesState.getInstance();   
       }   
     
       public int getRefreshCount() {   
           return refreshCount;   
       }   
     
       public void setRefreshCount(int refreshCount) {   
           this.refreshCount = refreshCount;   
       }   
     
       public Date getNow() {   
           return new Date();   
       }   
     
       public String refresh() {   
           refreshCount++;   
           return null;   
       }   
     
       public void setRenderManager(RenderManager renderManager) {   
           clock = renderManager.getIntervalRenderer("clock");   
           clock.setInterval(interval);   
           clock.add(this);   
           clock.requestRender();   
       }   
     
       public PersistentFacesState getState() {   
           return state;   
       }   
     
       public void renderingException(RenderingException renderingException) {   
           if (clock != null) {   
               clock.remove(this);   
               clock = null;   
           }   
       }   
   }  

package com.tss.beans;

import com.icesoft.faces.async.render.IntervalRenderer;
import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;

import java.util.Date;

public class TimeBean implements Renderable {
    static int refreshCount = 0;
    int interval = 1000;
    PersistentFacesState state;
    IntervalRenderer clock;

    public TimeBean() {
        init();
    }

    private void init() {
        state = PersistentFacesState.getInstance();
    }

    public int getRefreshCount() {
        return refreshCount;
    }

    public void setRefreshCount(int refreshCount) {
        this.refreshCount = refreshCount;
    }

    public Date getNow() {
        return new Date();
    }

    public String refresh() {
        refreshCount++;
        return null;
    }

    public void setRenderManager(RenderManager renderManager) {
        clock = renderManager.getIntervalRenderer("clock");
        clock.setInterval(interval);
        clock.add(this);
        clock.requestRender();
    }

    public PersistentFacesState getState() {
        return state;
    }

    public void renderingException(RenderingException renderingException) {
        if (clock != null) {
            clock.remove(this);
            clock = null;
        }
    }
}

 

最後にexampleを構築しますjspページ、呼び出すときの名前は「example.iface」
example.jsp:
Htmlコード

    <!DOCTYPE html   
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>  
    <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>  
    <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>  
    <%@ taglib prefix="ice" uri="http://www.icesoft.com/<SPAN class=hilite1>icefaces</SPAN>" %>  
    <%@ taglib prefix="comp" uri="http://www.icesoft.com/<SPAN class=hilite1>icefaces</SPAN>/component" %>  
    <f:view>  
       <html>  
       <head>  
           <title><SPAN class=hilite1>ICEFaces</SPAN> Example</title>  
       </head>  
       <body>  
       <h:form>  
           <comp:outputConnectionStatus/><br/>  
           Time: <comp:outputText value="#{timebean.now}"/><br/>  
           Refresh Count: <comp:outputText value="#{timebean.refreshCount}"/><br/>  
           <comp:commandLink value="Refresh" action="#{timebean.refresh}"/>  
       </h:form>  
       </body>  
       </html>  
   </f:view>  

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="ice" uri="http://www.icesoft.com/icefaces" %>
<%@ taglib prefix="comp" uri="http://www.icesoft.com/icefaces/component" %>
<f:view>
    <html>
    <head>
        <title>ICEFaces Example</title>
    </head>
    <body>
    <h:form>
        <comp:outputConnectionStatus/><br/>
        Time: <comp:outputText value="#{timebean.now}"/><br/>
        Refresh Count: <comp:outputText value="#{timebean.refreshCount}"/><br/>
        <comp:commandLink value="Refresh" action="#{timebean.refresh}"/>
    </h:form>
    </body>
    </html>
</f:view>

 

次に、アプリケーションをアプリケーションサーバにパブリッシュし、2つのセッション(IEとFireFoxを仮定)を開いてページにアクセスすると、2つのブラウザにクロックが表示されます.このとき、どちらかがその「Refresh」ハイパーリンクをクリックすると、両方のブラウザウィンドウがリフレッシュされます.
これがサーバ側でAJAXのプッシュ技術を用いてDOMの更新を伝えるものである.微小なDOM更新は、帯域幅の消費を考慮しないのが一般的ですが、帯域幅が常に豊かではないことを覚えておいてください.ネットワークトラフィックが制限を超えているかどうかを測定する必要があります.
現在の問題は、直接使用するサーブレット仕様が2.4であることです.EJB 3の構文を使って構築するのは問題があります.EJB 2は「悪くて時代遅れのもの」で、remoteとhomeインタフェースの使用を要求せざるを得ない.このときSpringを使うと、いくつかの構成だけでほとんど欲しいものを提供することができます.
そのため、EJBのようなコンポーネントは必要ありません.それを使用していない場合でも、すべてを行うことができます.次の例では、この例ではあまり意味がないので、トランザクションを無視するつもりです.
Springの実現方法を見てみましょう.
Hello.java:
Javaコード

    package com.tss.beans;   
      
    public interface Hello {   
        String sayHello(String name);   
    }  

package com.tss.beans;

public interface Hello {
    String sayHello(String name);
}

 

HelloImpl.java:
Javaコード

    package com.tss.beans;   
      
    import java.util.Date;   
      
    public class HelloImpl implements Hello {   
        public String sayHello(String name) {   
            return "Hello, "+name+" ("+new Date()+")";   
        }   
    }  

package com.tss.beans;

import java.util.Date;

public class HelloImpl implements Hello {
    public String sayHello(String name) {
        return "Hello, "+name+" ("+new Date()+")";
    }
}

(ここでは、なぜ事務がこのbeanにとって重要ではないのかがわかるかもしれませんが)
今はWebでxmlはSpringを構成し、context-paramと2つのlistenerを加えます.それでWeb.xmlには以下の内容が追加されます.
web.xml(コンテンツの追加):
Xmlコード

    <context-param>  
           <param-name>contextConfigLocation</param-name>  
           <param-value>/WEB-INF/applicationContext*.xml</param-value>  
       </context-param>  
      
       <listener>  
           <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
       </listener>  
      
      <listener>  
          <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
      </listener>  

 <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext*.xml</param-value>
    </context-param>

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

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

同様に、新しいfaces-configを定義する必要があります.xmlファイルは、Springを使用して解析を支援するように設定されています.faces-config.xmlの設定は次のとおりです.
faces-config.xml:
Xmlコード

    <?xml version='1.0' encoding='UTF-8'?>  
    <faces-config xmlns="http://java.sun.com/xml/ns/javaee"  
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
                  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"  
                  version="1.2">  
        <application>  
            <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>  
        </application>  
    </faces-config>  

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">
    <application>
        <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
    </application>
</faces-config>

アプリケーションContextを見てみましょうxml、WEB-INFフォルダの下にあります.
applicationContext.xml:
Xmlコード

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans"  
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
           xmlns:jee="http://www.springframework.org/schema/jee"  
           xmlns:context="http://www.springframework.org/schema/context"  
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd   
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
        <context:annotation-config />  
       <bean id="renderManager" class="com.icesoft.faces.async.render.RenderManager" scope="singleton" />  
       <bean id="timebean" class="com.tss.beans.TimeBean" lazy-init="true" scope="session">  
           <property name="renderManager" ref="renderManager"/>  
       </bean>  
   </beans>  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
    <bean id="renderManager" class="com.icesoft.faces.async.render.RenderManager" scope="singleton" />
    <bean id="timebean" class="com.tss.beans.TimeBean" lazy-init="true" scope="session">
        <property name="renderManager" ref="renderManager"/>
    </bean>
</beans>

ここで重要なのは、renderManagerを参照するbeanごとにlazy-init="true"をこのように設定できることです.なぜなら、beanがロードされるとPersistentFacesStateも初期化される必要がないからです.
変更が発生すると、2つのブラウザ間で「example.iface」を呼び出してexampleにアクセスできます.jspページは、最初の非Springバージョンと同じように、毎秒更新を観察しています.Spring 2にもかかわらず5はかなり簡略化されていますが、必要に応じてTimeBean.JAvaはいくつかの修正をして、やはり意味があります.
ここではsetRenderManager()メソッドを変更して「initClock()」と名前を変更し、パラメータを削除して@PostConstructを加算する必要があります.そうすると、このbeanがインスタンス化されると「initClock()」メソッドがすぐに呼び出されます.
Javaコード

    @PostConstruct  
      public void initClock() {   
          System.out.println(renderManager);   
          clock = renderManager.getIntervalRenderer("clock");   
          clock.setInterval(interval);   
          clock.add(this);   
          clock.requestRender();   
      }  

  @PostConstruct
    public void initClock() {
        System.out.println(renderManager);
        clock = renderManager.getIntervalRenderer("clock");
        clock.setInterval(interval);
        clock.add(this);
        clock.requestRender();
    }

もちろんsetRenderManager()が少なくなるとrenderManagerへの注入が少なくなります.@Autowiredを追加できます
Javaコード
   @Autowired 
       RenderManager renderManager; 
@Autowired
    RenderManager renderManager;
再びアプリケーションContext.へxml、次のように変更します.
Xmlコード

    <bean id="renderManager" class="com.icesoft.faces.async.render.RenderManager" scope="singleton" />  
        <bean id="timebean" class="com.tss.beans.TimeBean" lazy-init="true" scope="session" />  

<bean id="renderManager" class="com.icesoft.faces.async.render.RenderManager" scope="singleton" />
    <bean id="timebean" class="com.tss.beans.TimeBean" lazy-init="true" scope="session" />

2つのbeanをバインドする表示はありません.SpringはautowireでTimeBeanのrenderManagerプロパティを自動的に検出し、そのプロファイルに登録されているbeanで唯一のインスタンスを見つけて注入します.これにより、構成がより容易になります.