JSF, Scope

0

Mam parę niejasności odnoście JavaServer Faces:

Podczas tworzenia ziarna w ManagedBean można wybrać poniższe Scope:

  • request
  • application
  • view
  • none
    Kiedy oraz w jakich przypadkach mam je stosować ? Jakie są różnice między nimi ?

Kiedy mam do klasy implementować Serializable ?
Kiedy używać adnotację @PostConstruct ?
A co z konstruktorem klasy ? Zawsze zostawiać pusty ?

Wiem, że dużo pytać ale będę niezmiernie wdzięczy za wyjaśnienie chociaż jednego :)

2

Podczas tworzenia ziarna w ManagedBean można wybrać poniższe Scope:
request
application
view
none

Jest jeszcze session. Poczytaj o tym czym jest request http, czym jest sesja. Application to taki singleton, który jest współdzielony przez wszystkich użytkowników. NoneScoped oznacza, ze po wykonaniu DI wstrzyknięty Managed Bean odziedziczy scope komponentu, który go wstrzykuje. View zachowuje stan w biazacej zakladce przegladarki: w kazdej zakladce jest inny stan dla tego samego widoku.

Serializable przydaje sie tam, gdzie scope moze byc zrzucony w pamieci i zapisany np. na dysku. Czyli zawsze ViewScoped i SessionScoped.

@PostConstruct służy jako konstruktor, po stworzeniu Managed Beana jest wykonywana metoda w ten sposób zaadnotowana. Używa się tego ponieważ w konstruktorze nie masz dostępu do wstrzykiwanych bytów np. @ejb, @Inject, @ManagedProperty. Są one dostępne dopiero w @PostConstruct. Jest to przydatne szczególnie wtedy jak podczas załadowaniu widoku chcesz pobrać np. dane z bazy i je od razu wyswietlic.

Z czystych konstruktorów raczej nie korzysta się z przyczyn wspomnianych powyżej.

1

Zapomniałem o najważniejszym scope - session.

Po kolei:

  • application - odpowiednik singletonów, stworzony bean będzie działał tak długo, jak aplikacja. Może być stosowany jako np. zasób wspólny dla wszystkich użytkowników (cache, jakiś connection pool itp.).
  • session - stworzony bean jest przypisany do sesji i dopóki ona trwa, to taki obiekt będzie istniał. Chyba najbardziej uniwersalny, trzymamy w nim np. dane użytkownika w forum.
  • view - beany są "zapominane" przy wyjściu z konkretnego widoku. Przykładowo: jeśli chcemy, aby po wejściu na konkretną stronkę widok był pusty (np. stworzymy sobie funkcjonalność tworzenia notatek i chcemy, aby po wejściu w "Nową notatkę" za każdym razem wszystkie pola były puste)
  • request - beany są tworzone przy tworzeniu HttpRequest - do obsługi żądań
  • none - trudno mi powiedzieć, po co to jest :) W teorii można dodać jeden obiekt takiego zasięgu w dwóch obiektach (np. request i view), i wtedy będzie on trzymany tak długo jak jest potrzebny.

Obiekty powinny być serializowalne, kiedy muszą być powielane pomiędzy sesją użytkownika i serwerem. Tzn. wszystkie beany application, session i view muszą być serializowalne. Request chyba nie (jak jest inaczej niech mnie ktoś poprawi), none - nie wiem :)

Annotacji @PostConstruct używamy wtedy, kiedy chcemy aby po pojawieniu się beana coś się zadziało. Np. inicjalizacja zmiennych, list itp.
Konstruktor - musi być domyślny (bezparametrowy), najlepiej zostawić pusty i odwołać się do @PostConstruct.

0
  • Session - przechowuje np czy użytkownik jest zalogowany - żeby nie trzeba było po przejściu do innej strony znowu się logować - czas trwa domyślnie to chyba 24 minuty lub do zamknięcia przeglądarki.

  • View - jeśli stworzę dialog w którym będę się mógł zalogować i za każdym razem jak go otworzę otworzę to będą puste pola. A jeśli będę chciał aby były uzupełnione(po wcześniejszym ręcznym wpisaniu jakiś wartości) to ustawiam session ?

  • Request - jest to wykonywane za każdym razem gdy kliknę w przycisk czy coś takiego. Za każdym razem prosi o wykonanie tej rzeczy jeszcze raz.

  • Application - to jest taka jakby zmienna STATIC w Javie ? Globalna i dostępna dla każdego

  • None - jak mam w ziarnie zmienną imie="Adam" i zrobię formularz do którego wpiszę "Maria" to wtedy w tej zmiennej będzie cały czas przechowywana za zmienna - po prostu go odziedziczy.

