Zarobił Jacek, zarobisz i Ty!

Jak zapewne część z Was wie, ostatnio odbył się konkurs na najlepszy wpis na blogu o NetBeans 6.1, mieliśmy wśród zwycięzców jednego rodaka - Jacka Laskowskiego (ciekawe dlaczego mnie to nie dziwi :P), Jacek zgarnął w ten sposób swoje 500 dolców ale musiał się przy tym trochę napisać :D

Okazja do zarobienia takiej samej kwoty pojawia się ponownie, przy czym tym razem nie trzeba się aż tyle wysilać :P
Zapytacie pewnie jak to możliwe? Trzeba tylko wziąć udział w konkursie organizowanym przez The GlassFish Awards Program i zgłaszać bugi. Tak, nie mylicie się - za zgłoszenie buga który kwalifikuje się do czołowej setki otrzymujecie $500!


Zostań Sun Campus Ambassadorem

Wszystkich zainteresowanych pozycją Sun Campus Ambassadora we Wrocławiu odsyłam do informacji umieszczonych na blogu Pawła Szulca.


Prezentacja na Uniwersytecie Gdańskim

Miałem się wstrzymać z pisaniem czegokolwiek na blogu, jednak jutro wybieram się do Gdańska zaprezentować JavaFX, tak, tak - znowu JavaFX :D Właściwie to ten topic jest teraz (po JavaOne) bardzo trendy, gdyż w internecie można znaleźć bardzo dużo burzliwych dyskusji na temat JavaFX (świat Javy podzielił się na 2 fronty :D). Mam nadzieję, że i jutro nie zabraknie dyskusji zwłaszcza, że chciałem pewną, dość sporą ilość czasu przeznaczyć na luźną rozmowę na tematy Javowe (nie tylko JavaFX) takie jak JUG`i, community i rzeczy które się dzieją w naszej polskiej społeczności. Myślę, że może to być dość ciekawe, choćby dlatego, że zazwyczaj prelegenci rozmawiają na tematy związane tylko z prezentacją, a jeszcze inni zawsze uciekają na pociąg :P:P:P

Oto namiary:

Instytut Informatyki,Uniwersytet Gdański
ul. Wita Stwosza 57 Gdańsk,
aula nr 2. godzina 16:00

Wszystkich gorąco zapraszam!


NetBeans RoadShow

NetBeans WorldTourW dniach 11-13 kwietnia odbędzie się w Polsce NetBeans RoadShow, które wchodzi w skład NetBeans WorldTour 2007 - 2008. W ramach tego cyklu, w miastach takich jak Kraków, Warszawa i Wrocław odbędą się NetBeans Days, czyli wykłady na temat środowiska developerskiego NetBeans.

Uczestnicząc w spotkaniach będzie można się dowiedzieć wielu ciekawych rzeczy na temat możliwości tego mocno rozwijanego IDE.
Prelegentami podczas NetBeans Days będą zarówno inżynierowie Sun Microsystems z centrum w Pradze jak również nasi rodzimi prelegenci, znani z blogosfery. Również i ja będę miał okazję wystąpić - 13 kwietnia we Wrocławiu podczas mojej prezentacji “Visual Web Development w NetBeans” będziecie mieli okazję dowiedzieć się jak można w prosty i szybki sposób stworzyć aplikacje webowe za pomocą NetBeans. Więcej informacji na temat NetBeans RoadShow uzyskacie na stronie www.netbeansday.pl.

Wszystkich serdecznie zapraszam.


NetBeans, Maven 2 i TestNG

Dziś w południe dostałem takiego oto maila:

“Witam,

Znalazlem mail do Pana na JDN. Od wczoraj walcze z proba polaczenia
TestNG oraz Mavena2 pod Netbeans. Mimo iż w lokalnym repozytorium mam
pakiet TestNG i w przeglądarce projektow w TestLibraries widnieje wpis
testing-4.7-jdk15 to jednak gdy probuje napisac jakikolwiek test to
nie mam dostepu do zadnego klas/adnotacji z biblioteki TestNG - jakby
jej nie bylo na classpath.

Dodam jeszcze ze w przegladarce projektow ikona biblioteki TestNG w
gorjen czesci jest brazowa, podczas gdy ikony innych - szare.

Ponizej zamieszczam fragmenty mojego pliku pom.xml”

Poniżej fragment pliku pom.xml i imię autora maila.

W przerwie między dewelopmentem który przydarzył mi się w te święta, postanowiłem odpowiedzieć na tego maila… na blogu :D

A więc opiszę po krótko jak skonfigurować prosty projekt w NetBeans 6.1 Beta , do projektu wygeneruję plik pom.xml oraz dodam prościutki test TestNG.

Krok 1 - utworzenie projektu

Utwórzmy najpierw projekt z użyciem NetBeans 6.1 Beta oraz skonfigurujmy go jako projekt Maven 2. W tym celu wybieramy z menu opcję File -> New Project , następnie pojawi nam się takie oto okienko:

Rysunek 1

Wybieramy w nim opcję Maven -> Maven Project i klikamy Next.

Następny ekran to wybranie archetypu, wybieramy Maven Quickstart Archetype i klikamy Next:

Rysunek 2

Teraz czas na nadanie groupId i artifactId naszemu projektowi, ja zrobiłem to tak jak widzicie na poniższym obrazku:

Rysunek 3

Teraz kliamy Finish i proszę, oto nasz projekt:

Rysunek 4

Składa się on z przykładowego pliku aplikacji (App.java) oraz przykładowego testu (AppTest.java).

Krok 2 - modyfikacja projektu

Ponieważ w tym wpisie interesuje nas TestNG a przykładowy test jest napisany dla JUnit to możemy go usunąć - napiszemy swój od podstaw :D
Zmodyfikujmy nasz plik pom.xml na następujący (ten plik dotyczy mojego projektu, jeśli nadaliście inne groupId i artifactId to musicie go zmienić analogicznie):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.holewa</groupId>
  <artifactId>test</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>test</name>
  <url>http://www.holewa.org</url>
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.6</version>
      <scope>test</scope>
      <classifier>jdk15</classifier>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Teraz zmieńmy ustawienia naszego projektu tak aby ustawić dla niego wersję Java zgodną z wersja 1.5, w tym celu wybierzmy z menu kontekstowego naszego projektu opcję Properties, następnie z listy w okienku po lewej stronie opcję Sources i na dole ekranu który nam się ukaże Source/Binary Format ustawmy na 1.5. Możecie to zobaczyć na poniższym obrazku:

Rysunek 4b

NetBeans zmodyfikuje nasz plik pom.xml, dodając do niego taki fragment kodu:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>RELEASE</version>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
</plugin>

Dobra, teraz wybierzmy z menu kontekstowego projektu opcję Clean and Build, projekt nam się przebuduje a TestNG dodane jako zależność do naszego pom`a pobierze się z repozytorium Maven 2.

