javax.faces.application.ViewExpiredException: nie można przywrócić widoku

175

Napisałem prostą aplikację z zabezpieczeniami zarządzanymi przez kontener. Problem polega na tym, że kiedy loguję się i otwieram inną stronę, na której się wylogowuję, wracam do pierwszej strony i klikam na dowolny link itp. Lub odświeżam stronę, otrzymuję ten wyjątek. Chyba to normalne (a może nie :)), bo się wylogowałem i sesja jest zniszczona. Co powinienem zrobić, aby przekierować użytkownika na przykład do index.xhtml lub login.xhtml i uchronić go przed wyświetleniem strony / komunikatu błędu?

Innymi słowy, jak mogę automatycznie przekierować inne strony do strony indeksu / logowania po wylogowaniu?

Oto ona:

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)
l245c4l
źródło

Odpowiedzi:

353

Wprowadzenie

ViewExpiredExceptionZostanie wyrzucony, gdy javax.faces.STATE_SAVING_METHODjest ustawiony na server(domyślnie), a Użytkownik końcowy wysyła żądanie HTTP POST w widoku poprzez <h:form>z <h:commandLink>, <h:commandButton>lub <f:ajax>, gdy stan związany widok nie jest dostępny w sesji już.

Stan widoku jest identyfikowany jako wartość pola ukrytego wejścia javax.faces.ViewStatez <h:form>. Gdy metoda zapisywania stanu jest ustawiona na server, zawiera tylko identyfikator stanu widoku, który odwołuje się do serializowanego stanu widoku w sesji. Tak więc, gdy sesja wygaśnie z jakiegoś powodu (przekroczono limit czasu po stronie serwera lub klienta, lub plik cookie sesji nie jest już przechowywany z jakiegoś powodu w przeglądarce lub przez wywołanie HttpSession#invalidate()serwera lub z powodu błędu specyficznego dla serwera z plikami cookie sesji jako znany w WildFly ), to stan widoku serializowanego nie jest już dostępny w sesji i użytkownik końcowy otrzyma ten wyjątek. Aby zrozumieć działanie sesji, zobacz także Jak działają serwlety? Tworzenie instancji, sesje, zmienne współdzielone i wielowątkowość .

Istnieje również ograniczenie liczby wyświetleń, które JSF będzie przechowywać w sesji. Gdy limit zostanie osiągnięty, najdłużej używany widok wygaśnie. Zobacz także com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews .

Po ustawieniu metody zapisywania stanu na client, javax.faces.ViewStateukryte pole wejściowe zawiera zamiast tego cały stan widoku serializowanego, więc użytkownik końcowy nie otrzyma ViewExpiredExceptionpo wygaśnięciu sesji. Może się to jednak zdarzyć w środowisku klastra („BŁĄD: nie zweryfikowano adresu MAC” jest symptomatyczne) i / lub gdy po skonfigurowaniu stanu po stronie klienta występuje limit czasu specyficzny dla implementacji i / lub gdy serwer ponownie generuje klucz AES podczas ponownego uruchamiania zobacz także Uzyskiwanie wyjątku ViewExpiredException w środowisku klastrowym, gdy metoda zapisywania stanu jest ustawiona na klienta, a sesja użytkownika jest prawidłowa, jak go rozwiązać.

Niezależnie od rozwiązania upewnij się, że nie używasz enableRestoreView11Compatibility. w ogóle nie przywraca pierwotnego stanu widoku. Zasadniczo odtwarza widok i wszystkie powiązane komponenty bean o zasięgu widoku od zera, tracąc w ten sposób wszystkie oryginalne dane (stan). Ponieważ aplikacja będzie zachowywać się w mylący sposób („Hej, gdzie są moje wartości wejściowe… ??”), jest to bardzo niekorzystne dla użytkownika. Lepiej używaj widoków bezstanowych lub <o:enableRestorableView>zamiast tego możesz zarządzać nim tylko w określonym widoku zamiast we wszystkich widokach.

Jeśli chodzi o dlaczego JSF musi zapisywać stan widoku, przejdź do odpowiedzi: Dlaczego JSF zapisuje stan komponentów UI na serwerze?

Unikanie ViewExpiredException podczas nawigacji po stronie

Aby uniknąć ViewExpiredExceptionnp. Nawigacji powrotnej po wylogowaniu, kiedy ustawiono zapis stanu server, samo przekierowanie żądania POST po wylogowaniu nie jest wystarczające. Musisz także poinstruować przeglądarkę, aby nie buforowała dynamicznych stron JSF w pamięci podręcznej, w przeciwnym razie przeglądarka może wyświetlać je z pamięci podręcznej zamiast żądać nowej z serwera, gdy wysyłasz żądanie GET (np. Za pomocą przycisku Wstecz).

javax.faces.ViewStatePole ukryte w pamięci podręcznej może zawierać wartość identyfikatora widok członkowskich, które nie obowiązują już w bieżącej sesji. Jeśli (ab) używasz POST (linki / przyciski poleceń) zamiast GET (zwykłe linki / przyciski) do nawigacji między stronami i klikniesz taki link / przycisk polecenia na stronie w pamięci podręcznej, to z kolei nie uda się z ViewExpiredException.

Aby uruchomić przekierowanie po wylogowaniu w JSF 2.0, dodaj <redirect />do <navigation-case>pytania (jeśli istnieje) lub dodaj ?faces-redirect=truedo outcomewartości.

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

lub

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

Aby poinstruować przeglądarkę, aby nie buforowała dynamicznych stron JSF, utwórz plik, Filterktóry jest mapowany na nazwę serwletu FacesServleti dodaje potrzebne nagłówki odpowiedzi, aby wyłączyć pamięć podręczną przeglądarki. Na przykład

@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);
    }

    // ...
}

