JavaFX jako GUI do JBoss Seam? Nie ma problemu!

post_img

Jakiś czas temu napisałem artykuł opisujący wstępne założenia JavyFX. Wtedy też obiecałem, że gdy uda mi się uruchomić aplikację FXową na serwerze aplikacyjnym, podzielę się doświadczeniem. Właśnie nadszedł ten czas.

Często można spotkać opinie, że JavaFX nie ma przyszłości, bo nie posiada żadnego wsparcia dla komunikacji z elementami biznesowymi. Kiedyś być może było to prawdą, dziś naprzeciw takim oczekiwaniom wychodzi Flamingo. Jest to framework, który może stać się czymś w rodzaju „kleju” łączącego teoretycznie różne technologie, m.in. JavyFX i Seama.

Aby nie pozostawiać słów bez pokrycia, przygotuję projekt, który zaprezentuje możliwości Flamingo. Pokaże on jak łączyć JavaFX z Seamem. Na koniec wszystko wrzucimy na serwer aplikacji i uruchomimy z poziomu przeglądarki.

Zacznijmy od klasycznego projektu Seama. Wykorzystam tu Eclipse 3.5.2, Seama 2.2, JBossa 5.1 oraz JBoss Tools dla Eclipse, żeby szybko wygenerować działającą aplikację. Jeżeli jeszcze ich nie masz, czas się zaopatrzyć w te niezbędne narzędzia.

W Eclipse wybieramy New – > Other -> Seam -> Seam Web Project

Wypełniamy pola formularza:

  • nazwa projektu: SeamApp
  • Target runtime: JBoss 5.1 Runtime
  • Dynamic Web Module Vesion: 2.5
  • Target Server: JBoss 5.1 Runtime Server
  • Configuration: Dynamic web project with JBoss Seam 2.2.0

Najprawdopodobniej nazwy docelowego runtime’u i serwera będą inne – w zależności od tego co sobie skonfigurujemy. Najważniejsze, by wybrać JBoss 5.1 (Seam 2.2. teoretycznie działa też na wcześniejszych wersjach).

Przez kilka kolejnych ekranów konfiguratora możemy przeskoczyć z domyślnymi ustawieniami. Dotrzemy ostatecznie do ekranu z wyborem bazy danych i sposobu deploymentu aplikacji. Ponieważ przykłady mają być proste, wybieramy pakowanie do war i bazę HSQLową – lub dowolną inną, nie będziemy korzystać tutaj z tego elementu.

Możemy zmienić jeszcze domyślne pakiety, ale nie jest to konieczne.

Wygenerowana aplikacja jest gotowa do użycia i deploymentu – zawiera wszystkie niezbędne elementy do uruchomienia, przykładowe strony oraz klasę Authenticator służącą do autentykacji użytkownika w systemie. Dla pewności możemy uruchomić aplikację by upewnić się, że wszystko poszło ok.

Aby móc podpiąć się do aplikacji za pomocą JavaFX, musimy dodać do niej kilka niezbędnych elementów. Są to biblioteki Flamingo (linki do wszystkich materiałów znajdują się na końcu artykułu):

  • amf-serializer.jar
  • flamingo-service.jar
  • flamingo-services-common.jar
  • hessian.jar
  • scannotation.jar

Umieszczamy je bezpośrednio w katalogu lib aplikacji. W skład Flamingo wchodzi jeszcze parę bibliotek, ale do podstawowego przykładu wystarczą te. Aby móc wywoływać komponenty Seam musimy jeszcze dodać do pliku web.xml wpis definiujący servlet, który będzie odpowiadał za komunikację JavaFX z Seamem