Krok 3 - pisanie testu

Nadszedł czas na nasz test :D W tym celu tworzymy nowy plik xml o nazwie testng.xml, musi się on znajdować w tym katalogu w którym znajduje się nasz pom.xml, jego zawartość będzie następująca:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Simple test siute">
  <test name="Simple test">
    <classes>
      <class name="org.holewa.test.SimpleTest"/>
    </classes>
  </test>
</suite>

Podaliśmy w nim, że nasz projekt zawiera jeden test org.holewa.test.SimpleTest w takim razie czas na jego napisanie :)
Dodajmy nową klasę do projektu, klikamy prawym przyciskiem myszy na gałąź Test Packages w strukturze projektu, następnie wybieramy opcję New -> Java Class… i dodajemy klasę org.holewa.test.SimpleTest.

Kod znajdujący się w niej powinien mieć następującą postać:

package org.holewa.test;
 
import org.testng.annotations.*;
 
public class SimpleTest {
 
  @Test
  public void simpleTest() {
    System.out.println("My simple test.");
  }
}

Zapiszmy plik. Wybierzmy z menu kontekstowego projektu opcję Clean and Build, w logach które pojawią się na dole w okienku zobaczymy podobną treść:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
[Parser] Running:
  C:\Documents and Settings\raho\My Documents\NetBeansProjects\test\testng.xml
