2013-10-08 3 views
1

Я сконфигурированный JSF 2.1 в моем Google App применения двигателя в соответствии с указаниями на:Session потерял в Google App Engine с помощью JSF

https://sites.google.com/a/wildstartech.com/adventures-in-java/Java-Platform-Enterprise-Edition/JavaServer-Faces/javaserver-faces-21/configuring-javaserver-faces-21-to-run-on-the-google-app-engine-using-eclipse

Приложение отлично работает, когда работает локально, но сеанс теряется при развернутый в Google App Engine, например: значения компонентов теряются при обновлении любого другого компонента на странице, а также поля заголовка SessionScope.

Мой файл web.xml является:

<?xml version="1.0" encoding="utf-8" standalone="no"?> 
<web-app 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    version="2.5" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
    <display-name>JavaServerFaces</display-name>  

    <context-param> 
     <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
     <param-value>client</param-value> 
    </context-param> 
    <context-param> 
     <param-name>javax.faces.DEFAULT_SUFFIX</param-name> 
     <param-value>.xhtml</param-value> 
    </context-param> 
    <context-param> 
     <param-name>com.sun.faces.expressionFactory</param-name> 
     <param-value>org.jboss.el.ExpressionFactoryImpl</param-value> 
    </context-param> 
    <context-param> 
     <param-name>com.sun.faces.enableThreading</param-name> 
     <param-value>false</param-value> 
    </context-param>  
    <context-param> 
     <param-name>javax.faces.PROJECT_STAGE</param-name> 
     <param-value>Production</param-value> 
    </context-param> 
    <context-param> 
     <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name> 
     <param-value>true</param-value> 
    </context-param> 
    <context-param> 
     <param-name>primefaces.UPLOADER</param-name> 
     <param-value>commons</param-value> 
    </context-param> 
    <context-param> 
     <param-name>primefaces.THEME</param-name> 
     <param-value>home</param-value> 
    </context-param> 

    <!-- ***** Specify session timeout of thirty (30) minutes. ***** --> 
    <session-config> 
     <session-timeout>30</session-timeout> 
    </session-config> 

    <!-- Welcome page --> 
    <welcome-file-list> 
     <welcome-file>faces/home.xhtml</welcome-file> 
    </welcome-file-list> 

    <!-- JSF mapping --> 
    <servlet> 
     <servlet-name>Faces Servlet</servlet-name> 
     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Faces Servlet</servlet-name> 
     <url-pattern>/faces/*</url-pattern> 
     <url-pattern>*.jsf</url-pattern> 
     <url-pattern>*.xhtml</url-pattern> 
    </servlet-mapping> 

    <!-- Primefaces --> 
    <filter> 
     <filter-name>PrimeFaces FileUpload Filter</filter-name> 
     <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class> 
     <init-param> 
      <param-name>thresholdSize</param-name> 
      <param-value>2147483647</param-value> 
     </init-param>  
    </filter> 
    <filter-mapping> 
     <filter-name>PrimeFaces FileUpload Filter</filter-name> 
     <servlet-name>Faces Servlet</servlet-name> 
    </filter-mapping> 

    <error-page> 
     <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
     <location>/faces/home.xhtml</location> 
    </error-page> 

    <!-- System --> 
    <servlet> 
     <servlet-name>SystemServiceServlet</servlet-name> 
     <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class> 
     <init-param> 
      <param-name>services</param-name> 
      <param-value/> 
     </init-param> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>SystemServiceServlet</servlet-name> 
     <url-pattern>/_ah/spi/*</url-pattern> 
    </servlet-mapping> 
</web-app> 

И файл AppEngine-web.xml:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE project> 
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> 
    <application>id</application> 
    <version>1</version> 

    <!-- Allows App Engine to send multiple requests to one instance in parallel: --> 
    <threadsafe>true</threadsafe> 

    <!-- Configure java.util.logging --> 
    <system-properties> 
     <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" /> 
    </system-properties> 

    <sessions-enabled>true</sessions-enabled> 
    <async-session-persistence enabled="false" /> 
</appengine-web-app> 

ли JSF сессия действительно работает в Google App Engine? Я что-то упустил?

Заранее благодарен

ответ

3

Это распространенная проблема. Что вам нужно сделать, это сериализация силовой сессии. Это можно сделать, выполнив следующие действия:

  • Создание фазы Слушатель
  • В конце каждой фазы, хранить случайный атрибут в сессионный карте
    • например sessionMap.put («CURRENT_TIME», System.currentTimeMillis())
  • Это приведет к тому, что измененные данные для сериализации в датасторе

Причина вам нужно сделать что-то вроде этого, потому что, когда дерево представлений было построено, оно было добавлено в сеанс ... а затем ваша бизнес-логика внесла изменения в компоненты в дереве представлений, но, к сожалению, изменения, внесенные в эту переменную, не создают никаких событий, которые информируют GAE о сериализации снова , Именно поэтому вы увидите ViewExpiredExceptions или данные, которые не хранятся, и т. Д.

Эта концепция похожа на модель markDirty(), с которой вы могли столкнуться с другими технологиями просмотра.

+0

Вау, спасибо !! Это решило проблему !! Я все еще не понимаю причину, которую вы объясняете, разве это не должно быть связано с реализацией JSF, а не с сервером приложений? И почему это работает при работе на локальном компьютере? – akrog

+1

Дело в том, что сам объект сеанса привязан к спецификации сервлета, то есть контейнер управляет сеансом. В размещенной среде GAE/J вам необходимо разработать код, который гарантирует, что он будет осведомлен о кластере. Значение любого объекта, который находится в области сеанса, должен реализовывать Serializable. GAE/J сохраняет сеанс в хранилище данных (sudo clustering).К сожалению, в локальной среде нет сериализации, поэтому нет циклов поиска настойчивости. Следовательно, вы никогда не увидите сбоев в локальной среде. –

+2

Далее, чтобы быть эффективными GAE/J отслеживает, грязна ли карта сессии * или нет. Когда вы обновляете его с помощью простых значений (например, в примере), он замечает изменения. Но если вы измените некоторую внутреннюю переменную какого-либо объекта на карте, нет никакого способа, чтобы GAE/J знал, что карта сеанса должна сохраняться в конце запроса. Поэтому мы добавляем этот небольшой взлом. Причина, по которой мы делаем это на всех этапах, состоит в том, что рендер-ответ можно вызвать на любой фазе (например, отказ проверки/перенаправление/и т. Д.). Надеюсь, эта информация вам поможет. –

2

Основываясь на моем понимании ответа Харши, я публикую решение, которое я использовал в случае интереса для кого-либо еще.

В GaeSession.java:

public class GaeSession implements PhaseListener { 
    private static final long serialVersionUID = 1L; 

    @Override 
    public void afterPhase(PhaseEvent arg0) { 
     FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("CURRENT_TIME", System.currentTimeMillis()); 
    } 

    @Override 
    public void beforePhase(PhaseEvent arg0) { 
    } 

    @Override 
    public PhaseId getPhaseId() { 
     return PhaseId.ANY_PHASE; 
    } 

} 

И в лицах-config.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<faces-config 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" 
    version="2.2"> 

    <lifecycle> 
     <phase-listener>package.GaeSession</phase-listener> 
    </lifecycle> 

</faces-config> 
Смежные вопросы