Unikanie ViewExpiredException podczas odświeżania strony

Aby uniknąć ViewExpiredExceptionodświeżania bieżącej strony, gdy zapisywanie stanu jest ustawione na server, musisz nie tylko upewnić się, że nawigacja między stronami odbywa się wyłącznie za pomocą GET (zwykłe linki / przyciski), ale także upewnij się, że że do przesyłania formularzy używasz wyłącznie Ajax. Jeśli i tak przesyłasz formularz synchronicznie (bez AJAX), to najlepiej byłoby albo uczynić widok bezstanowym (zobacz dalszą sekcję), albo wysłać przekierowanie po POST (zobacz poprzednią sekcję).

Mając ViewExpiredExceptionna stronie odświeżanie jest w domyślnej konfiguracji to bardzo rzadki przypadek. Może się to zdarzyć tylko wtedy, gdy zostanie osiągnięty limit ilości wyświetleń, które JSF będzie przechowywać w sesji. Tak więc stanie się to tylko wtedy, gdy ręcznie ustawisz ten limit zbyt nisko, lub jeśli ciągle tworzysz nowe widoki w "tle" (np. Przez źle zaimplementowaną ankietę Ajax na tej samej stronie lub przez źle zaimplementowaną 404 strona błędu na uszkodzonych obrazach tej samej strony). Zobacz także com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews, aby uzyskać szczegółowe informacje na temat tego limitu. Inną przyczyną jest konflikt zduplikowanych bibliotek JSF w ścieżce klas środowiska wykonawczego. Prawidłową procedurę instalacji JSF przedstawiono na naszej stronie wiki JSF .

Obsługa wyjątku ViewExpiredException

Jeśli chcesz obsłużyć nieuniknione ViewExpiredExceptionpo akcji POST na dowolnej stronie, która była już otwarta w jakiejś karcie / oknie przeglądarki, gdy jesteś wylogowany z innej karty / okna, to chcesz określić error-pagedla tego, w web.xmlktórym idzie do strony „Przekroczono limit czasu sesji”. Na przykład

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

W razie potrzeby użyj nagłówka meta odświeżania na stronie błędu, na wypadek gdybyś zamierzał przekierować dalej na stronę główną lub stronę logowania.

<!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>

( 0in contentreprezentuje ilość sekund przed przekierowaniem, 0co oznacza "przekierowanie natychmiast", możesz użyć np. 3aby przeglądarka czekała 3 sekundy z przekierowaniem)

Zauważ, że obsługa wyjątków podczas żądań Ajax wymaga specjalnego ExceptionHandler. Zobacz także przekroczenie limitu czasu sesji i obsługa wyjątków ViewExpiredException dla żądania AJAX JSF / PrimeFaces . Przykład na żywo można znaleźć na stronie prezentacji OmniFacesFullAjaxExceptionHandler (dotyczy to również żądań spoza AJAX ).

Należy również pamiętać, że „ogólne”, strona błędu powinien być odwzorowany na <error-code>od 500Zamiast <exception-type>EG java.lang.Exceptionlub java.lang.Throwable, w przeciwnym razie wszystkie wyjątki opakowane w ServletExceptiontaki jak ViewExpiredExceptionbędzie nadal kończy się w ogólnym strony błędu. Zobacz także wyjątek ViewExpiredException pokazany na stronie błędu java.lang.Throwable w pliku web.xml .

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

