Zarządzanie transakcjami przez serwer aplikacji

W środowiskach zarządzanych (czyli np w serwerze aplikacyjnym JBoss AS) to te systemu mogą zarządzać transakcjami, czyli rozpoczynać, kończyć je w odpowiednim momencie, zwalniając z tego obowiązku programistę. W aplikacji można zdefiniować, jak dany fragment kodu ma wpływać na transakcje. Jeżeli sposób zachowanie nie zostanie zdefiniowany przez metodę, to kontener rozpoczyna transakcję zanim rozpocznie się wykonywanie metody, i kończy ją tuż przed końcem jej wykonywania. Nie są dozwolone zagnieżdżone transakcje, każda metoda może zostać skojarzona z jedną transakcją.

Definicja rodzaju transakcji

Rodzaje transakcji można zdefiniować przy użyciu adnotacji TransactionAttribute oraz TransactionAttributeType.

Adnotacja TransactionAttribute może występować zarówno na poziomie deklaracji klasy jak i deklaracji metody. Jeżeli zostanie podana przy deklaracji klasy, oznacza to że dany poziom transakcji ma zostać użyty we wszystkich metodach danej klasy, w przypadku deklaracji na poziomie metody odnosi się tylko do niej. W przypadku gdy występuje w jednym jak i drugim miejscu, pod uwagę brana jest wartość występująca przy deklaracji metody.

Poniżej przykład deklarowania rodzajów transakcji, na poziomie klasy i metod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class UserManager {
   
    @TransactionAttribute(TransactionAttributeType.SUPPORTS)
    public String getUserName() {
        return null;
    }
   
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void setUserName(String name) {
       
    }
}

Typy transakcji

Za pomocą adnotacji TransactionAttributeType można zdefiniować rodzaj transakcji, jaka ma obowiązywać w metodach. Występują następujące typy transakcji:

  • MANDATORY
    Konieczność wykonania metody w ramach istniejącej już transakcji. Jeżeli dla danego klienta istnieje już działająca transakcji, dana metoda zostanie w jej ramach wykonana. Jeżeli natomiast taka transakcji nie istnieje, to zostanie wyrzucony wyjątek TransactionRequiredException. Należy użyć tego atrybutu używać wtedy, gdy dana metoda musi zostać wykonana w ramach transakcji klienta.
  • REQUIRED
    Jeżeli klient działa w ramach transakcji i zostanie wywołana metoda oznaczona tym typem, to zostanie ona wykonana w ramach tej transakcji. Jeżeli natomiast klient nie działa w ramach transakcji, to zostanie rozpoczęta nowa, zanim metoda zostanie uruchomiona. Jest to także domyślne zachowanie, jeżeli nie zostanie ustawiony typ transakcji.
  • REQUIRES_NEW
    Jeżeli klient nie działa w ramach transakcji, to po prostu jest rozpoczynana nowa przed uruchomieniem metody. Natomiast jeżeli jest istnieje już działająca transakcja, to podejmowane są następujące kroki:

    1. Zawieszenie aktualnie działającej transakcji.
    2. Rozpoczęcie nowej transakcji do wykonania wybranej metody.
    3. Wywołanie i wykonanie metody.
    4. Po zakończeniu działania metody ponowne uruchomienie wcześniej zawieszonej transakcji.

    Typu tego należy używać w sytuacji, gdy istnieje potrzeba wykonywania danej metody zawsze w nowej transakcji.

  • SUPPORTS
    Jeżeli klient działa w ramach transakcji i wywoła daną metodę, to zostanie ona wykonana w ramach tej transakcji. Jeżeli natomiast transakcja nie istnieje, to nie zostanie ona także rozpoczęta przed wykonaniem wybranej metody.
  • NOT_SUPPORTED
    Jeżeli klient działa w ramach transakcji, to zostanie ona zatrzymana na czas wywołania wybranej metody, a po jej wykonaniu ponownie przywrócona. Jeżeli nie ma takiej transakcji, metoda zostanie po prostu wykonana, bez rozpoczynania nowej.

    Należy używać tego typu wtedy, gdy wybrana metoda nie potrzebuje transakcji do działania, a zależy nam na większej wydajności jej wykonywania (transakcje mają negatywny wpływ na szybkość wykonywania metod).

  • NEVER
    Jeżeli klient działa w ramach transakcji i wywoła metodą oznaczoną tym typem, zostanie wyrzucony wyjątek RemoteException. Natomiast jeżeli transakcja nie istnieje, to metoda zostanie wykonana bez rozpoczynania nowej transakcji.

