Problem z sesją w JSF

Problem z sesją w JSF
0

Witam.
Na początku zaznaczę, że programowaniem w Javie zajmuję się od kilku lat, ale JEE uczę się dopiero od tygodnia.
Mój problem dotyczy zarządzaniem sesją w JSF. Napisałem prostą aplikację, która po zalogowaniu usera, ustawia odpowiedni obiekt UserSessionBean jako atrybut sesji, tak aby mieć potem wygodny do niego dostęp. Sam proces logowania odbywa się poprzez prosty formularz (używam kontrolek PrimeFaces, stąd <p:...>):

Kopiuj
<h:form>

            <p:panel header="Logowanie">
                <h:panelGrid columns="2">  
                    <h:outputText value="Użytkownik: " />
                    <p:inputText value="#{userForm.userName}"/>
                    <h:outputText value="Hasło: " />
                    <p:password value="#{userForm.password}" feedback="false" minLength="3"/>
                    <p:commandButton value="Zaloguj" action="#{userForm.login}" update="growl" ajax="false"/>
                </h:panelGrid>
            </p:panel>

        </h:form>

Klasa odpowiedzialna za logowanie (najważniejszy fragment):

Kopiuj
@ManagedBean(name = "userForm")
@SessionScoped
public class UserForm implements HttpSessionListener{

    private PostgreManager pm;
    @ManagedProperty(value = "#{userSession}")
    private UserSessionBean userSession;
    private String userName;
    private String password;

    public String login() {
        try {
            try {
                pm = PostgreManager.getInstance();
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(UserForm.class.getName()).log(Level.SEVERE, null, ex);
            }
            UserBean user = null;
            try {
                user = pm.validateLogin(getUserName(), getPassword(), false);
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(UserForm.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (user != null) {

                HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);

                userSession = (UserSessionBean) session.getAttribute(UserSessionFilter.MANAGED_BEAN_NAME);
                userSession.setUser(user);
                session.setAttribute(UserSessionFilter.MANAGED_BEAN_NAME, userSession);

                return "valid";
            } else {
                // Do your error handling thing.
                setErrorMessage("Podano zły login lub hasło.");
            }
        } catch (SQLException e) {
            // Do your exception handling thing.
            setErrorMessage("Błąd przy łączeniu z bazą.", e);
        }

        return null;
    }

    public String logout() {

        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        userSession = (UserSessionBean) session.getAttribute(UserSessionFilter.MANAGED_BEAN_NAME);
        userSession.setUser(null);
        session.setAttribute(UserSessionFilter.MANAGED_BEAN_NAME, userSession);
        return "logout";
    }
}

W faces-config.xml mam następującą regułę, dotyczącą nawigacji:

Kopiuj
<navigation-rule>
    <from-view-id>/login.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>valid</from-outcome>
        <to-view-id>/view.xhtml</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

Mój problem polega na tym, że podczas logowania, przy przechodzeniu z /login.xhtml do /view.xhtml sesja zostaje zamknięta (sprawdzałem to ustawiając odpowiedni HttpSessionListener ) a w jej miejsce zostaje wstawiona nowa sesja, przez co nie mam już dostępu do atrybutu UserSessionBean. Dodam, że w web.xml timeout jest standardowy = 30 minut. Co może być tego powodem i jak sprawić, aby sesja nie została usunięta.

Dodam jeszcze stack trace, jaki otrzymałem po umyślnym wyrzuceniu wyjątku w metodzie sessionDestroyed() obiektu nasłuchującego:

Kopiuj
2011-07-30 15:18:13 UserForm sessionDestroyed
FINE: Niszczenie sesji
java.lang.Exception: sesja zlikwidowana
	at UserForm.sessionDestroyed(UserForm.java:152)
	at org.apache.catalina.session.StandardSession.expire(StandardSession.java:807)
	at org.apache.catalina.session.StandardSession.expire(StandardSession.java:769)
	at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:686)
	at org.apache.catalina.session.StandardManager.processExpires(StandardManager.java:996)
	at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5717)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1790)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1779)
	at java.lang.Thread.run(Thread.java:662)

Wygląda na to, że moja sesja wygasła z nieznanych mi przyczyn.

R9
  • Rejestracja:ponad 14 lat
  • Ostatnio:prawie 11 lat
0

Moje doświadczenie w JSF jest niewielkie ale w aktualnym JSF2 faces-config.xml ma niewiele do gadania (w nowostworzonym projekcie go nawet nie ma), bo się większość załatwia poprzez dyrektywy.

Poza tym metoda którą wywołujesz przez ActionButton, czy tam ActionCommand z PrimeFaces, to przy poprawnym zalogowaniu mógłby zwrócić Stringa do której strony ma przenieść zamiast null.

Czyli zamiast return null;, to return "/view.xhtml";. A nulla zwraca przy niepowodzeniu jakimś.

Ze stacka wychodzi, że sesja wygasła:/ Swoją drogą: skoro użytkownik i tak się loguje, to mógłbyś utworzyć nową sesję, ew. starą zamknąć. Nie wiem w którym ziarnie ci wywala wyjątek z tą sesją.

0

@Razi91: Ta metoda działa dokładnie tak jak napisałeś. Przy poprawnym logowaniu zwraca ciąg "valid",
co zgodnie z regułą zapisaną w faces-config.xml powoduje przekierowanie na stronę /view.xhtml.
Null jest zwracany, gdy nie znaleziono usera w bazie. W tym przypadku strona nie zostaje przeładowana,
wyświetla się za to okienko z komunikatem o niepoprawnym loginie.

Robiłem testy w których w identyczny sposób realizowałem logowanie, ale bez użycia primefaces.
W takim przypadku sesja była inicjowana na początku działania i trwała, dopóki nie upłynął zadany czas.
Wygląda na to, że primefaces w jakiś sposób wpływa na wcześniejsze zamknięcie sesji.

0

Okazuje się, że jestem kretynem w dodatku zapominalskim. W czasie jednego z poprzednich eksperymentów zostawiłem w kodzie jednego z rzadko używanych ziaren funkcję zmieniającą czas życia sesji na 5 ms i zapomniałem jej po wszystkim stamtąd usunąć, co kosztowało mnie 8 godzin szukania o_O
Problem rozwiązany.

remigio
uroki programowania :d
SE
  • Rejestracja:około 14 lat
  • Ostatnio:około 13 lat
  • Postów:9
0

Super, że znalazłeś przyczynę błędu, ja mam taki sam kawałek kodu i problem z tym, że nie pobiera mi wartości z danego pola tekstowego w formularzu natomiast do gettera mi wchodzi i w debugerze widzę że jest wartość null ponieważ settera mi nie wywołuje. Natomiast ten kawałek kodu nad prywatną zmienną, która ustawia setter @ManagedProperty(value="#{firstname}") nie przekazuje wartości z pola formularza o tej właśnie nazwie. Czy ktoś wie jak to rozwiązać? Będę wdzięczny.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)