Poglądy bezpaństwowe

Zupełnie inną alternatywą jest uruchamianie widoków JSF w trybie bezstanowym. W ten sposób nic ze stanu JSF nie zostanie zapisane, a widoki nigdy nie wygasną, ale będą po prostu odbudowywane od podstaw na każde żądanie. Możesz włączyć bezstanowe widoki, ustawiając transientatrybut <f:view>na true:

<f:view transient="true">

</f:view>

W ten sposób javax.faces.ViewStateukryte pole otrzyma stałą wartość "stateless"w Mojarra (nie sprawdzałem w tym momencie MyFaces). Zwróć uwagę, że ta funkcja została wprowadzona w Mojarra 2.1.19 i 2.2.0 i nie jest dostępna w starszych wersjach.

W konsekwencji nie możesz już używać fasoli z zakresem widoku. Będą teraz zachowywać się jak fasola o zasięgu żądania. Jedną z wad jest to, że musisz samodzielnie śledzić stan, bawiąc się ukrytymi danymi wejściowymi i / lub luźnymi parametrami żądania. Głównie te formularze z polami wejściowymi z rendered, readonlylub disabledbędą miały wpływ atrybutów, które są kontrolowane przez ajax zdarzeń.

Zwróć uwagę, że <f:view>niekoniecznie musi być niepowtarzalny w całym widoku i / lub znajdować się tylko w szablonie głównym. Całkowicie legalne jest również ponowne zadeklarowanie i zagnieżdżenie go w kliencie szablonu. Zasadniczo wtedy „rozszerza” rodzica <f:view>. Np. W szablonie głównym:

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

oraz w kliencie szablonu:

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

Możesz nawet zawinąć <f:view>w a, <c:if>aby był warunkowy. Zwróć uwagę, że będzie to dotyczyło całego widoku, a nie tylko zagnieżdżonej zawartości, takiej jak <h:form>w powyższym przykładzie.

Zobacz też


Bez związku z konkretnym problemem, używanie HTTP POST do czystej nawigacji między stronami nie jest zbyt przyjazne dla użytkownika / SEO. W JSF 2.0 naprawdę powinieneś preferować <h:link>lub <h:button>od <h:commandXxx>tych, które zapewniają zwykłą, waniliową nawigację ze strony do strony.

Czyli zamiast np

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

lepiej zrób

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

Zobacz też

BalusC
źródło
Jak mogę to zrobić z niejawną nawigacją w Javie EE 6? Nie używam Faces-config.
l245c4l
1
Och, używasz JSF 2.0? Powinieneś był o tym wspomnieć w swoim pytaniu! Dodaj ?faces-redirect=truedo outcome. Odpowiednio zaktualizowałem odpowiedź.
BalusC
Tak, właśnie zacząłem od java ee :) i używam faces-redirect = true we wszystkich moich nawigacjach. Używam h: commandLink tylko wtedy, gdy mam z nim związane akcje. Na przykład link do wylogowania ... Mam akcję String logout (), w której unieważniam sesję i przekierowuję do logowania, ale nie działa na stronie, na której byłem zalogowany i jestem w tej chwili wylogowany i zgłasza ten wyjątek :(
l245c4l
1
Jeszcze raz dziękuję i przepraszam :) ale przynajmniej dostałem szybką i profesjonalną odpowiedź w
mgnieniu oka
1
@LS: Filtr jest jednak nadal obowiązkowy w przypadku, gdy ktoś naciśnie przycisk Wstecz po wygaśnięciu testu POST i spróbuje wywołać inne żądanie POST. W przeciwnym razie nieintuicyjnie spowodowałoby to wyjątek.
BalusC
56

Czy próbowałeś dodać poniższe wiersze do swojego web.xml?

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

Okazało się, że jest to bardzo skuteczne, gdy napotkałem ten problem.

