UvodDoKomponent: EclipseProSpringDM |
from Wiki KIVu |
(autoři: Richard Lipka, Pavel Herout, Kateřina Štollová, verze z dubna 2012)
Pro práci se Spring existuje varianta Eclipse Spring Source Tool (http://www.springsource.com/developer/sts), ale s jejím spuštěním byly potíže. Na fórech se objevila informace, že funguje jen ve Windows Vista a vyšších. Pro práci se Spring se ale stejně dobře dá použít Eclipse s doinstalovanými nástroji, což je předmětem následujícícho návodu.
Eclipse IDE for Java EE Developers
(http://www.eclipse.org/downloads/) např. soubor eclipse-jee-indigo-win32.zip
c:\Program Files (x86)\
. Doporučuji pojmenovat adresář jako eclipseEE, aby se nepletl s případnou verzí EclipseSE
SpringSource Tool Suite
, nejlépe přes Eclipse Marketplace
SpringSource Tool Suite
, kliknout na Instal
Spring Dynamic modules
(http://www.springsource.org/osgi). Na stránce je několik odkazů, stáhněte si nejnovější oficiální verzi – v sekci Current GA release
, ne Spring Framework
. Před stažením je nutné vyplnit registrační formulář. (stahovat spring-osgi-1.2.1-with-dependencies.zip
)
Spring Dynamic modules
:
C:\
… cesta k SpringDM …\spring-osgi-verze\dist
bundly:
org.springframeork.osgi.core org.springframeork.osgi.extender org.springframeork.osgi.io
C:\
… cesta k SpringDM …\spring-osgi-verze\lib
bundly:
org.springframeork.aop org.springframeork.beans org.springframeork.context org.springframeork.core
\dist
, pak pokračujte Next >
\lib
. Kromě bundlů zapsaných v bodě 8 importujte navíc org.springframeork.osgi.catalina.osgi
HelloWorld
a změňte parametr This plugin is targeted to run with na hodnotu an OSGi framework, k dispozici je Framework Equinox. Pak pokračujte Next>
src
projektu vytvořte package cz.zcu.fav.kiv.lipka.test1
Hello
(později dávejte pozor na správné jméno třídy a package): package cz.zcu.fav.kiv.lipka.test1; public class Hello { public void start() throws Exception { System.out.println("Hello Spring World!!"); } public void stop() throws Exception { System.out.println("Goodbye Spring World!!"); } }SpringDM nevyžaduje, aby spouštěná třída implementovala nějaké rozhraní.
META-INF
je hotový soubor MANIFEST.MF
, který otevřete poklepáním a jeho textový obsah zobrazte kliknutím na záložku dole MANIFEST.MF
spring
který založte jako podadresář adresáře META-INF
. Spring (přes .springframeork.osgi.extender
) načítá všechny XML soubory, které v něm najde; není nutné, aby se nový konfigurační soubor nějak konkrétně jmenoval.
spring
v adresáři META-INF
– pravé tlačítko na META-INF
, pak New pak Folder.
congif.xml
– pravé tlačítko na spring, pak New pak File, dále zvolte dole v záložkách editovacího okna záložku Source.
Hello beana
, důležité je uvést atributy class
(třída která obsahuje spustitelný kód), init-method
(metoda, která se má volat po spuštění) a destroy-method
(metoda, která se volá při zastavení). Pozor na správné vyplnění jména třídy, včetně package, ve kterém je umístěna. Soubor může vypadat následovně:
<?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:osgi="http://www.springframework.org/schema/osgi" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"> <bean name="hello" class="cz.zcu.fav.kiv.lipka.test1.Hello" init-method="start" destroy-method="stop" /> </beans>
V takovém případě se třída jmenuje Hello
a je v package cz.zcu.fav.kiv.lipka.test1
.
Pro zvýšení přehlednosti je možné zavést Working sety
– v Package Exploreru je možné přepnout zobrazení Top Level Elements na Working sets.
V položce Configure working sets se dá nastavit, který projekt a bundle bude patřit do kterého working setu. Pomocí New je vhodné vytvořit projekt pro SpringDMBundle
a další projekt SpringDMProjects
pro náš projekt HelloWorld
– viz obrázek.
Tím dojde k výraznému zpřehlednění workspace. Srovnejte výsledek se zobrazením v Project Exploreru (Window/Show view/ Project Explorer).
Package explorer je obvykle v levé části okna (seznam všech projektů, jejich zdrojových textů a tak dále). K jeho nastavení se dostanete stisknutím šipky dolů v horní liště exploreru.
Nyní by projekt měl být hotový (obsahuje jednu třídu Hello
a konfigurační soubor) a je možné ho spustit. Pro spuštění je nutné spustit i bundly SpringDM
, které se importovaly do workspace.
Pokud projekt spouštíme poprvé, je nutné provést konfiguraci:
HelloWorld
otevřete kontextové menu a zvolte Run As -> Run configuration.
HelloWorld
a importované bundly ze seznamu výše.
ss
napsaným do konzole. Mezi nimi je i bundle se třídou Hello
, jmenuje se podle projektu HelloWorld
– podívejte se jaké je jeho id, například řádka ve výpisu 19 ACTIVE [=HelloWorld_1.0.0.qualifier=]znamená, že bundle
HelloWorld
má id 19
start id
a stop id
. Spuštění by mělo vypsat „Hello Spring Word!“ a zastavení „Goodbye Spring World!“. Po příkazu stop a vypsání (ss
) všech bundlů dostanete např.: 19 RESOLVED HelloWorld_1.0.0.qualifier
Existují dvě základní metody komunikace mezi komponentami – volání metod rozhraní, které komponenta poskytuje, nebo využití správce událostí, který dokáže předat zprávy registrovaným komponentám.
Vytvoříme dvě komponenty, server a klient. Server bude obsahovat okno s textem (JTextArea) a poskytovat rozhraní, přes které půjde text číst a zapisovat. Klient bude obsahovat podobné pole, do kterého půjde psát text. V klientovi budou navíc tlačítka, která umožní nahrát text na server tak, aby se na něm zobrazil, a tlačítko pro stáhnutí textu ze serveru a jeho zobrazení v poli klienta.
První návod obsahuje jen postup pro tvorbu komponent komunikujících pomocí rozhraní, ve druhém bude projekt rozšířen tak, aby využil správce událostí pro předávání zpráv.
ExampleClient
a ExampleServer
do adresáře Eclipse.
HelloWorld
postupujte až k bodu 4). Jeden bude sloužit jako klient (ExampleClient
), druhý jako server (ExampleServer
).
komponentygui
a komponentygui.server
.
komponentygui
vytvořte rozhraní IServer
– rozhraní, které server poskytuje navenek a přes které lze využívat jeho služby.
IServer
vytvořte metody, které bude server poskytovat. Bude to:
void zobrazOknoServeru()
– zobrazení okna serveru
void skryjOknoServeru()
– skrytí okna
String getText()
– získání textu v okně serveru
void setText(String text)
– nastavení textu v okně serveru
void addText(String text)
– přidání textu ke stávajícímu
komponentygui.server
vytvořte dvě třídy – KomponentaServer
a GUIServer
. KomponentaServer
bude implementovat rozhraní IServer
. Na třídách není nic zvláštního – KomponentaServer
po svém vytvoření vytvoří okno GUIServer
a metody rozhraní budou okno zobrazovat, skrývat a nastavovat nebo číst text. V příkladu je GUIServer
vytvořena děděním od Jframe
. Obě třídy zkopírujte z dodaného příkladu.
META-INF
vytvořte podadresář spring a v něm vytvořte xml
soubor beanDefinitionServer.xml
. Obsah souboru bude podobný jako v příkladu HelloWorld
, navíc je třeba jen doplnit, jaké rozhraní komponenta poskytuje: <?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:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd"> <bean id="InstanceServeru" name="Server" class="komponentygui.server.KomponentaServer" /> <osgi:service id="VolaniRozhrani" ref="InstanceServeru" interface="komponentygui.IServer" /> </beans>Rozhraní je popsáno v řádce
<bean id="InstanceServeru"…
služba InstanceServeru
je poskytována uvedenou třídou KomponentaServer
. <osgi:service id="VolaniRozhrani" ref="InstanceServeru"
… říká, jaké rozhraní (IServer
) službu definuje. Je důležité, aby se shodovalo označení služby v atributech ref
elementu osgi:service
a id v elementu bean
. Také je třeba dát pozor na jméno a třídy a rozhraní, aby se shodovalo s package a jménem souboru, ve kterém třída a rozhraní opravdu je.
MANIFEST.MF
v adresáři META-INF
. Soubor je už připravený, jen do něj doplníte potřebné řádky. Po otevření souboru se objeví pravděpodobně okno s Overview, pomocí dolní záložky se přepněte do MANIFEST.MF, abyste mohli přímo upravovat text souboru. Na konec doplňte řádku: Export-Package: komponentygui
komponentygui.klient
a v něm dvě třídy – GUIKlient
a KomponentaKlient
. Třída GUIKlient
bude obsahovat normálně vytvořené GUI s textovou oblastí a tlačítky pro zobrazení a skrytí okna serveru a pro získání textu a nahrání textu na server.
KomponentaKlient
bude sloužit pro komunikaci se serverem. Aby mohla tento úkol vykonávat, musí obsahovat referenci na instanci objektu splňujícího rozhraní IServer
. Bude tedy obsahovat privátní atribut server rozhraní IServer
(a tedy i importovat toto rozhraní z balíku komponentygui
) a metodu setOdkazNaServer(IServer odkazNaServer)
.
IServer
z projektu ExampleServer
je nutno zajistit pomocí kliknutí pravého tlačítka nad projektem ExampleClient
. Po vybrání Properties / Java Build Path záložky Projects přidejte pomocí tlačítka Add… projekt ExampleServer
. Rozhraní musí oba projekty sdílet, aby klient věděl, jak vypadají služby poskytované serverem.
KomponentaKlient
bude spouštěcí třída komponenty klienta, bude tedy obsahovat metodu start()
a v ní vytvoření okna GUIKlient
.
IServer
. Spring zajistí, že po spuštění získá klient správnou referenci na vytvořený objekt serveru.
META-INF
doplňte podadresář spring
a v něm soubor >beanDefinitionKlient.xml</code>. V souboru bude uvedeno, jaké rozhraní chce komponenta využívat: <?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:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd">
<osgi:reference id="RozhraniServeru"
interface="komponentygui.IServer" />
<bean name="Klient" class="komponentygui.klient.KomponentaKlient"
init-method="start" destroy-method="stop" >
<property name="odkazNaServer" ref="RozhraniServeru" />
</bean>
</beans>
Důležité je nastavení řádek <osgi:reference id="RozhraniServeru" …
, které označuje, jaké rozhraní komponenta požaduje, a <property name="odkazNaServer …
, kterým říkáte Springu, do jakého atributu má vložit referenci na instanci komponenty, která požadované rozhraní splňuje. Ze jména atributu pak Spring automaticky odvozuje jméno metody set, pokud je tedy jméno property odkazNaServer
, metoda se musí jmenovat setOdkazNaServer
.
IServer
tak, aby o ní věděl Spring. To se provádí v souboru >MANIFEST.MF</code> v adresáři META-INF
. Na jeho konec doplňte řádku Import-Package: komponentygui
HelloWorld
. Pro nastavení zvolte možnost Run … -> Run Configurations nad projektem ExampleClient
a zkontrolujte, že z workspace spouštíte projekty klienta i serveru a dále všechny balíky springframeworku jako v předchozím příkladu. Odeberte spouštění projektu HelloWorld
.
Pro využití správce událostí je nutné mít objekt EventAdmin
, který by ale měl být ve workspace
Elipsu. Není proto nutné ho stahovat. Při spouštění se ale bundle org.osgi.service.event
musí vybrat a spouštět s projektem.
Pokud nemáte EventAdmin
k dispozici, je třeba si ho stáhnout ze stránek Eclipse. Najdete ho na stránce http://download.eclipse.org/equinox/, v sekci Latest Release Builds, klikněte na nejnovější verzi a najděte část Add-on Bundles. Mezi nimi najděte org.eclipse.equinox.event
a stáhněte.
Získaný bundle importujte stejně jako bundly pro Spring framework. V menu zvolte File-> Import, v okně vyberte Plug-in Development / Plug-ins and Fragments, v dalším okně zvolte Import from Directory a zadejte cestu k bundlu. V posledním okně bude seznam dostupných bundlů, vyberte org.eclipse.equinox.event
a přidejte ho do seznamu. Při spouštění je nutné ho v konfiguraci také vybrat a spouštět.
Událost je objekt, který se skládá ze dvou částí – topic
a properties
. Topic
je textový atribut se jménem události, které slouží jako klíč. Properties
je HashMap
, jejíž obsah může být libovolný a která slouží k přenosu dat v události – typicky opět obsahuje textový klíč a hodnotu.
Pro komunikaci se zprávami upravíme předchozí příklad, který podstatně rozšíříme. Budeme využívat více klientů (zde dva). Každý klient může poslat serveru dva různé typy zpráv. První (tlačítko Posli text) posílá textový obsah okna. Druhý (tlačítko Zobraz server) posílá řetězec s novou X,Y souřadnicí okna serveru. Komunikace pomocí zasílání zpráv je obousměrná, takže server (tlačítkem Zprava klientům) posílá textovou zprávu s textem Ahoj kliente. Pozor, klient si aktuální text z okna serveru stahuje jako v předchozím případě přímým voláním metody serveru server.getText()
(nejedná se o zasílání zpráv – je to další možný způsob komunikace se serverem).
ExampleClientZpravy
a ExampleServerZpravy
do adresáře Eclipse.
SpringDM
. Opět by mělo dojít k jejich propojení, tedy měly by se stát projekty SpringDMProjects
.
ExampleServerZpravy
je třeba doplnit možnost přijímání zpráv. Aby to bylo možné, stiskněte nad projektem pravé tlačítko a zvolte Properties. V části Java Build Path je třeba v záložce Libraries doplnit knihovnu org.eclipse.osgi.services
(číslo verze). Přidejte ji tlačítkem Add External JARs, najdete ji v podadresáři plugins
adresáře eclipse s J2EE? instalací Eclipse.
ExampleClientZpravy
.
ExampleClientZpravy
na ExampleServerZpravy
(ne na původním ExampleServer
); nastavení je ve vlastnostech projektu ExampleClientZpravy
, v záložce Java build path / Projects
ExampleServerZpravy
přibyl v souboru >MANIFEST.MF</code> řádek Import-Package: org.osgi.service.event
ExampleClientZpravy
se změnil v souboru >MANIFEST.MF</code> řádek Import-Package: komponentygui, org.osgi.service.event
IServer
přibyly konstanty používané jako klíče pro předávání zpráv: // bude pouzit v definicnim souboru Springu - nesmi obsahovat mezery String TOPIC_ZPRAVY_PRO_KLIENTA = "Zprava_pro_klienta"; String TOPIC_ZPRAVY_PRO_SERVER = "Zprava_pro_server"; // pouziti jen v Java souborech String TYP_ZPRAVY_PRO_SERVER_SOURADNICE = "X,Y souradnice textove"; String TYP_ZPRAVY_PRO_SERVER_TEXT = "Text v okne"; String TYP_ZPRAVY_PRO_KLIENTA_TEXT = "Text v okne";
beanDefinitionServer.xml
je doplněn o informaci, že komponenta je schopna naslouchat událostem. Přibyl element <osgi:service id="PoslouchaniZprav" ref="InstanceServeru" interface="org.osgi.service.event.EventHandler" > <osgi:service-properties> <entry key="event.topics" value="Zprava_pro_server" /> </osgi:service-properties> </osgi:service>Ten popisuje, na jaké události bude komponenta reagovat. V podstatě říká, že komponenta splňuje rozhraní, které jí umožňuje reagovat na události a že bude reagovat jen na události, jejichž topic obsahuje řetězec
Zprava_pro_server
. PoslouchaniZprav
je zvolené označení služby, můžete použít libovolný název. Až atribut ref
označuje třídu, která tuto službu využívá.
KomponentaServer
implementuje rozhraní EventHandler
a jeho metodou handleEvent(Event event)
přijímá od klientů dva typy zpráv. Rozlišuje je podle IServer.TYP_ZPRAVY_PRO_SERVER_TEXT@@
a IServer.TYP_ZPRAVY_PRO_SERVER_SOURADNICE
GUIServer
jednu (konstantní) zprávu klientům HashMap<String, String> properties = new HashMap<String, String>(); String zprava = "Ahoj kliente"; properties.put(IServer.TYP_ZPRAVY_PRO_KLIENTA_TEXT, zprava); zasilacZprav.sendEvent(new Event(IServer.TOPIC_ZPRAVY_PRO_KLIENTA, properties));
KomponentaKlient
implementuje rozhraní EventHandler
a jeho metodou handleEvent(Event event)
přijímá od serveru jeden typ zpráv.
GUIKlient
, a to metodami zasliXSouradniciServeru()
a posliTextDoOknaServeru(String text)
. Tělo těchto metod je podobné tělu zpráv od serveru, pouze je nutné správně nastavit topic zprávy, tj. IServer?.TOPIC_ZPRAVY_PRO_SERVER
a typ zprávy: buď TYP_ZPRAVY_PRO_SERVER_SOURADNICE
nebo TYP_ZPRAVY_PRO_SERVER_TEXT
.
beanDefinitionKlient.xml
) došlo k větším změnám. <osgi:reference id="ZasilacZprav" interface="org.osgi.service.event.EventAdmin" /> Tím říkáme, že komponenta bude vyžadovat služby EventAdmin. <bean id="InstanceKlient1" name="Klient1" class="komponentygui.klient.KomponentaKlient" init-method="start" destroy-method="stop" > <property name="odkazNaServer" ref="RozhraniServeru" /> <constructor-arg ref="ZasilacZprav"/> <constructor-arg value="1"/> </bean>
Tento element říká, že podle třídy KomponentaKlient
se vytvoří instance, nastaví se jí odkaz na instanci serveru (metodou setOdkazNaServer()
) a konstruktoru se pošlou dva skutečné parametry. První je reference na instanci EventAdmin
a druhý je číslo klienta.
<osgi:service id="PoslouchaniZprav1" ref="InstanceKlient1" interface="org.osgi.service.event.EventHandler" > <osgi:service-properties> <entry key="event.topics" value="Zprava_pro_klienta" /> </osgi:service-properties> </osgi:service>
Nyní můžete projekt spustit. Je třeba zkontrolovat, jestli jsou mezi spouštěnými bundly i org.eclipse.osgi.services
a org.osgi.service.event
, oba by měly být vidět v seznamu bundlů z workspace
. Pokud pracujete s kopií projektu, zkontrolujte také, jestli spouštíte upravené bundly (ExampleClientZpravy
a ExampleServerZpravy
). Pozor, názvy bundlů jsou přebírané z jejich manifestů, nejde o jména projektů.