Mała tabela, która podsumowuje powyższe:

Zachowanie kontenera w zależności od typu i stanu transakcji
Nazwa atrybutu Transakcja istnieje Brak transakcji
MANDATORY używa istniejącej wyrzuca wyjątek
REQUIRED używa istniejącej rozpoczyna nową
REQUIRES_NEW zawiesza istniejącą, rozpoczyna nową rozpoczyna nową
SUPPORTS używa istniejącej działa bez
NOT_SUPPORTED zawiesza istniejącą działa bez
NEVER wyrzuca wyjątek działa bez

Źródła

Tags: , , , , ,

Monitorowanie aktywności sieciowej procesu lub użytkownika

Oto prosta komenda, która pozwoli na monitorowanie, z jakimi adresami sieciowymi łączy się dana aplikacja lub też dany użytkownik:

  • monitorowanie aktywności procesu:
    lsof -r 2 -p PID -i -a
  • monitorowanie aktywności użytkownika
    lsof -r 2 -u USER -i -a

Poszczególne parametry oznaczają:

  • -p PID – numer procesu, który ma być monitorowany
  • -u USER – nazwa użytkownika, którego połączenia sieciowe mają być monitorowane, parametr może być użyte więcej niż jeden raz, może to pozwolić to wtedy na monitorowanie aktywności kilku użytkowników
  • -r 2 – tryb ciągłego odczytu, w tym przypadku co dwie sekundy zostaną wyświetlone aktualne dane
  • -i – wyświetlenie połączeń IP (pominięcie wyświetli także np. otwarte pliki), pozwala także na ograniczanie zakresu wyświetlanych opcji (np. IPv4 lub IPv6 czy jakaś pojedyncza domena)
  • -a – powoduje, że pomiędzy warunkami definiującymi co ma być wyświetlone jest stosowany spójnik logiczny AND (w przeciwnym wypadku będzie stosowany spójnik OR, czyli wyświetlenie np. informacji o podanym procesie lub wszystkie połączenie TCP)

Źródła

Tags: , , ,

Model nawigacji w JSF

Model nawigacyjny JSF pozwala na zdefiniowanie nawigacji pomiędzy stronami oraz na wykonywania dodatkowych akcji związanych z przechodzeniem pomiędzy stronami. W terminologii JSF nawigacją jest nazywany zestaw reguł, za pomocą których można stwierdzić jaka następna strona ma zostać wyświetlona po wybraniu jakieś przycisku bądź linku znajdującego się na stronie. Reguły te są zdefiniowane w pliku konfiguracyjnym faces-config.xml.

Jak zdefiniować regułę nawigacyjną?

Zdefiniowanie prostej nawigacji pomiędzy stronami sprowadza się do:

  • zdefiniowaniu odpowiednich reguł w pliku konfiguracyjnym faces-config.xml
  • odwołanie się do poprzez zdefiniowany ciąg znaków z poziomu przycisku lub linku

Przykładowy zapis w pliku konfiguracyjnym:

<navigation-rule>
    <from-view-id>/login.jsp</from-view-id>
    <navigation-case>
        <from-outcome>sukces</from-outcome>
        <to-view-id>/home.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-outcome>błąd</from-outcome>
        <to-view-id>/login.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

Aby wykorzystać podany zapis, należy w następujący sposób zbudować link lub przycisk (w pliku login.jsp):

<h:commandButton id="submit" action="sukces"
        value="Submit" />

W pliku konfiguracyjnym faces-config.xml definiujemy zasady nawigacji. Czyli:

  • navigation-rule – definicja reguły nawigacyjnej
  • from-view-id – informacja, jakiej strony dotyczą reguły
  • navigation-case – definicje wszystkich reguł, jakie mają mieć zastosowanie dla danej strony
  • from-outcome – definicja ciągu znakowego, który będzie użyty do rozpoznania danego przypadku nawigacyjnego, czyli przekirowania na podaną stronę, ciąg ten musi się „znaleźć” w atrybucie action, podany albo bezpośrednio, lub też zwrócony przez jakąś metodę
  • to-view-id – na jaką stronę przekierować przeglądarkę

Natomiast w pliku login.jsp definiujemy odpowiedni interfejs użytkownika (klikalny, czyli przycisk bądź link). Tam w jako parametr dla atrybutu action wprowadzamy zdefiniowany ciąg znaków, lub też wywołujemy jakąś metodę, która zwróci dany ciąg znaków (zdefiniowany w pliku konfiguracyjnym), co umożliwi odpowiednie przekierowanie w zależności od akcji.

