Spring i wstrzykiwanie zależności między bean’ami o różnych zasięgach.

Na pewno wszyscy z Was znają framework (rusztowanie aplikacyjne? LOL) Spring, więc nieobce jest wam hasło Dependency Injection. Wielu z Was codziennie korzysta z dobrodziejstw jakie daje DI, a niektórzy nie są w stanie się bez tego obejść.
Jak wiemy w Springu dostępnych jest kilka zasięgów które określają cykl życia bean’ów (ziaren), bean’y te mogą być od siebie wzajemnie zależne.
Uzależnienie jednego bean’a od drugiego jest w Springu dziecinnie proste i polega na napisaniu kawałka XML:

<?xml version=“1.0″ encoding=“UTF-8″?>
<beans xmlns=“http://www.springframework.org/schema/beans”
    xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
    xsi:schemaLocation=“http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd”
>

    <bean id=“firstBean” class=“org.holewa.FirstBean”/>

    <bean id=“secondBean” class=“org.holewa.SecondBean”>
        <property name=“firstBean” ref=“firstBean”/>
    </bean>

</beans>

Gdzie postać klasy FirstBean jest następująca:

package org.holewa;

public class FirstBean {
 
}

Klasa SecondBean zawiera akcesory dzięki którym zostanie wstrzyknięta zależność od FirstBean:

package org.holewa;

public class SecondBean {

  private FirstBean firstBean;

  public FirstBean getFirstBean() {
    return firstBean;
  }

  public void setFirstBean( FirstBean firstBean ) {
    this.firstBean = firstBean;
  }
}

To jest chyba najbardziej trywialny przykład zdefiniowania wzajemnych zależności jaki kiedykolwiek wymyślono :)
Obydwa zdefiniowane powyżej bean’y mają ten sam zasięg, który jest domyślnie zasięgiem singleton.
Sytuacja się jednak nieco komplikuje gdy chcemy stworzyć zależności między bean`ami o różnych zasięgach, tu przykładowo zasięg sesji (session) oraz singleton. O ile wykorzystanie singleton’a w bean’ie o zasięgu sesji jest bezproblemowe (dla wszystkich sesji będzie jeden singleton) o tyle sprawa jest bardziej zagmatwana w przeciwną stronę, bo skąd mamy wiedzieć o którą instancję bean’a chodzi, jest ich przecież wiele (jedna per sesja)? Otóż z pomocą przychodzi nam oczywiście Spring i programowanie aspektowe. Dzięki wykorzystaniu AOP Spring tworzy dynamic proxy które to pośredniczy podczas odwołania się do bean’a. Tak powstałe proxy automagicznie (uwielbiam to określenie :D) odnajduje bean’a znajdującego się w zasięgu sesji z której nastąpiło do niego odwołanie i zwraca do niego referencję. Niestety Spring nie jest aż tak automagiczny jakbyśmy chcieli (a może i dobrze :P), dlatego też trzeba w definicji wybranego bean’a (w tym przypadku tego o zasięgu sesji) zastosować specjalny tag który poinformuje Springa, że odwołania do tego bean’a będą odbywać się dzięki zastosowaniu dynamic proxy.

Robi się to następująco:

<?xml version=“1.0″ encoding=“UTF-8″?>
<beans xmlns=“http://www.springframework.org/schema/beans”
    xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
    xmlns:aop=“http://www.springframework.org/schema/aop”
    xsi:schemaLocation=“http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”
>

    <bean id=“sessionData” scope=“session”
        class=“org.holewa.SessionData”>
        <aop:scoped-proxy/>
    </bean>

    <bean id=“singleton” class=“org.holewa.Singleton”>
        <property name=“sessionData” ref=“sessionData”/>
    </bean>

</beans>

Klasy Singleton i SessionData są tworzone analogicznie do klas FirstBean i SecondBean.
Taka definicja w zupełności wystarcza do tego aby z poziomu singletona odwoływać się do danych (bean’ów) znajdujących się w zasięgu aktualnej sesji.

Prawda, że proste?

July 27, 2008 | Leave a Comment 

Spring WebFlow

Po pewnej przerwie spowodowanej chorobą i sesją powracam :D
Jako, że ostatnimi czasy miałem okazję zajmować się Spring WebFlow, dlatego też dziś będziecie mieli “przyjemność” poczytać coś na ten temat :D

A więc zaczynamy !!!

Na początek pytanie : Czy wiesz co to jest Spring WebFlow ?
Bardzo krótka odpowiedź : Framework który pozwala definiować flow (czyli przepływ) przez Waszą aplikację i w łatwy sposób nim zarządzać :D

Pewnie niejednokrotnie mieliście problemy z zarządzaniem zdefiniowanym przez Was przepływem, w szczególności toczyliście boje z obsługą różnych przejść, powrotów, wszelkiego rodzaju powiązań i przekazywania danych między akcjami itd. itp. :D
A więc Spring WebFlow ma za zadanie Wam to ułatwić, czy tak naprawdę ułatwia ? No cóż - ja mam mieszane uczucia :(
W dzisiejszej części przedstawię prostą konfigurację Spring WebFlow z użyciem Spring MVC.

W pierwszym kroku musimy stworzyć projekt webowy którego deployment descriptor (web.xml) powinien wyglądać następująco :




org.springframework.web.context.ContextLoaderListener
  

  
    sampleservlet
    org.springframework.web.servlet.DispatcherServlet
    1
    
contextConfigLocation

        /WEB-INF/sample-servlet.xml
        /WEB-INF/sample-flow.xml
      
    
  

  
    sampleservlet
    *.htm
  

  
    index.jsp
  

W powyższym pliku podaliśmy ścieżki do dwóch plików (/WEB-INF/sample-servlet.xml oraz /WEB-INF/sample-flow.xml), które to przechowują ogólną konfigurację naszej aplikacji, taką jak viewResolver służący do tworzenia widoku (w naszym przypadku będzie odpowiednio mapował widok zdefiniowany w konfiguracji flow na odpowiednią stronę JSP) czy też flowController dzięki któremu będziemy mieli możliwość wywoływania zdefiniowanego przez nas flow o podanym identyfikatorze (przykładowy sposób wywołania flow w dalszej części tego wpisu).

Kolejny krok to stworzenie plików sample-servlet.xml i sample-flow.xml.
Na pierwszy rzut pójdzie sample-servlet.xml :




  

  

  


  

  

Powyżej były widoczne wspomniane wcześniej viewResolver i flowController.

Oczywiście teraz zdefiniujemy główny plik konfiguracyjny flow (sample-flow.xml) :




  

  
    
  


FlowExecutor to główny element obsługi flow w Spring WebFlow, to on jest wykorzystywany przez flowController do obsługi przepływu naszej aplikacji.

Nasz kontroler zdefiniowaliśmy jako springowy bean w pliku applicationContext.xml :




  


Zwróci nam on listę obiektów, które będą zawierały namiary na blogi :)

Oto definicja naszego pierwszego (i w tym wpisie jedynego) flow - plik first-flow.xml




  

  
    
      
        
      
    
  


Jak łatwo zauważyć w powyższym kodzie, nasz flow przekieruje nas do widoku listForm co dzięki konfiguracji viewResolver`a w pliku sample-flow.xml sprawi, iż zostaniemy przekierowani do strony listForm.jsp znajdującej się w katalogu /WEB-INF/jsp/.
Zwróćmy też uwagę na tag gdyż definiuje on “punkt wejściowy” naszego przepływu, to właśnie od stanu zdefiniowanego za pomocą tego znacznika zacznie się nasz przepływ.
W chwili obecnej mamy w naszym przepływie tylko jeden stan o nazwie list, gdy osiągniemy ten stan zostanie wygenerowany widok, jego do jego stworzenia zostanie użyty nasz kontroler na którym zostanie wywołana metoda loadData (zwracająca kolekcję obiektów), kolekcja którą otrzymamy w wyniku jej wykonania będzie widoczna dla nas pod nazwą result (zgodnie z tym co zostało podane w znaczniku ).

Oto strona (listForm.jsp) na której zostanie pokazana zawartość kolekcji zwróconej przez wywołanie metody na kontrolerze :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>







Tak jak już wspomniałem, nasz kontroler (SampleController) będzie w tym przypadku zwracał jedynie przykładową listę zawierającą informacje o trzech blogach :

package org.holewa.webflow.controller;

import org.holewa.webflow.vo.SampleVO;

import java.util.List;
import java.util.ArrayList;

public class SampleController {

  public List loadData() {
    List list =  new ArrayList();
    list.add(new SampleVO("http://jaceklaskowski.pl/", "Blog Jacka Laskowskiego"));
    list.add(new SampleVO("http://blog.mocna-kawa.com/", "Blog Wiktora"));
    list.add(new SampleVO("http://holewa.org/", "Mój blog"));
    return list;
  }

}

Value object (SampleVO) który użyliśmy w tym przykładzie ma następującą implementację :

package org.holewa.webflow.vo;

public class SampleVO {

  private String link;
  private String name;

  public SampleVO(String link, String name) {
    this.link = link;
    this.name = name;
  }

  public String getLink() {
    return link;
  }

  public String getName() {
    return name;
  }

  public void setLink(String link) {
    this.link = link;
  }

  public void setName(String name) {
    this.name = name;
  }
}

Teraz pasuje przygotować stronę powitalną, po kliknięciu na link przekieruje ona użytkownika do naszego flow.
Strona index.jsp jest następującej postaci :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>



 Uruchom flow


Wywołanie /flowController.htm?_flowId=first-flow sprawi, że zostaniemy przekierowani do przepływu o identyfikatorze first-flow.
To w zasadzie tyle na początek przygody z Spring WebFlow, kod aplikacji (bez bibliotek) możecie pobrać tutaj. Kolejna część wkrótce (wytłumaczę w niej dlaczego mam mieszane uczucia w stosunku do tego frameworku) :D

February 16, 2008 | Leave a Comment