My simple test.

To znak, że nasz test się wykonał, gdy zmienimy kod metody testowej na:

@Test
public void simpleTest() {
  System.out.println("My simple test.");
  assert false;
}

Dostaniemy podobny komunikat do tego:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
[Parser] Running:
  C:\Documents and Settings\raho\My Documents\NetBeansProjects\test\testng.xml
My simple test.
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.297 sec <<< FAILURE!
Results :
Failed tests: 
  simpleTest(org.holewa.test.SimpleTest)
------------------------------------------------------------------------
[ERROR]BUILD FAILURE
------------------------------------------------------------------------
There are test failures.

Gdy wybierzemy teraz z menu kontekstowego projektu opcję Test ukarze nam się wynik w okienku testów JUnit:

Rysunek 6

Niestety NetBeans nie posiada wtyczki do obsługi testów TestNG, stąd też pojawiające się okienko JUnit ;(

Ponieważ w mailu który był na samym początku padło stwierdzenie “Dodam jeszcze ze w przegladarce projektow ikona biblioteki TestNG w gorjen czesci jest brazowa, podczas gdy ikony innych - szare”, chciałem wytłumaczyć opisaną w nim sytuację.

Zobaczmy na widoku projektu:

Rysunek 5

A dokładnie bibliotek które się znajdują w zależnościach. Biblioteki zaznaczone kolorowo to bezpośrednie zależności w naszym pom.xml, biblioteki zaznaczone na szaro to biblioteki które są zależnościami do naszych zależności, stąd też inne ich oznaczenie, gdyż nie wprowadzaliśmy ich do projektu bezpośrednio - wprowadził je twórca dodanej przez nas biblioteki ustawiając je jako zależność bez której jego biblioteka nie może funkcjonować. Gdy chcemy ustawić tą bibliotekę tak aby nie była dodana do naszego projektu możemy to zrobić w bardzo łatwy sposób, wystarczy wybrać w menu kontekstowym biblioteki opcję Exclude Dependency a nasz pom.xml zostanie automatycznie zmodyfikowany. Prawda, że łatwe? :D


DWR czyli “Easy Ajax for Java”

Jeśli ktoś jeszcze jakimś cudem nie wie co to DWR (Direct Web Remoting) to ten wpis jest dla niego, ponieważ postaram się w nim szybko przedstawić co to jest i jak tego można używać :)

DWR to biblioteka która pozwala z poziomu JavaScript wywołać metody Java oraz vice versa.
W jaki sposób rozpocząć przygodę z DWR? Najprościej pobrać go ze strony i wykonać kilka kolejnych kroków opisanych w tym wpisie.

Krok 1 - dodanie konfiguracji DWR do web.xml.

Chcąc użyć DWR w naszej webowej aplikacji musimy ją najpierw skonfigurować. Na samym początku wprowadzimy ustawienia do naszego pliku web.xml. Dodajmy do niego ten fragment kodu:

<servlet>
  <servlet-name>dwr</servlet-name>
  <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
  <init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
  </init-param>
</servlet>
 
<servlet-mapping>
  <servlet-name>dwr</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

W ten sposób dodaliśmy serwlet DWR do naszej aplikacji. Serwlet ten odpowiada za generowanie plików JavaScript które będą wykorzystane w stronach JSP tworzonych w projekcie.

Krok 2 - Integracja DWR i Spring Framework.

Ponieważ Spring Framework jest szeroko stosowany w projektach opartych o platformę JEE stąd też DWR w łatwy sposób się z nim integruje. Wystarczy dodać do naszego projektu plik zawierający definicję beanów:

<?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:dwr="http://www.directwebremoting.org/schema/spring-dwr"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.directwebremoting.org/schema/spring-dwr
       http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd">
 
  <dwr:configuration>
    <dwr:convert class="org.holewa.Sample" type="bean"/>
  </dwr:configuration>
 
  <bean id="dwrFacade" class="org.holewa.DwrFacade">
    <dwr:remote javascript="dwrFacade">
      <dwr:include method="getData"/>
    </dwr:remote>
  </bean>
</beans>

W powyższym przykładzie zdefiniowaliśmy jeden bean o nazwie dwrFacade oraz udostępniliśmy dla DWR jedną jego metodę o nazwie getData, domyślnie z uwagi na względy bezpieczeństwa wszystkie metody nie są udostępnione.
Podobnie zresztą ma się sprawa z transfer object`ami - musimy dla nich ustawić konwersję czyli sprawić aby DWR mapował odpowiednie struktury danych z poziomu JavaScript na obiekty Java. W naszym przypadku transfer object Sample zawiera tylko jedną zmienną o nazwie parameter.

Krok 3 - dodanie plików JavaScript do naszych stron JSP.

Aby umożliwić wywołanie metod po stronie serwera należy dodać w stronach JSP taki oto fragment kodu:

<script type='text/javascript' src='/dwr/interface/dwrFacade.js'></script>
<script type='text/javascript' src='/dwr/engine.js'></script>
<script type='text/javascript' src='/dwr/util.js'></script>

Pliki util.js i engine.js to pliki wchodzące w skład DWR, plik dwrFacade.js to plik który został wygenerowany przez serwlet i to właśnie dzięki funkcją które znajdują się w nim możemy wywołać metodę po stronie serwera.

Krok 4 - wywołanie metody po stronie serwera.

W celu wywołania metody po stronie serwera należy wywołać w przeglądarce następującą funkcję:

function refreshData( elementId, param ) {
  var to = {
    parameter: param 
  };
  dwrFacade.getData(to, function ( str ) {
    dwr.util.byId(elementId).innerHTML = str;
  });
}

Powyższy kod definiuje funkcję która jako parametry przyjmuje id elementu którego atrybutowi o nazwie innerHTML chcemy przypisać wartość zwróconą przez wywoływaną przez nas metodę getData. Metoda ta przyjmuje jeden parametr który jest obiektem zawierającym pole (atrybut) o nazwie parameter, podczas przesyłania będzie on przekształcony w obiekt Java dla którego wartości atrybutu parameter będzie równa wartości atrybutu parameter którą ustawiliśmy w JavaScript. Funkcja która zostanie wywołana gdy otrzymamy odpowiedź od serwera (pamiętajmy, że występują tu wywołania asynchroniczne dlatego też mamy do czynienia z callback`ami) jest przekazywana do funkcji dwrFacade.getGetData jako drugi parametr.

Jak widzicie zastosowanie DWR jest niezwykle proste - od jego konfiguracji do wywołania zrobiliśmy właściwie tylko cztery główne kroki :D

Pisząc ten wpis nie zauważyłem, że na j2ee.pl jest już pewnien opis DWR - dużo dłuższy więc go Wam gorąco polecam a siebie biję w pierś za duplikowanie tematu. :D


SunSPOT i inne prezentacje :)