Tak to zrozumiałem. Jeśli jest błędne to proszę poprawić.

0
  1. Czas trwania sesji konfigurujesz w minutach w web.xml.
  2. Sesja moze przechowywac cokolwiek tak dlugo jak jestes zalogowany.
  3. Domyslnie sesja jest przechowywana po stronie serwera.
  4. Tak naprawde @ViewScoped to specjalnie wydzielony fragment sesji, tak aby bylo wygodnie. Zasieg byl opisany powyzej.
  5. Nie jest to static, ale mozna o tym tak myslec (singleton): cos co jest dostepne dla kazdego (przynajmniej jak nie ma node'ow). Jak sa node'y i klastrowe srodowisko to trzeba zobaczyc w specyfikacji JSF Managed Beans.
  6. Pomysl o @NoneScoped jako o zwyklym DI, ktore po prostu zawsze tworzy obiekt (bez proxy), zamiast new i rejestruje go zgodnie z JSF EL (dostep po nazwie).
1

Stworzyłem sobie coś takiego:

FirstPage.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Scope - testowanie</title>
    </h:head>
    <h:body>
        
        <h:form id="testForm" >
            <p:outputLabel for="session" value="Session" />
            <p:inputText id="session" size="20"  value="#{mySession.session}"/> <br />
            
            <p:outputLabel for="view" value="View" />
            <p:inputText id="view" size="20"  value="#{myView.view}"/> <br />
            
            <p:outputLabel for="request" value="Request" />
            <p:inputText id="request" size="20"  value="#{MyRequest.request}" /> <br />

            <p:outputLabel for="none" value="None" />
            <p:inputText id="none" size="20"  value="#{myNone.none}" /> <br />
            
            <p:commandButton ajax="false" value="Save value" />  <br/>
                
            <p:link value="First Page" outcome="FirstPage.xhtml?faces-redirect=true" /> <br/>
            <p:link value="Second Page" outcome="SecondPage.xhtml?faces-redirect=true" /><br/>
            
            <h:outputText value="Session" /> <br/>
            <h:outputText value="#{mySession.session}" /><br/>
            <h:outputText value="View" /> <br/>
            <h:outputText value="#{myView.view}" /><br/>
            <h:outputText value="Request" /> <br/>
            <h:outputText value="#{MyRequest.request}" /><br/>
            <h:outputText value="None" /> <br/>
            <h:outputText value="#{myNone.none}" /><br/>
        </h:form>
        
    </h:body>
</html>

SecondPage.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Scope - testowanie</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </h:head>
    <h:body>
        <h:outputText value="Druga strona" /><br/>
        
        <h:outputText value="Session" /> <br/>
        <h:outputText value="#{mySession.session}" /><br/>
        <h:outputText value="View" /> <br/>
        <h:outputText value="#{myView.view}" /><br/>
        <h:outputText value="Request" /> <br/>
        <h:outputText value="#{MyRequest.request}" /> <br/>
        <h:outputText value="None" /> <br/>
        <h:outputText value="#{myNone.none}" /><br/>
        
            <p:link value="First Page" outcome="FirstPage.xhtml?faces-redirect=true" /> <br/>
            <p:link value="Second Page" outcome="SecondPage.xhtml?faces-redirect=true" /><br/>
    </h:body>
</html>

Ziarna (każe wygląda tak samo tylko inna adnotacja i nazwa):

@ManagedBean (name = "mySession")
@SessionScoped
public class Session implements Serializable{
    private String session = "S - domyślna wartość";
    /**
     * Creates a new instance of Session
     */
    public Session() {
    }
    

    public String getSession() {
        return session;
    }

    public void setSession(String session) {
        this.session = session;
    }
    
}

Wnioski:

@SessonScoped
działa tak długo jak mam otwartą przeglądarkę - mogę otwerać nowe karty a i tak session będzie cały czas aktywna.
Aby móc pobierać wartości z sesji w javie trzeba je najpierw zapisać "setAttribute" - szczególnie podczas robia panelu logowania

@ViewScoped
działa tylko na aktualnej stronie,przejśćie do innej strony pobiera domyślną wartość, otworzenie nowej karty, odświeżenie strony robi to samo

@NoneScoped
Sam nie wiem ile on trwa, po kliknięcu w przcisk od razu się ustawia na domyślną wartość

@Application Scoped
http://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml
Ten tam użyty @ApplicationScope
Jest on użyty po to aby uzupełnić tabelę losowymi wartościami - niby już wiem kiedy to używać

0

Tak na marginesie, bodajże od wersji JSF 2.2 ManagedBeany nie są zalecane do używania. Zamiast nich powinno się używać CDI.

1 użytkowników online, w tym zalogowanych: 0, gości: 1