Session Bean Gets Lost in GAE using JSF and Primefaces

0 views
Skip to first unread message

user2048819 via StackOverflow

unread,
Feb 6, 2013, 6:28:40 PM2/6/13
to google-appengin...@googlegroups.com

I have been digging for quite a long time on how to make jsf and session beans work on google app engine. The problem is that the bean gets lost at every request if I use in the web.xml file:

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

and if I use:

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

The google app engine yields a string out of bound error not sure why. Here it is:

/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)

The thing is that the app works perfectly in the local development server.

I'm using GAE-1.7.4.

Here are some of the stuff I have read so far and did not get a conclusive answer:

  1. http://consultingblogs.emc.com/jaddy/archive/2009/11/20/jsf2-in-google-app-engine.aspx
  2. JSF2 with GAE and ViewScoped ManagedBean
  3. Session Bean being lost?

Hope it is not some silly situation. Thanks in advance.



Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/14740847/session-bean-gets-lost-in-gae-using-jsf-and-primefaces

user2048819 via StackOverflow

unread,
Feb 6, 2013, 7:58:56 PM2/6/13
to google-appengin...@googlegroups.com

I have been digging for quite a long time on how to make jsf and session beans work on google app engine. The problem is that the bean gets lost at every request if I use in the web.xml file:

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

This makes on the local development a hidden field be created in the page of the client which encode the view state in base64.

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

And supposedly in the google server would be the same. But the result seems wierd.

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

user2048819 via StackOverflow

unread,
Feb 6, 2013, 8:09:00 PM2/6/13
to google-appengin...@googlegroups.com

How ever if a take the view state value for the local deplyment and edit the source code provided by the gae the session seems to hold!

user2048819 via StackOverflow

unread,
Feb 9, 2013, 6:48:05 AM2/9/13
to google-appengin...@googlegroups.com

I'm using GAE-1.7.4.

UPDATE: I was able to concluded, using:

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

That the session bean was not being created at every single page request but for some unknown reason, the values are being setted to their defaults. I am starting to think that is better to use cookies and reload them in to the bean, as a fix at every single page request. I don't see any other way out of this.

user2048819 via StackOverflow

unread,
Feb 9, 2013, 6:53:05 AM2/9/13
to google-appengin...@googlegroups.com

That the session bean was not being created at every single page request but for some unknown reason, the values are being setted to their defaults. I am starting to think that is better to use cookies and reload them in to the bean, as a fix at every single page request. I don't see any other way out of this. May be I will use AES to encrypt some of the cookies for extra security.

user2048819 via StackOverflow

unread,
Feb 9, 2013, 8:08:11 AM2/9/13
to google-appengin...@googlegroups.com

Note that in the file appengine-web.xml there is the required:

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

UPDATE 1: I was able to concluded, using:

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

That the session bean was not being created at every single page request but for some unknown reason, the values are being setted to their defaults. I am starting to think that is better to use cookies and reload them in to the bean, as a fix at every single page request. I don't see any other way out of this. May be I will use AES to encrypt some of the cookies for extra security.

UPDATE 2: Again tried the following: 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;

impo

rt 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;
}

}

And in the .xhtml of the facelet

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

With no result the data just won't hold via session or cookies.

user2048819 via StackOverflow

unread,
Feb 9, 2013, 11:18:24 AM2/9/13
to google-appengin...@googlegroups.com
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;
}

}

user2048819 via StackOverflow

unread,
Feb 9, 2013, 11:38:26 AM2/9/13
to google-appengin...@googlegroups.com

Hope it is not some silly situation. Thanks in advance.

UPDATE 3:

"Not supported There are various APIs and technologies that are not supported by App Engine at present for various reasons. These include:

Enterprise Java Beans (EJB)"

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

Tested session variables with out java beans and it works fine.

user2048819 via StackOverflow

unread,
Feb 9, 2013, 4:30:13 PM2/9/13
to google-appengin...@googlegroups.com

UPDATE 4:

You can't in GAE just write a object to session because its attributes values will get lost. I suspect that EJB does this. Maybe they could just serialize the object using JSON I don't know. I am sure that is a work around. I added a thread asking for this feature in:

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

Don't sure if this is the group responsible for developing the EJB just for jboss, though... Any way if you want this feature may be you should make some noise in that thread.

Reply all
Reply to author
Forward
0 new messages