Już w najbliższą środę o godzinie 18:30 w sali numer 3 na Politechnice Krakowskiej będę miał okazję przedstawić część możliwości SunSPOT`a, spotkanie to ma też zapoczątkować cykl spotkań dotyczących inżynierii oprogramowania które były pomysłem moim i Tomka Treli :)
Chciałem również nawiązać do komentarza Radka Kozaka i wspomnieć o innych moich prezentacjach. Otóż zostałem zaproszony do Szczecina na konferencję java4people organizowaną przez Szczecin JUG, tematem mojej prelekcji będzie… JavaFX, mało tego - zostałem już zapisany na wizytę 8mego maja w… Gdańsku gdzie odbędzie się spotkanie JUG Trójmiasto !!!. Tak, tak - mamy już sporo JUG`ów w Polsce :D Najlepsze to to, że wszystkie (no może oprócz poznańskiego) ostro ostatnio działają. Jeśli już piszę o działalności to chciałem zwrócić uwagę na to co dzieje się we Wrocławiu - tamtejszy JUG bije wszystko inne co możemy uświadczyć w kraju. Wystarczy, że zobaczycie na częstotliwość spotkań które są tam organizowane (czasami to wydaje mi się, że aż zbyt często :P). Nie wiem jak to robi Paweł Szulc ale w pojedynkę rozkręca to na maxa - brawo Paweł !!! Mam nadzieję, że będziemy mieli okazję spotkać się ponownie w Warszawie na JAVArsovi którą organizuje Warszawa JUG i która podobno (wg. szimano) ma za 2 lata przebić SFI.


Studencki Festiwal Informatyczny 2008

W dniach 6-8 marca 2008 odbędzie się kolejna, czwarta edycja Studenckiego Festiwalu Informatycznego, bezpłatnej i największej imprezy informatycznej w naszym kraju.
Jak i w poprzednich latach, tak i w tym roku będziemy mieli kolejnych znakomitych gości, wymienię Wam tylko trzech z nich : Joe Armstrong, Gilad Bracha, Chad Fowler myślę, że ich nazwiska w zupełności wystarczą do tego aby zachęcić Was do zaglądnięcia na stronę festiwalu i zarejestrowania się.
Jak już wcześniej pisałem, udział w festiwalu jest darmowy i w dodatku nie dotyczy tylko studentów, a co za tym idzie macie możliwość wzięcia udziału w najlepszej imprezie IT w jakiej możecie uczestniczyć w Polsce i to w dodatku za darmo!!!
Niemożliwie? A jednak!:D
I Wy możecie się przyczynić do promowania tej imprezy, wystarczy, że umieścicie na swoim blogu/stronie baner naszego festiwalu wklejając następujący kod :

<embed width="500" height="100" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" 
           type="application/x-shockwave-flash" flashvars="$swf.flashvars" allowscriptaccess="samedomain" 
           swliveconnect="true" name="SFI video" quality="high" src="http://www.sfi.org.pl/files/swf/500_100_white.swf"/>

Umieścicie w ten sposób taki oto baner :

Gdy już to zrobicie, to dajcie mi proszę koniecznie o tym znać na adres radek[małpka]holewa[kropeczka]org .

Jeśli chcecie umieścić inny baner to znajdziecie tutaj więcej informacji na ten temat.


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 :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
 
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
 
  <servlet>
    <servlet-name>sampleservlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
        /WEB-INF/sample-servlet.xml
        /WEB-INF/sample-flow.xml
      </param-value>
    </init-param>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>sampleservlet</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>
 
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

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 :

<?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.5.xsd">
 
  <bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController">
    <property name="flowExecutor" ref="flowExecutor"/>
  </bean>
 
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
 
  <import resource="sample-flow.xml"/>
</beans>

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