1
2
3
4
5
6
7
8
<servlet>
    <servlet-name>Hessian Remote Servlet</servlet-name>
    <servlet-class>com.exadel.flamingo.service.seam.HessianToSeamServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Hessian Remote Servlet</servlet-name>
    <url-pattern>/flamingo/hessian/*</url-pattern>
</servlet-mapping>

Teraz już możemy dostać się do dowolnego komponentu Seam w naszej aplikacji za pomocą Flamingo. Przykładowa aplikacja posiada tylko jeden komponent (autentykator), więc wykorzystajmy go, aby nie komplikować całości. Do klasy Authenticator.java dodajmy metodę

1
2
3
public String hello(String name){
        return "Hello " + name +"!";
}

Pozostanie ona naszą metodą, którą będziemy wywoływać z poziomu aplikacji FX-owej.

Czas na stworzenie klienta tej jakże wyrafinowanej metody. 😉

W Eclipse tworzymy nowy projekt, w którym znajdą się zarówno klasy Java jak i JavaFX. Polecam by zainstalować sobie wytczkę  Exadel JavaFX Eclipse plugin. Ułatwia ona nieco tworzenie projektów FX-owych w Eclipse. Do tej części wymagane jest też posiadanie JavaFX 1.3 SDK. Jeżeli jeszcze go nie masz – czas zainstalować.

Wybieramy New -> Other -> JavaFX -> JavaFX Project

Na kolejnych ekranach wizarda wybieramy nazwę projektu (FxClient), wersję SDK JavyFX, oraz JDK do wykorzystania w projekcie. Po „doklikaniu” do końca wizarda zostanie utworzony projekt ze wszystkimi niezbędnymi bibliotekami do pisania uruchamiania aplikacji FXowej.

Aby móc skorzystać z mechanizmów Seamowych, musimy dodać jeszcze trzy biblioteki. Tworzymy katalog lib i wrzucamy do niego:

  • jboss-seam.jar (z instalacji seama)
  • jboss-seam-remoting.jar (jw.)
  • hessian.jar (ta sama wersja co w aplikacji Seamowej)

Teraz musimy dodać interfejs, który będzie bramką do naszej usługi seamowej. W idealnym świecie pewnie byłby on zawarty w dostarczonym z zewnątrz jarze z API, ale upraszczamy wszystko jak możemy.

1
2
3
4
5
package pl.atena.client.seam.api;

public interface HelloWorld {
     public String hello(String name);
}

Potrzebna będzie też fabryka tej usługi, dodajmy więc i ją:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package pl.atena.client.java;

import java.net.MalformedURLException;

import com.caucho.hessian.client.HessianProxyFactory;

import pl.atena.client.seam.api.HelloWorld;

public class HelloWorldClient {

    public static HelloWorldClient CLIENT;

    private String _url;
    private HelloWorld _service;

    private HelloWorldClient(String url) {
        _url = url;
    }

    public static void setServerUrl(String url) {
        CLIENT = new HelloWorldClient(url);
    }

    private HelloWorld getService() {
        if (_service == null) {
            try {
                HessianProxyFactory factory = new HessianProxyFactory(); //(1)
                _service = (HelloWorld) factory.create(HelloWorld.class, _url); //(2)
            } catch (MalformedURLException ex) {
                System.out.println(ex);
            }
        }
        return _service;
    }

    public String hello(String s) {

        return getService().hello(s);

    }

}

Krótki komentarz do powyższego:

(1)   – Tworzymy nową instancję fabryki połączeń. Komunikacja za pomocą JavaFX i Seam odbywa się po protokole Hessian.

(2)   – Pobieramy instancję usługi HelloWorld na podstawie adresu URL zasobu. Parametr ten ustawimy już bezpośrednio w skrypcie FX i tam opiszę jego wygląd.

Pozostał nam jeszcze skrypt FX który skorzysta z usługi Seamowej. Utwórzmy go zatem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*

*MainFrame.fx

*

*Created on sie 12, 2010, 08:09:02 AM

*/

package pl.atena.client.fx;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.TextOrigin;
import javafx.ext.swing.SwingButton;
import javafx.scene.layout.VBox;
import javafx.scene.control.TextBox;

import pl.atena.client.java.HelloWorldClient;

class Hello{ //(1)

    public var name:String;
    public var str:String;    
}

var helloModel = new Hello();

HelloWorldClient.setServerUrl("http://localhost:8080/SeamApp/flamingo/hessian/authenticator"); //(2)

var helloText: TextBox = TextBox {
    text: bind helloModel.name with inverse //(3)
    columns: 7
    selectOnFocus:true
}

var helloLabel = Text{
    y:8
    font: Font { name:"sansserif", size: 12 }
    fill: Color.BLACK
    content: bind "Server says: {helloModel.str}"
    textOrigin: TextOrigin.TOP
}

var helloButton = SwingButton  {
    text:"Say Hello!"
    action: function(){
        helloModel.str = HelloWorldClient.CLIENT.hello(helloModel.name);
    } //(4)
}

