2

ファイル appengine-web.xml には、次の必須項目があることに注意してください。

<sessions-enabled>true</sessions-enabled>

私はかなり長い間、jsf とセッション Bean を Google App Engine で動作させる方法を掘り下げてきました。問題は、web.xml ファイルで使用すると、リクエストごとに Bean が失われることです。

<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>

これにより、ローカル開発で、ビューステートをbase64でエンコードするクライアントのページに隠しフィールドが作成されます。

<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState"
value="H4sIAAAAAAAAAE1QO0sDQRAe73LxLTGClelsLDwQLEQLDWjwMD4QFMFCN3drcmHv9txHcmcRSKOFjYUWFqKFZf6EWNgJWlqJvbWtuyEmDuwwuzPzPbb1DVbEGYxXUQ3ZUvjEXke8sokiq//j6Xny+M0EowBDhCKvgFxBmQODosIwr1DixdHyCugYqQ+onFHHFDDl0sDmMrRPkIu5vZqEKPDdvCt8GnLFNdHjyjOGkqLPRdx8z92+oDsT+hxIcf8Mx5EGrqd0jgWMVo98T8wvKmZJhFQoh8U2DkFh2d4uVbErlq5eD+4zfIYYakWvpyIVAiy9OydPoQFp9Wp0K0v3uzezwWBWY8Yd5cpHREMcCnvP2fdxfZdSMb3DaISZSDZwwqETWcXHYKynZy2Uwf+mEpEmiAvH6/51e84JBS5jlv16ePxpXiwY2r1VQ0RihZfpzW3JoITZeesmN3z9eflnT8mPfwGGpwEXwQEAAA==" autocomplete="off" />

おそらくGoogleサーバーでも同じでしょう。しかし、結果は奇妙に思えます。

<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState"
value="-7485706817535542099:-1131777842892951150" autocomplete="off" />

私が使用する場合:

<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

Google アプリ エンジンは、原因不明の範囲外の文字列エラーを生成します。ここにあります:

/Trainer.jsf
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(String.java:1949)
    at com.sun.faces.renderkit.ServerSideStateHelper.getState(ServerSideStateHelper.java:277)
    at com.sun.faces.renderkit.ResponseStateManagerImpl.getState(ResponseStateManagerImpl.java:100)
    at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:352)
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:138)
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:518)
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:142)
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:192)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
    at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:447)
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:454)
    at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:461)
    at com.google.tracing.TraceContext.runInContext(TraceContext.java:703)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:338)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:330)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:458)
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
    at java.lang.Thread.run(Thread.java:679)

問題は、アプリがローカル開発サーバーで完全に機能することです。

GAE-1.7.4 を使用しています。

これまでに読んだものの、決定的な答えが得られなかったもののいくつかを次に示します。

  1. http://consultingblogs.emc.com/jaddy/archive/2009/11/20/jsf2-in-google-app-engine.aspx
  2. GAE と ViewScoped ManagedBean を使用した JSF2
  3. セッション Bean が失われていますか?

ばかげた状況ではないことを願っています。前もって感謝します。

更新 1: 以下を使用して、結論を出すことができました。

FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Warning building CardController", null));

セッション Bean はページ要求ごとに作成されていませんでしたが、不明な理由で、値がデフォルトに設定されています。私は、すべてのページ要求の修正として、Cookie を使用して Bean に再読み込みする方がよいと考え始めています。これ以外に方法はありません。セキュリティを強化するために、AES を使用して一部の Cookie を暗号化する場合があります。

更新 2: 再度次のことを試しました。

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;

import com.google.gson.Gson;

@SuppressWarnings("serial")
public class Counter implements Serializable{

public int counter;

public Counter() {
    counter = -1;
}

public String getCounter(){
    counter++;
    return counter+"";
}




public String getSetCounter(){
    Gson gson = new Gson();
    HttpServletResponse res = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
    Cookie cookie = new Cookie(this.hashCode()+"",gson.toJson(this));
    cookie.setMaxAge(60*60); //1 hour
    res.addCookie(cookie);
    return "Write Counter";
}

public String getReadCounter(){
    Gson gson = new Gson();
    Cookie cookieJSON = getCookie();
    if(cookieJSON!=null){
        Counter counter = gson.fromJson(cookieJSON.getValue(), Counter.class);
        this.counter = counter.counter;
    }
    return "Read Counter";
}

private Cookie getCookie(){
    HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
    Cookie[] cookies = req.getCookies();
    Cookie cookieJSON = null;
    if(cookies!=null){
        List<Cookie> cookiesList = Arrays.asList();
        cookieJSON = (Cookie) CollectionUtils.find(cookiesList, new Predicate() {
            @Override
            public boolean evaluate(Object cookie) {
                return ((Cookie)cookie).getName().equals(Counter.this.hashCode()+"");
            }
        });
    }
    return cookieJSON;
}

}

そして、facelet の .xhtml で

<h:outputText value="#{counter.readCounter}"/>
<br />
<h:outputText value="#{counter.counter}"/>
<br />
<h:outputText value="#{counter.setCounter}"/>

結果がなければ、データはセッションまたは Cookie を介して保持されません。

更新 3:

「サポートされていません さまざまな理由により、現在 App Engine でサポートされていないさまざまな API とテクノロジーがあります。これらには、次のようなものがあります。

エンタープライズ Java Bean (EJB)」

http://code.google.com/p/googleappengine/wiki/WillItPlayInJava

Java Bean を使用しないでセッション変数をテストしたところ、正常に動作しました。

更新 4:

オブジェクトの属性値が失われるため、GAE では単にオブジェクトをセッションに書き込むことはできません。EJB がこれを行っているのではないかと思います。たぶん、彼らは私が知らないJSONを使用してオブジェクトをシリアル化することができました. 私はそれが回避策であると確信しています。この機能を求めるスレッドを次の場所に追加しました。

https://community.jboss.org/thread/221125?tstart=0

ただし、これが jboss のためだけに EJB の開発を担当するグループであるかどうかはわかりません... この機能が必要な場合は、そのスレッドで何らかの騒ぎを起こす必要があります。

4

0 に答える 0