Mike GH
źródło
1
na mnie też zadziałało. Dziękuję za odpowiedź. Jaki jest tego cel?
MartK
2
Nie pamiętam dokładnie, ale znalazłem to rozwiązanie na stronie ICEFaces.
Mike GH
mogę się trochę spóźnić na imprezę, ale to też zadziałało. dzięki!
stellarossa,
4
Czy jest to zdefiniowane tylko dla JSF 1.2 lub JSF 2?
SRy
17
Spowoduje to zaprzestanie zgłaszania wyjątku po wygaśnięciu widoku i po prostu kontynuowanie żądania, ale JSF nadal nie będzie w stanie przywrócić stanu widoku ani znaleźć żadnych powiązanych komponentów bean o zasięgu widoku. Ta transakcja będzie zachowywać się jak bezstanowy JSF i trzeba będzie samodzielnie przywrócić stan widoku na podstawie parametrów żądania POST, aby uniknąć „wtf?” doświadczenie użytkownika końcowego podczas przetwarzania przesłanego formularza odpowiedziało nieoczekiwanie. Jeśli chcesz zastosować to tylko na określonych stronach JSF, użyj OmniFaces <o:enableRestorableView>zamiast parametru kontekstowego dla całej aplikacji.
BalusC
5

Przed zmianą pliku web.xml musisz najpierw upewnić się, że Twój ManagedBean implements Serializable:

@ManagedBean
@ViewScoped
public class Login implements Serializable {
}

Zwłaszcza jeśli używasz MyFaces

ZuzEL
źródło
3

Unikaj formularzy wieloczęściowych w Richfaces:

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

Jeśli używasz Richfaces, odkryłem, że żądania Ajax wewnątrz formularzy wieloczęściowych zwracają nowy identyfikator widoku przy każdym żądaniu.

Jak debugować:

Przy każdym żądaniu ajax zwracany jest identyfikator widoku, to jest w porządku, o ile identyfikator widoku jest zawsze taki sam. Jeśli otrzymujesz nowy identyfikator widoku przy każdym żądaniu, oznacza to problem i należy go naprawić.

tak3shi
źródło
Zachowaj ostrożność podczas korzystania z ankiet, ponieważ może to zapobiec wygaśnięciu sesji użytkowników ..
Jonathan Simas
0

Możesz użyć własnego niestandardowego AjaxExceptionHandler lub primefaces-extensions

Zaktualizuj swój face-config.xml

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

Dodaj następujący kod na swojej stronie jsf

...
<pe:ajaxErrorHandler />
...
myset
źródło
0

Otrzymałem ten błąd: javax.faces.application.ViewExpiredException. Kiedy korzystałem z różnych żądań, znalazłem te, które mają ten sam JsessionId, nawet po ponownym uruchomieniu serwera. Wynika to więc z pamięci podręcznej przeglądarki. Po prostu zamknij przeglądarkę i spróbuj, zadziała.

rahul
źródło
0

Gdy nasza strona jest bezczynna przez x okres czasu, widok wygaśnie i wyrzuci javax.faces.application.ViewExpiredException, aby temu zapobiec, jednym rozwiązaniem jest utworzenie CustomViewHandler, który rozszerza ViewHandler i zastępuje metodę restoreView, wszystkie inne metody są delegowane do Rodzic

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

}   

Następnie musisz dodać go do swojego faces-config.xml

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

Dzięki za oryginalną odpowiedź na poniższy link: http://www.gregbugaj.com/?p=164

user4924157
źródło
To podejście nie przywraca fasoli z zakresem widoku.
BalusC
-2

Dodaj tę linię do swojego pliku web.xml. U mnie działa

<context-param>
        <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name> 
        <param-value>true</param-value>     
    </context-param>
ostry
źródło
4
Twoja odpowiedź będzie bardziej przydatna, jeśli uwzględnisz wyjaśnienie i kontekst dotyczący działania kodu.
Palpatim
1
Nawet jeśli jest to poprawna odpowiedź, StackOverflow odradza takie odpowiedzi bez wyjaśnienia. Byłoby pomocne dla społeczności, gdyby dodała więcej informacji o tym, dlaczego to działa.
RacerNerd
-2

Sam napotkałem ten problem i zdałem sobie sprawę, że jest to efekt uboczny utworzonego przeze mnie filtru, który filtrował wszystkie żądania w aplikacji. Jak tylko zmodyfikowałem filtr, aby wybierać tylko niektóre żądania, ten problem nie wystąpił. Może warto sprawdzić takie filtry w swojej aplikacji i zobaczyć, jak się zachowują.

javshak
źródło
-3

Dodałem następującą konfigurację do web.xml i został rozwiązany.

<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>
Mohamed ali
źródło
6
Okropna rada. Rób to tylko wtedy, gdy masz dużo pamięci, a Twoi użytkownicy końcowi naprawdę stale otwierają do 500 kart przeglądarki i naciskają przycisk Wstecz przeglądarki nawet 500 razy, aby przejść do poprzednich synchronicznych ogłoszeń zwrotnych.
BalusC