Stage { //(5)
    title: "Helloworld Sample"
    width: 200
    height: 150
    scene: Scene {
        content: VBox {
            translateX: 5
            translateY: 5
            spacing: 10
            content: [                
                HBox {
                    content: helloText
                    spacing: 10
                },
                HBox {
                    content: helloButton
                    spacing: 10
                },
                HBox {
                    content: helloLabel
                    spacing: 10
                }
            ]
        }
    }
}

(1)    – Tworzymy miniklasę, w której będziemy trzymać imię do powitania, oraz odpowiedź z komponentu Seam.
(2)    – Ustawiamy adres do komponentu Seam do którego chcemy się odwołać. Generalnie powinien mieć on postać http://adres_serwera/kontekst_aplikacji/flamingo/hessian/nazwa_komponentu_seam, przy czym /flamingo/hessian to ścieżka dla servletu Flamingo którą wpisaliśmy w web.xml aplikacji seamowej.
(3)    – Wiążemy zawartość pola tekstowego z jedną ze zmiennych naszej miniklasy.
(4)    – Podpinamy wywołanie usługi pod kliknięcie na przycisk.
(5)    – Tworzymy scenę, na której umieszczone zostaną nasze elementy graficzne.

W tym momencie (jeżeli mamy uruchomioną aplikację seamową oczywiście) możemy już uruchomić aplikację FXową i sprawdzić czy wszystko się udało.

Jak widać, udało nam się wywołać komponent Seam z aplikacji desktopowej.

Czas podnieść sobie nieco poprzeczkę, i zrobić to samo z aplikacji webowej.

Tu też przydatny jest plugin do eclipse, gdyż może on za nas załatwić mozolną walkę z kompilacją do pliku jar wraz z wymaganymi bibliotekami (javafxpackager z linii poleceń też może to zrobić, ale wówczas trzeba się trochę napisać…).

Aby przygotować plik jar odpowiedni do wykorzystania na serwerze aplikacji wystarczy kliknąć na naszym skrypcie prawym przyciskiem myszy i wybierać Run as -> JavaFX Application (applet)

W folderze dist projektu zostaną utworzone następujące elementy

  • plik jar ze skompilowanym skryptem FX
  • pliki jnlp, umożliwiające uruchamianie aplikacji przez Java Web Start
  • strona html, w treści której umieszczony został aplet ze skryptem FX

Wszystko to przenosimy do katalogu WebContent naszej aplikacji Seamowej, zmieniamy nazwę wygenerowanego przez kompilator pliku html na index.html i robimy redeploy całej aplikacji. Teraz pod domyślnym adresem aplikacji seamowej powinniśmy otrzymać działający skrypt JavyFX

Prawda, że to proste?

Na koniec jeszcze jedna ciekawostka. Jeżeli zmodyfikujemy plik index.html i dodamy do definicji apletu parametr draggable, będziemy mogli dosłownie wyciągnąć aplet na pulpit (trzymając klawisz alt oraz lewy przycisk myszy) i korzystać z niego nawet po zamknięciu przeglądarki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>MainFrame</title>
</head>
<body>
<h1>MainFrame</h1>
<script src="http://dl.javafx.com/1.3/dtfx.js"></script>
<script>
    javafx(
        {
              archive: "MainFrame.jar",
              draggable: true,
              width: 400,
              height: 400,
              code: "pl.atena.client.fx.MainFrame",
              extPackages: "javafx.ext.swing",
              name: "MainFrame"
        }
    );
</script>
</body>
</html>

Podsumowując, Flamingo pozwala nam łatwo zintegrować aplikację FXową z aplikacją Seamową. Dzięki niemu możemy korzystać z komponentów Seama zarówno w aplikacji desktopowej, jak i wykorzystać JavaFX do stworzenia interfejsu użytkownika bezpośrednio w aplikacji seamowej. Aplikację przygotowaną w ten sposób bez problemu można umieścić na serwerze, a także udostępnić wersję desktopową przez jnlp. JavaFX nie zabrania wykorzystania innych elementów na stronie, może współistnieć z innymi elementami i bibliotekami. Czas więc zakasać rękawy i stworzyć prawdziwe RIA.

Zasoby i bibliografia

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *