javax.yüzler.uygulama.ViewExpiredException: Görünüm geri yüklenemedi

konteyner tarafından yönetilen güvenlik ile basit bir uygulama yazdım. Sorun, oturum açtığımda ve oturum açtığım başka bir sayfayı açtığımda, ilk sayfaya geri döndüm ve bu istisnayı aldığım herhangi bir bağlantıyı vb.veya yenileme sayfasını tıklıyorum. Sanırım normal (ya da belki de değil:)) çünkü giriş yaptım ve oturum yok edildi. Kullanıcıyı örneğin dizine yönlendirmek için ne yapmalıyım.xhtml veya giriş.xhtml ve onu bu hata sayfasını / mesajını görmekten kurtarın mı?

içinde diğer kelimeler giriş yaptıktan sonra diğer sayfaları otomatik olarak dizin/giriş sayfasına nasıl yönlendirebilirim?

İşte:

javax.faces.application.ViewExpiredException: viewId:/index.xhtml - View /index.xhtml could not be restored.
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:212)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at filter.HttpHttpsFilter.doFilter(HttpHttpsFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
    at java.lang.Thread.run(Thread.java:619)
151
tarihinde sordu BalusC 2010-09-04 19:45:31
kaynak

10 ответов

giriş

'1519740920 ViewExpiredException javax.faces.STATE_SAVING_METHOD server (varsayılan) olarak ayarlandığında ve enduser <h:form> ile <h:commandLink> , <h:commandButton> veya <f:ajax> ile bir görünümde bir HTTP POST isteği gönderirken , ilişkili görünüm durumu artık oturumda mevcut değil.

görünüm durumu, <h:form> gizli giriş alanının javax.faces.ViewState değeri olarak tanımlanır . Devlet ile kaydetme yöntemi server olarak ayarlayın, bu yalnızca oturumdaki seri hale getirilmiş görünüm durumuna başvuran görünüm durumu kimliği içerir. Bu nedenle, oturum herhangi bir nedenden dolayı sona erdiğinde (sunucu veya istemci tarafında zaman aşımına uğradı veya Oturum çerezi tarayıcıda herhangi bir nedenle artık korunmadı veya sunucuda HttpSession#invalidate() çağırarak veya WildFly olarak bilinen oturum çerezlerine sahip bir sunucuya özgü hata nedeniyle), daha sonra seri hale getirilmiş görünüm durumu artık mevcut değil. oturum ve son kullanıcı bu istisnayı alacak. Oturumun çalışmasını anlamak için bkz. servlets nasıl çalışır? Örnek oluşturma, oturumlar, paylaşılan değişkenler ve çok iş parçacıklı .

oturumda jsf'nin depolayacağı görüş miktarına ilişkin bir sınır da vardır. Sınır vurulduğunda, en az kullanılan görünüm sona erecektir. Ayrıca bakınız com.güneşlendirmek.yüzler.numberOfViewsİnSession vs com.güneşlendirmek.yüzler.numberOfLogicalViews .

client olarak ayarlanmış durum kaydetme yöntemi ile javax.faces.ViewState gizli giriş alanı yerine tüm seri hale getirilmiş görünüm durumunu içerir, bu nedenle son kullanıcı oturum sona erdiğinde ViewExpiredException almaz. Ancak yine de bir küme ortamında ("hata: Mac doğrulamadı" semptomatiktir) ve/veya istemci tarafında yapılandırılmış ve/veya sunucu sırasında AES anahtarını yeniden ürettiğinde uygulamaya özgü bir zaman aşımı olduğunda gerçekleşebilir yeniden başlatma, bkz. ayrıca alma ViewExpiredException kümelenmiş ortamda durum kaydetme yöntemi istemci ve kullanıcı oturumuna ayarlanır ise geçerli nasıl çözülür.

ne olursa olsun çözüm, yapmak emin olun değil kullanın enableRestoreView11Compatibility . orijinal görünüm durumunu hiç geri yüklemez. Temelde görünümü ve tüm ilişkili görünümü sıfırdan taranmış fasulye yeniden oluşturur ve bu nedenle tüm orijinal verileri (devlet) kaybediyor. Uygulama kafa karıştırıcı bir şekilde davranacağından ("hey, giriş değerlerim nerede..??"), bu kullanıcı deneyimi için çok kötü. Stateless views veya <o:enableRestorableView> yerine daha iyi kullanın, böylece yalnızca tüm görünümler yerine belirli bir görünümde yönetebilirsiniz.

, neden JSF'NİN görünüm durumunu kaydetmesi gerekiyor, bu cevabın başında: neden JSF, UI bileşenlerinin durumunu sunucuda kaydeder?

. Sayfa gezinme

üzerinde ViewExpiredException

, ViewExpiredException durum tasarrufu server olarak ayarlandığında, çıkıştan sonra geri giderken ViewExpiredException önlemek için, yalnızca çıkış sonrası isteği yeniden yönlendirme yeterli değildir. Ayrıca değil dinamik JSF sayfaları önbellek için tarayıcı talimat gerekir, aksi takdirde tarayıcı yerine bir GET isteği gönderdiğinizde sunucudan yeni bir talep önbellekten gösterebilir (örneğin geri düğmesi ile).

önbelleğe alınmış sayfanın javax.faces.ViewState gizli alanı, geçerli oturumda artık geçerli olmayan bir görünüm durumu kimliği değeri içerebilir. Sayfadan sayfaya gezinme için (normal bağlantılar/düğmeler)almak yerine (AB) POST (komut bağlantıları/düğmeleri) kullanıyorsanız ve önbelleğe alınmış sayfadaki böyle bir komut bağlantısı/düğmesini tıklarsanız, bu da ViewExpiredException ile başarısız olur.

, JSF 2.0'da oturum açtıktan sonra bir yönlendirme başlatmak için <redirect /> söz konusu <navigation-case> (varsa) veya ?faces-redirect=true değerini outcome değerine ekleyin.

<h:commandButton value="Logout" action="logout?faces-redirect=true" />

veya

public String logout() {
    // ...
    return "index?faces-redirect=true";
}

, dinamik JSF sayfalarını önbelleğe almamasını, FacesServlet servlet adına eşlenen ve tarayıcı önbelleğini devre dışı bırakmak için gerekli yanıt başlıklarını ekleyen Filter oluşturun. E. g.

@WebFilter(servletNames={"Faces Servlet"}) // Must match <servlet-name> of your FacesServlet.
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
            res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            res.setDateHeader("Expires", 0); // Proxies.
        }

        chain.doFilter(request, response);
    }

    // ...
}

- sayfa üzerinde ViewExpiredException yenileme

devlet tasarrufu server olarak ayarlandığında Geçerli sayfayı yenilerken ViewExpiredException önlemek için, sadece almak (düzenli bağlantılar/düğmeler) tarafından sadece sayfa-sayfa navigasyon performans emin olmak gerekir, ama aynı zamanda formları göndermek için Ajax kullanarak münhasıran emin olmak gerekir. Formu eşzamanlı olarak (ajax olmayan) gönderiyorsanız, görünümü stateless (daha sonraki bölüme bakınız) veya göndermek için en iyi şekilde yaparsınız sonrası bir yönlendirme (önceki bölüme bakın).

sayfa yenileme ViewExpiredException sahip varsayılan yapılandırma çok nadir bir durumdur. Yalnızca oturumda jsf'nin depolayacağı görüş miktarına ilişkin sınır vurulduğunda gerçekleşebilir. Bu nedenle, yalnızca bu sınırı çok düşük bir şekilde manuel olarak ayarladığınızda veya arka planda sürekli olarak yeni görünümler oluşturduğunuzda (örn. kötü uygulanan bir anket ile) olur. Ayrıca bakınız com.güneşlendirmek.yüzler.numberOfViewsİnSession vs com.güneşlendirmek.yüzler.numberOfLogicalViews . Başka bir neden, çalışma zamanı classpath'de yinelenen JSF kitaplıklarına sahip. JSF yüklemek için doğru prosedür bizim JSF wiki sayfa özetlenmiştir .

- ViewExpiredException

oturum açarken bazı tarayıcı sekmesinde/penceresinde zaten açılmış keyfi bir sayfada bir yazı eyleminden sonra ViewExpiredException kaçınılmaz bir

işlemek istediğinizde başka bir sekmede / pencerede, "oturumunuz zaman aşımına uğradı" sayfasına giden error-page de bunun için error-page belirtmek istersiniz. E. g.

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/WEB-INF/errorpages/expired.xhtml</location>
</error-page>

aslında redirect ev veya giriş sayfasına daha fazla niyetinde durumunda hata sayfasında bir meta yenileme Başlığı gerekirse kullanın.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Session expired</title>
        <meta http-equiv="refresh" content="0;url=#{request.contextPath}/login.xhtml" />
    </head>
    <body>
        <h1>Session expired</h1>
        <h3>You will be redirected to login page</h3>
        <p><a href="#{request.contextPath}/login.xhtml">Click here if redirect didn't work or when you're impatient</a>.</p>
    </body>
</html>

( 0 içinde content saniye önce miktarını temsil eder yönlendirme, 0 böylece "hemen yönlendirme" anlamına gelir, örneğin kullanabilirsiniz 3 tarayıcı yönlendirme ile 3 saniye bekleyin izin)