Oczywiście teraz zdefiniujemy główny plik konfiguracyjny flow (sample-flow.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"
       xmlns:flow="http://www.springframework.org/schema/webflow-config"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/webflow-config
      http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd">
 
  <flow:executor id="flowExecutor" registry-ref="flowRegistry"/>
 
  <flow:registry id="flowRegistry">
    <flow:location
      path="/WEB-INF/flows/**/*-flow.xml"/>
  </flow:registry>
 
</beans>

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 :

<?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="sampleController" class="org.holewa.webflow.controller.SampleController"/>
 
</beans>

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

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
        http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
 
  <start-state idref="list"/>
 
  <view-state id="list" view="listForm">
    <render-actions>
      <bean-action bean="sampleController" method="loadData">
        <method-result name="result"/>
      </bean-action>
    </render-actions>
  </view-state>
 
</flow>

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" %>
<html>
<head><title>Lista blogów</title></head>
<body>
<ul>
  <c:forEach var="item" items="${result}">
    <li><a href="${item.link}">${item.name}</a></li>
  </c:forEach>
</ul>
</body>
</html>

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<SampleVO>();
    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" %>
<html>
<head><title>Lista blogów</title></head>
<body>
 <a href="/flowController.htm?_flowId=first-flow">Uruchom flow</a>
</body>
</html>

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


Refleksje po mojej prezentacji na spotkaniu Warszawa JUG

Byłem wczoraj w Warszawie na spotkaniu Warszawa JUG gdzie prezentowałem JavaFX. Muszę powiedzieć, że moje wrażenia są pozytywne a nawet bardzo pozytywne :)
To co najbardziej mi się podobało to fakt, że Warszawa JUG jest zgrana, było dużo pytań, wymian zdań. To co mnie zdziwiło to fakt, że nikt mnie nie pojechał za moje “hasła”, które momentami były chyba zbyt luźne (pewnie nie oberwało mi się tylko przez grzeczność) :)
Prezentację oceniam jako dobrą, nie jestem do końca zadowolony, nie przedstawiłem wszystkiego co chciałem :/
Niestety 45-50 minut to naprawdę zbyt mało jak na taką prezentację (normalnie zajmuje mi 90 minut) stąd też zmuszony byłem ją obciąć z 50 slajdów do 27 :(
Ciekawe jakie są refleksje po spotkaniu ? Wiktor Gworek stwierdził, że dyskusja podczas prezentacji nie była zbyt dobrym rozwiązaniem z uwagi na fakt, że “wchodziliśmy sobie w słowo”. Hmmmm sam nie wiem, ogólnie lubię tego typu dyskusje :D
Ja jedynie żałuję, że nie odpalił mi się przykład z Jackiem Laskowskim w roli głównej, napisałem go w nocy dzień przed prezentacją, był to szybki pomysł na prostą prezentację możliwości JavaFX w dodatku mogło być dużo dobrej zabawy przy implementowaniu “transformacji” Jacka :D

Oto kod tego przykładu wraz z linkiem do JavaFXPada w którym możecie sobie go uruchomić, i np. poćwiczyć transformacje jak choćby sprawić żeby Jacek chodził trochę “wygięty” (miałem do tego stosowny komentarz ale zostawię go dla siebie) :D
No nic, trudno - chłopakowi się upiekło, jego szczęście :P

package animationdemo;

import javafx.ui.canvas.*;
import javafx.ui.*;

class Model {
    attribute xpos:Number;
}

Group {
    var model = Model
    transform:
    [Translate {
        x: bind model.xpos
    }]
    content: [
    ImageView {
        image: Image {
            url: "http://www.holewa.org/images/JacekLaskowski.jpg"
        }
    },Line {
        x1: 60
        x2: 60
        y1: 140
        y2: 300
        stroke: black
        strokeWidth: 7
    },Line {
        x1: 60
        x2: 100
        y1: 200
        y2: 250
        stroke: black
        strokeWidth: 7
    },Line {
        x1: 60
        x2: 20
        y1: 200
        y2: 250
        stroke: black
        strokeWidth: 7
    },Line {
        x1: 60
        x2: 100
        y1: 300
        y2: 450
        stroke: black
        strokeWidth: 7
    },Line {
        x1: 60
        x2: 20
        y1: 300
        y2: 450
        stroke: black
        strokeWidth: 7
    }, Ellipse {
        cx: 53
        cy: 102
        stroke: red
        fill: red
        radiusX: 10
        radiusY: 5
    }]
    onMouseClicked: operation(e) {
        model.xpos = [1..500] dur 2000 linear;
    }
};

Jeśli macie jakieś odczucia po mojej prezentacji czy to dobre czy złe to byłbym wdzięczny za podzielenie się nimi, pozwoli mi to przygotować się jeszcze lepiej do kolejnego mojego większego wystąpienia, które będę miał w Szczecinie 10 marca. Będzie to wystąpienie na konferencji organizowanej przez Szczecin JUG.