I tak:

<h:commandButton id="submit" action="#{loginManager.login}"
        value="Submit" />

Metoda login zwraca ciąg znaków sukces w przypadku powodzenia podczas logowania. Nastąpi wtedy wykonanie reguły nawigacyjnej tak oznaczonej, i przekierowanie do strony ]home.jsp. Natomiast jeżeli uwierzytelnienie użytkownika nie powiedzie się, metoda ta zwraca ciąg znaków błąd, co spowoduje przekierowanie z powrotem do strony logowania.

Można także zdefiniować globalne przekierowania na daną stronę:

<navigation-rule>
    <from-view-id>*</from-view-id>
    <navigation-case>
        <from-outcome>loguj</from-outcome>
        <to-view-id>/login.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

Czyli niezależnie na jakiej stronie zostanie użyty w ciąg znaków loguj w atrybucie action, to zawsze nastąpi przekierowanie na stronę logowania.

Co się dzieje po wybraniu linka w przeglądarce?

W momencie, gdy użytkownik kliknie na przycisk lub też link, dany komponent generuje odpowiednie zdarzenie, którym informuje o tym fakcie. Zdarzenie to jest obsługiwane domyślną implementację interfejsu ActionListener, który wywołuje odpowiednią metodę z akcją zdefiniowaną w komponencie. Podana metoda wykonuje się i zwraca ciąg znaków, który zostanie użyty do podjęcia decyzji o nawigacji.

Zwrócony ciąg znaków jest przekazywany do domyślnej implementacji NavigationHandler, która bazując na tej wartości sprawdza, jaka strona powinna zostać wyświetlona.

Jeżeli uda się odnaleźć odpowiednią regułę nawigacyjną, rozpocznie się faza tworzenia docelowej strony HTML.

Źródła

Tags: , , , ,

Zakres działania ziaren zarządzanych przez JSF

W JSF ziarno zarządzane (managed bean) może mieć jeden z czterech zakresów:

  • application
    Obiekt o takim czasie życia funkcjonuje przez cały okres życia aplikacji, czyli jest tworzony w momencie uruchamiania aplikacji i niszczony w momencie zatrzymywania jej działania.
  • session
    Ziarna oznaczone w ten sposób mają czas życie ograniczony do długości trwania sesji. Czyli są tworzone w momencie tworzenia sesji i niszczone razem z jej zakończeniem. Sesja może zostać zniszczona: ręcznie przez aplikację lub też jej czas życia się skończył. Dlatego też dany obiekt może brać udział w wielu zapytaniach wysyłanych do serwera (np. przechowywać stan koszyka w sklepie internetowych).
  • request
    Czas życia ziarna jest ograniczony do pojedynczego zapytania, czyli od momentu rozpoczęcia przetwarzania żądania wyświetlenia strony do momentu jej całkowitego utworzenia. Po wysłaniu strony do klienta obiekt jest niszczony.
  • none
    Brak zakresu działania, używany czasem w dla ziaren zarządzających innymi obiektami.

Przykładowa definicji ziarna w pliku faces-config.xml:

<managed-bean>
    <managed-bean-name>customer</managed-bean-name>
    <managed-bean-class>
        com.mycompany.mybeans.CustomerBean
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>mailingAddress</property-name>
        <value>#{addressBean.mail}</value>
    </managed-property>
    <managed-property>
        <property-name>streetAddress</property-name>
        <value>#{addressBean.street}</value>
    </managed-property>
    <managed-property>
        <property-name>customerType</property-name>
        <value>New</value>
    </managed-property>
</managed-bean>

Powyższy przykład pokazuje w jaki sposób zdefiniować zarządzalne ziarno oraz jak je zainicjalizować początkowymi wartościami.

Tags: , , , , , , , ,

Zmiana domyślnej implementacji JSF w serwerz JBoss AS

Domyślną implementacją JSF w serwerze aplikacji JBoss AS w wersji 4.2 oraz 5 jest biblioteka o nazwie Mojarra. Wcześniej była używana biblioteka Apache MyFaces. Ponieważ istnieje wiele różnych implementacji JSF, może zajść potrzeba użycia własnej wersji. Aby jej używać, trzeba zrobić dwie rzeczy:

  • dodać biblioteki do pakietu z aplikacją
  • poinformować serwer JBoss, aby używał dostarczonej biblioteki, a nie dostarczanych z serwerem, czyli zmodyfikować plik web.xml:
    <context-param>
    <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
    <param-value>true</param-value>
    </context-param>

Źródła

Tags: , , ,