ajax istekleri sırasında özel durumları işleme özel bir ExceptionHandler gerektirir unutmayın . Ayrıca oturum zaman aşımı ve JSF/primefaces ajax isteği üzerinde ViewExpiredException işleme bakın. Canlı bir örnek OmniFaces FullAjaxExceptionHandler vitrin sayfa (bu ayrıca ajax olmayan istekleri kapsar).

ayrıca, "genel" hata sayfanızın <error-code> 500 yerine <exception-type> veya java.lang.Exception veya java.lang.Throwable üzerinde eşleştirilmesi gerektiğini, aksi takdirde ServletException gibi ViewExpiredException ile sarılan tüm istisnalar hala genel hata sayfasında sona erecektir. Ayrıca Bkz. Java'da gösterilen ViewExpiredException.dil.Web Throwable hata sayfası.xml .

<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/errorpages/general.xhtml</location>
</error-page>

Stateless views

tamamen farklı bir alternatif, JSF görünümlerini durumsuz modda çalıştırmaktır. Bu şekilde JSF devletinin hiçbir şey kaydedilmeyecek ve görünümler asla sona ermeyecek, ancak her istek üzerine sıfırdan yeniden inşa edilecek. transient özniteliğini <f:view> ile true olarak ayarlayarak durumsuz görünümleri açabilirsiniz:

<f:view transient="true">

</f:view>

bu şekilde javax.faces.ViewState gizli alan "stateless" sabit bir değer alacak Mojarra(bu noktada yüzümü kontrol etmedim). Bu özelliğin mojarra 2.1.19 ve 2.2.0'da tanıtıldığını ve eski sürümlerde mevcut olmadığını unutmayın.

sonuç, taraklı fasulyeleri artık kullanamazsınız. Şimdi taraklı fasulye gibi davranacaklar. Dezavantajlardan biri, gizli girdilerle ve/veya gevşek istek parametreleriyle uğraşarak durumu kendiniz izlemeniz gerektiğidir. Esas olarak giriş alanları olan formlar rendered ile readonly veya disabled Ajax olayları tarafından kontrol edilen öznitelikler etkilenecektir.

<f:view> mutlaka görünüm boyunca benzersiz olması ve/veya yalnızca ana şablonda bulunması gerekmez unutmayın. Ayrıca, redeclare için tamamen okunaklı ve bir şablon istemcisine yerleştirildi. Temel olarak <f:view> ebeveynini" genişletir". E. g. ana şablonda:

<f:view contentType="text/html">
    <ui:insert name="content" />
</f:view>

ve şablon müşteri:

<ui:define name="content">
    <f:view transient="true">
        <h:form>...</h:form>
    </f:view>
</f:view>

koşullu hale getirmek için <f:view> yi <c:if> olarak bile sarabilirsiniz. tüm görünümünde, yalnızca yukarıdaki örnekte <h:form> gibi iç içe geçmiş içerikler üzerinde geçerli olacağını unutmayın.

Ayrıca bakınız


saf sayfadan sayfaya gezinme için HTTP GÖNDERİSİNİ kullanarak somut soruna ile ilgisi olmayan çok kullanıcı/SEO dostu değildir. JSF 2.0'da gerçekten <h:link> veya <h:button> yi tercih etmelisiniz <h:commandXxx> düz vanilya sayfa-sayfa navigasyon için olanlar.

örneğin

yerine
<h:form id="menu">
    <h:commandLink value="Foo" action="foo?faces-redirect=true" />
    <h:commandLink value="Bar" action="bar?faces-redirect=true" />
    <h:commandLink value="Baz" action="baz?faces-redirect=true" />
</h:form>

daha iyi

<h:link value="Foo" outcome="foo" />
<h:link value="Bar" outcome="bar" />
<h:link value="Baz" outcome="baz" />

Ayrıca bakınız

313
cevap BalusC 2017-05-23 15:10:41
kaynak

web.xml için aşağıdaki satırları eklemeyi denediniz mi ?

<context-param>
   <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
   <param-value>true</param-value>
</context-param>

bu sorunla karşılaştığımda bunu çok etkili buldum.

50
cevap Mike GH 2013-05-30 12:54:54
kaynak

ilk ne yapmanız gereken, web değiştirmeden önce.xml , ManagedBean implements Serializable :

@ManagedBean
@ViewScoped
public class Login implements Serializable {
}

özellikle MyFaces

kullanırsanız
5
cevap ZuzEL 2013-07-28 18:58:09
kaynak

Richfaces çok parçalı formları önlemek:

<h:form enctype="multipart/form-data">
    <a4j:poll id="poll" interval="10000"/>
</h:form>

Richfaces kullanıyorsanız, ajax isteklerinin çok parçalı formların içinde her istek üzerine yeni bir görünüm kimliği döndürdüğünü buldum.

hata ayıklama:

Her ajax isteğinde

Görünüm kimliği her zaman aynı olduğu sürece bir görünüm kimliği döndürülür. Her istek üzerine yeni bir görünüm kimliği alırsanız, o zaman bir sorun ve sabit olmalıdır.

3
cevap tak3shi 2017-03-24 15:24:55
kaynak

kendi özel AjaxExceptionHandler veya primefaces-uzantıları

kullanabilirsiniz

yüzlerinizi güncelleyin-yapılandırma.xml

...
<factory>
  <exception-handler-factory>org.primefaces.extensions.component.ajaxerrorhandler.AjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
...

JSF sayfanıza aşağıdaki kodu ekleyin

...
<pe:ajaxErrorHandler />
...
0
cevap myset 2014-01-11 14:00:50
kaynak

bu hatayı alıyordum : javax.yüzler.uygulama.ViewExpiredException.Farklı istekler kullandığımda, sunucuyu yeniden başlattıktan sonra bile aynı Jsessionıd'ye sahip olanları buldum. Bu nedenle tarayıcı önbelleğinden kaynaklanmaktadır. Sadece tarayıcıyı kapatın ve deneyin, işe yarayacak.

0
cevap rahul 2014-10-05 18:44:47
kaynak

sayfamız zaman x miktarı için boşta olduğunda görünüm sona erecek ve javax atmak.yüzler.uygulama.Bunun olmasını önlemek için ViewExpiredException bir çözüm ViewHandler genişleten CustomViewHandler oluşturmaktır ve override restoreView yöntemi diğer tüm yöntemler üst

için temsilci
import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

public class CustomViewHandler extends ViewHandler {
    private ViewHandler parent;

    public CustomViewHandler(ViewHandler parent) {
        //System.out.println("CustomViewHandler.CustomViewHandler():Parent View Handler:"+parent.getClass());
        this.parent = parent;
    }

    @Override 
    public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
    /**
     * {@link javax.faces.application.ViewExpiredException}. This happens only  when we try to logout from timed out pages.
     */
        UIViewRoot root = null;
        root = parent.restoreView(facesContext, viewId);
        if(root == null) {
            root = createView(facesContext, viewId);
        }
        return root;
    }

    @Override
    public Locale calculateLocale(FacesContext facesContext) {
        return parent.calculateLocale(facesContext);
    }

    @Override
    public String calculateRenderKitId(FacesContext facesContext) {
        String renderKitId = parent.calculateRenderKitId(facesContext);
        //System.out.println("CustomViewHandler.calculateRenderKitId():RenderKitId: "+renderKitId);
        return renderKitId;
    }

    @Override
    public UIViewRoot createView(FacesContext facesContext, String viewId) {
        return parent.createView(facesContext, viewId);
    }

    @Override
    public String getActionURL(FacesContext facesContext, String actionId) {
        return parent.getActionURL(facesContext, actionId);
    }

    @Override
    public String getResourceURL(FacesContext facesContext, String resId) {
        return parent.getResourceURL(facesContext, resId);
    }

    @Override
    public void renderView(FacesContext facesContext, UIViewRoot viewId) throws IOException, FacesException {
        parent.renderView(facesContext, viewId);
    }

    @Override
    public void writeState(FacesContext facesContext) throws IOException {
        parent.writeState(facesContext);
    }

    public ViewHandler getParent() {
        return parent;
    }

}   

sonra faces-config eklemek gerekir.xml

<application>
    <view-handler>com.demo.CustomViewHandler</view-handler>
</application>

aşağıda orijinal cevap için teşekkürler bağ: http://www.gregbugaj.com/?p=164

0
cevap user4924157 2016-05-13 09:45:29
kaynak

lütfen bu satırı webinize ekleyin.xml Benim için çalışıyor

<context-param>
        <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name> 
        <param-value>true</param-value>     
    </context-param>
-2
cevap harshal 2014-06-13 19:21:05
kaynak

bu soruna kendim rastladım ve appliation üzerindeki tüm istekleri filtreleyen bir filtrenin yan etkisi nedeniyle olduğunu fark ettim. Filtreyi yalnızca belirli istekleri almak için değiştirdiğimde, bu sorun oluşmadı. Uygulamanızda bu tür filtreleri kontrol etmek ve nasıl davrandıklarını görmek iyi olabilir.

-2
cevap javshak 2014-06-25 13:40:26
kaynak

aşağıdaki yapılandırmayı web'e ekliyorum.xml ve çözüldü.

<context-param>
    <param-name>com.sun.faces.numberOfViewsInSession</param-name>
    <param-value>500</param-value>
</context-param>
<context-param>
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>500</param-value>
</context-param>
-3
cevap Mohamed Ali 2012-11-10 13:50:47
kaynak