Wst pę Modele powi za WS

Transkrypt

Wst pę Modele powi za WS
Katedra Architektury Systemów Komputerowych
Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej
mgr inż. Karol Bańczyk
Technologie Internetowe
Laboratorium nr 5.
Globus Toolkit
Temat: WebServices Resource Framework. Usługi z wieloma zasobami, własności zasobów.
Wstęp
Niniejsza instrukcja stanowi podzbiór informacji zawartych w punktach 3-6 doskonałego
samouczka programistów Globus Toolkit autorstwa Borji Sotomayora, dostępnego pod adresem:
http://gdp.globus.org/gt4-tutorial/ . Zaleca się przerobienie owego samouczka, zwłaszcza, gdy
ujęcie tematu w niniejszym opracowaniu okaże się dla czytelnika zbyt skondensowane.
Niniejsza instrukcja traktuje o tym, jak tworzyć i osadzać usługi sieciowe powiązane z zasobami na
platformie Globus Toolkit. Za zarządzanie takimi parami WS-Resource odpowiada specjalny
podsystem globusa implementujący specyfikację WebServices Resource Framework. Specyfikacja
ta stała się standardem organizacji OASIS. Można o niej poczytać na stronach: OASIS WSRF Page
oraz Globus WSRF Page . Najważniejszą przyczyną dla której owa specyfikacja powstała był fakt,
że istniejący standard WebServices, doskonale nadający się do sieci usług o globalnym zasięgu, nie
wypowiada się do problemu stanowości. Ten niedostatek uzupełnia właśnie WSRF, w którym mowa
już nie o samych usługach sieciowych, ale raczej o parach: WebService-Resource. Zasoby posiadają
własności (ResourceProperties), opisujące ich stan. Niniejsza instrukcja skupia się właśnie na tym,
jak można stworzyć i umieścić na platformie globus toolkit usługę sieciową połączoną z zasobami
oraz jak dostać się do własności owych zasobów.
Modele powiązań WS-R
Można wyróżnić 3 podstawowe modele powiązań usługi sieciowej z zasobami:
1. Implementacja usługi sieciowej oraz zasobu znajduje się w tej samej klasie.
2. Zasób i usługa sieciowa są różnymi klasami, zasób jest pojedynczym obiektem (Singleton).
3. Usługa sieciowa może działać w kontekście różnych zasobów.
Szerszy opis przypadków 1 i 2 znajduj się w samouczku w punktach 3 i 4. Niniejszym zostanie
szerzej przedstawiony przykład stworzony w zgodzie z trzecim modelem, najbardziej
rozbudowanym z pośród wymienionych.
Opis tego modelu można poprzeć niniejszym rysunkiem zaczerpniętym z samouczka:
Obiekt klienta współpracuje z dwoma usługami sieciowymi, nazwanymi na rysunku: Factory
Service i Instance Service. Rolą pierwszego z nich jest dostarczenie fasady pozwalającej stworzyć
nowy zasób (wzorzec projektowy Factory) i wykorzystać go w powiązaniu z usługą na nim
operującą, czyli właśnie Instance Service. Obiekt ResourceHome jest wykorzystywany przez
fabrykę do stworzenia nowego zasobu, który jest modelowany przez klasę Resource.
Dla rozpoznania tego modelu przedstawiony zostanie przykład usługi sieciowej obliczającą całkę na
zadanym obszarze. Obszar będzie dla prostoty jednowymiarowy i będzie opisany przez pewną
całkowitoliczbową funkcję f(n). Stworzenie i umieszcznie usługi sieciowej na zainstalowanym
kontenerze globus toolkit składa się z następujących etapów:
1. Zdefiniowanie interfejsu usług sieciowych (w tym przypadku InstanceService i
FactoryService). Interfejs definiuje się w języku nieco rozszerzonym na potrzeby stanowości
języku WSDL.
2. Implementacja usługi w języku programowania (w tym przypadku będzie to Java).
3. Zdefiniowanie plików deskryptorów: WSDD i JNDI.
4. Stworzenie archiwum GAR (globus archive) zbierającego wcześniej wytworzone artefakty i
wygenerowane na ich podstawie pieńki (stubs) w jednym miejscu.
5. Wdrożenie pliku archiwalnego na kontener globusa.
6. Stworzenie i uruchomienie pliku klienta.
Interfejs i własności usługi
Wszystkie plik wytwarzane w ramach tego opisu najlepiej pobrać z załączonego archiwum.
Interfejs usługi sieciowej będzie obejmować dwie operacje:
setRange(x1,x2), określającą zakres całkowania oraz
integrate(), rozkazujacą dokonania całkowania.
Stan zasobu, z którego będzie korzystać WS składać się będzie z czterech własności: x1, x2, state,
integral. Pierwsze dwie opisują przedział całkowania, trzecia określa stan zasobu (przed
całkowaniem, po całkowaniu, w trakcie całkowania, błąd), integral przechowuje informację o
wartości całki, o ile stan wskazuje na to, że została obliczona.
Interfejsy tworzonej usługi właściwej oraz fabryki w rozszerzonym języku WSDL przedstawione są
niżej. Nie będą tutaj dokładnie opisywane szczegóły, zwłąszcza, że istnieje pełna analogia do tego,
co opisane jest w samouczku w punkcie 3 oraz szczególnie w dodatku A1 http://gdp.globus.org/gt4tutorial/singlehtml/progtutorial_0.2.1.html#appendix_howto_wsdl .
Plik Range.wsdl definiujacy usługę RangeService ma postać:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="RegionService"
targetNamespace="http://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft01.wsdl"
xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:import
namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="../../wsrf/properties/WS-ResourceProperties.wsdl" />
<!--============================================================
T Y P E S
============================================================-->
<types>
<xsd:schema targetNamespace="http://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance"
xmlns:tns="http://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- REQUESTS AND RESPONSES -->
<xsd:element name="setRegion">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="x1" type="xsd:int"/>
<xsd:element name="x2" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="setRegionResponse">
<xsd:complexType/>
</xsd:element>
<xsd:element name="integrate">
<xsd:complexType/>
</xsd:element>
<xsd:element name="integrateResponse">
<xsd:complexType/>
</xsd:element>
<!-- RESOURCE PROPERTIES -->
<xsd:element name="X1" type="xsd:int"/>
<xsd:element name="X2" type="xsd:int"/>
<xsd:element name="State" type="xsd:string"/>
<xsd:element name="Integral" type="xsd:int"/>
<xsd:element name="RegionResourceProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="tns:X1" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="tns:X2" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="tns:State" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="tns:Integral" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<!--============================================================
M E S S A G E S
============================================================-->
<message name="SetRegionInputMessage">
<part name="parameters" element="tns:setRegion"/>
</message>
<message name="SetRegionOutputMessage">
<part name="parameters" element="tns:setRegionResponse"/>
</message>
<message name="IntegrateInputMessage">
<part name="parameters" element="tns:integrate"/>
</message>
<message name="IntegrateOutputMessage">
<part name="parameters" element="tns:integrateResponse"/>
</message>
<!--============================================================
P O R T T Y P E
============================================================-->
<portType name="RegionPortType"
wsdlpp:extends="wsrpw:GetResourceProperty"
wsrp:ResourceProperties="tns:RegionResourceProperties">
<operation name="setRegion">
<input message="tns:SetRegionInputMessage"/>
<output message="tns:SetRegionOutputMessage"/>
</operation>
<operation name="integrate">
<input message="tns:IntegrateInputMessage"/>
<output message="tns:IntegrateOutputMessage"/>
</operation>
</portType>
</definitions>
Plik Factory.wsdl definiujacy usługę FactoryService ma postać:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="FactoryService"
targetNamespace="http://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--============================================================
T Y P E S
============================================================-->
<types>
<xsd:schema targetNamespace="http://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService"
xmlns:tns="http://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import
namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="../../ws/addressing/WS-Addressing.xsd" />
<!-- REQUESTS AND RESPONSES -->
<xsd:element name="createResource">
<xsd:complexType/>
</xsd:element>
<xsd:element name="createResourceResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<!--============================================================
M E S S A G E S
============================================================-->
<message name="CreateResourceRequest">
<part name="request" element="tns:createResource"/>
</message>
<message name="CreateResourceResponse">
<part name="response" element="tns:createResourceResponse"/>
</message>
<!--============================================================
P O R T T Y P E
============================================================-->
<portType name="FactoryPortType">
<operation name="createResource">
<input message="tns:CreateResourceRequest"/>
<output message="tns:CreateResourceResponse"/>
</operation>
</portType>
</definitions>
Jeśli katalog rozpakowania dostarczonego archiwum to uznany zostanie za bieżący to przedstawione
pliki znajują się odpowiednio w ./scheme/lab5/RangeService_instance/Range.wsdl i
./scheme/lab5/FactoryService/Factory.wsdl. Miejsce plików jest istotne, a zwłaszcza liczba
zagłębień w stosunku do katalogu bieżącego.
Należy dodatkowo stworzyć plik o nazwie namespace2package.mapping w katalogu bieżącym
zawierający następujące mapowania przestrzeni nazw na pakiety zawierające klasy implementujące
i stuby.
http\://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance=org.pg.ti.lab5.stubs.RegionService_i
nstance
http\://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance/bindings=org.pg.ti.lab5.stubs.Region
Service_instance.bindings
http\://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance/service=org.pg.ti.lab5.stubs.RegionS
ervice_instance.service
http\://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService=org.pg.ti.lab5.stubs.FactoryService
http\://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService/bindings=org.pg.ti.lab5.stubs.FactoryService
.bindings
http\://eti.pg.gda.pl/namespaces/ti/lab5/FactoryService/service=org.pg.ti.lab5.stubs.FactoryService.
service
Implementacja
Wymagane jest, by klasy wchodzące w skład jednego archiwum GAR znajdowały się w pakiecie
postaci nazwa1.nazwa2.nazwa3.impl. Wówczas deskryptory jndi i wsdd będą w pakiecie
nazwa1.nazwa2.nazwa3. Na implementajcę skłądają się następujące klasy pakietu :
FactoryService, RegionQNames, RegionResourceHome, RegionResource, RegionService,
UniqueSequence i WorkerThread. Wszystkie zostały zawarte w pakiecie org.pg.ti.lab5.impl. Przed
przystąpieniem do implementacji klas warto wygenerować pieńki (stubs), gdyż bez tego będzie
niezręcznie tworzyć kod, który nie będzie się chciał skompilować.
Z tego powodu należy w katalogu rozpakowanego archiwum wywołać polecenia:
./globus-build-service.sh -d org/pg/ti/lab5 -s schema/lab5/RegionService_instance/Region.wsdl -t
stubs
./globus-build-service.sh -d org/pg/ti/lab5 -s schema/lab5/FactoryService_instance/Factory.wsdl -t
stubs
Spowoduje to wygenerowanie samych pieńków i pozwoli na kompilację tworzonych klas.
Implementajca klas FactoryService, RegionQName, RegionResourceHome, RegionResource jest w
pełni analogiczna do przykładu przedstawionego w samouczku w punkcie 5, więc nie będzie
omawiana szczegółowo. Klasa UniqueSequence została użyta na potrzeby uzyskania unikalnych
identyfikatorów kolejno tworzonych zasobów. Klasa WorkerThread została wprowadzona, by
zademonstrować, jak zadania mogą być wykonywane w tle. Z obiektem RegionService jest
skojrzaona prosta pula 10 wątków, które gotowe są do przyjmowania zleceń. W wypadku
wywołania na metody integrate na serwisie RegionService próbuje on przydzielić zadanie
całkowania zadanego obszaru całkowania jednemu z wolnych wątków. Gdy brak takiego wątku
zgłaszany jest wyjątek. Całkowanie przeprowadza zasób ze stanu UNINTEGRATED przez stan
INTEGRATING do stanu INTEGRATED, gdy proces został zakończony. Pozwoli do m.in.
klientowi określić, czy zasób już jest gotowy do odczytu.
Oto kod klasy implementującej usługę sieciową.
package org.pg.ti.lab5.impl;
import java.rmi.RemoteException;
import org.globus.wsrf.ResourceContext;
import org.pg.ti.lab5.stubs.RegionService_instance.Integrate;
import org.pg.ti.lab5.stubs.RegionService_instance.IntegrateResponse;
import org.pg.ti.lab5.stubs.RegionService_instance.SetRegion;
import org.pg.ti.lab5.stubs.RegionService_instance.SetRegionResponse;
import org.pg.ti.lab5.impl.WorkerThread;
import org.pg.ti.lab5.impl.WorkerThread;
public class RegionService {
WorkerThread[] thread = new WorkerThread[10];
public RegionService(){
// inicjalizacja puli wątków
for (int i=0; i< thread.length; i++){
thread[i] = new WorkerThread();
thread[i].start();
}
}
// pobieranie zasobu skojarzonego z danym wołaniem (kontekstem)
private RegionResource getResource() throws RemoteException {
Object resource = null;
try {
ResourceContext resourceContext = ResourceContext.getResourceContext();
System.out.println("resource key = " + resourceContext.getResourceKey());
resource = ResourceContext.getResourceContext().getResource();
} catch (Exception e) {
e.printStackTrace();
throw new RemoteException("", e);
}
return (RegionResource) resource;
}
// ustawienie obszaru całkowania
public SetRegionResponse setRegion(SetRegion setRegion) throws RemoteException{
System.out.println("setRegion(" + setRegion.getX1() +","+ setRegion.getX2() + ")");
RegionResource resource = getResource();
resource.setX1( setRegion.getX1() );
resource.setX2( setRegion.getX2() );
resource.setState(RegionResource.UNINTEGRATED);
resource.setIntegral(0);
return new SetRegionResponse();
}
// wysłanie polecenie całkowania
public IntegrateResponse integrate(Integrate integrate) throws RemoteException{
assignResourceToThread();
return new IntegrateResponse();
}
// próba przydzielenia wątku całkującego do bieżącego zasobu
synchronized private void assignResourceToThread() throws RemoteException {
for (int i=0; i<thread.length; i++){
if ( thread[i].isWaitingForNewRequests()) {
thread[i].performIntegration(getResource());
return;
}
}
throw new RemoteException("No worker thread available");
}
}
Deskryptory wdrożenia
W nadpakiecie pakietu impl zawierającego klasy implementacyjne powinny znaleźć się pliki
wdrożeniowe wsdd oraz jndi. Ich postać w przypadku omawianego przykładu jest następująca:
deploy-servier.wsdd:
<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultServerConfig"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Instance service -->
<service name="ti/lab5/RegionService" provider="Handler" use="literal" style="document">
<parameter name="className" value="org.pg.ti.lab5.impl.RegionService"/>
<wsdlFile>share/schema/lab5/RegionService_instance/Region_service.wsdl</wsdlFile>
<parameter name="allowedMethods" value="*"/>
<parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
<parameter name="scope" value="Application"/>
<parameter name="providers" value="GetRPProvider"/>
</service>
<!-- Factory service -->
<service name="ti/lab5/RegionFactory" provider="Handler" use="literal" style="document">
<parameter name="className" value="org.pg.ti.lab5.impl.FactoryService"/>
<wsdlFile>share/schema/lab5/FactoryService/Factory_service.wsdl</wsdlFile>
<parameter name="allowedMethods" value="*"/>
<parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
<parameter name="scope" value="Application"/>
<parameter name="instance" value="ti/lab5/RegionService"/>
</service>
</deployment>
Wiele z parametrów wdro eniowych poznanych ju było przy okazji laboratoriów zwi zanych z serwerem
AXIS. Na szczególn uwag zasługuje parametr “providers”, który dokonuje niejako wstrzykni cie
implementacji metody do serwisu RegionService umo liwiaj cej pobranie informacji o własno ciach zasobu
skojarzonego z usług . Mo liwe jest to równie dzi ki atrybutowi
wsdlpp:extends="wsrpw:GetResourceProperty" zdefiniowanemu w pliku WSDL, stanowi cemu zarazem punkt
rozszerzenia standardowego WSDL.
deploy-jndi-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
<!-- Instance service -->
<service name="ti/lab5/RegionService">
<resource name="home" type="org.pg.ti.lab5.impl.RegionResourceHome">
<resourceParams>
<parameter>
<name>resourceClass</name>
<value>org.pg.ti.lab5.impl.RegionResource</value>
</parameter>
<parameter>
<name>factory</name>
<value>org.globus.wsrf.jndi.BeanFactory</value>
</parameter>
<parameter>
<name>resourceKeyType</name>
<value>java.lang.Integer</value>
</parameter>
<parameter>
<name>resourceKeyName</name>
<value>{http://eti.pg.gda.pl/namespaces/ti/lab5/RegionService_instance}RegionResourceKey</value>
</parameter>
</resourceParams>
</resource>
</service>
<!-- Factory service -->
<service name="ti/lab5/RegionFactory">
<resourceLink name="home" target="java:comp/env/services/ti/lab5/RegionService/home"/>
</service>
</jndiConfig>
Plik JNDI wdra a obie usługi. Parametry dokonuj powi zania usługi z obiektem Home oraz z obiektem
zasobu. Dodatkowo przekazywana jest informacja o typie klucza identyfikuj cego usług oraz o jego
kwalifikowanej nazwie. W zeł resourceLink pozwala na odwołanie si do własno ci zdefiniowanej gdzie indziej
w pliku, w tym wypadku do własno ci home usługi RegionService. Przypisana ona zostaje te usłudze fabryki.
Plik GAR
Gdy wszystkie pliki są już gotowe należy skorzystać ze skryptu globus-build-service.sh . Dla
wygody najlepiej stworzyć plik build.mappings w katalogu bieżącym i wpisać w nim wiersz:
factory,org/pg/ti/lab5,schema/lab5/RegionService_instance/Region.wsdl,schema/lab5/FactoryService/Factory.
wsdl
Pozwoli to utworzy archiwum GAR przez wywołanie komendy:
./globus-build-service.sh factory
Gdy plik jest gotowy nale y jako u ytkownik globus (lub inny posiadaj cy uprawnienia) umie ci plik gar w
kontenerze globusa poleceniem
globus-deploy-gar ./org_pg_ti_lab5.gar
oraz jako ten sam u ytkownik uruchomi kontener globusa:
globus-start-container -nosec
(-nosec tylko dla celów testowych).
Program testowy
Program testowy działa w nast puj cy sposób: Tworzy 5 niezale nych zasobów, ka demu przypisuj c inny
zakres całkowania, nast pnie dla ka dego zasobu uruchamia obliczanie całki i sprawdza przy u yciu
standardowego mechanizmu pobierania informacji o własno ciach zasobów, czy zadanie ju zostało
wykonane, a je li tak, to podaje wynik.
Oto kod klienta:
package org.pg.ti.client;
import java.rmi.RemoteException;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
org.apache.axis.message.addressing.Address;
org.apache.axis.message.addressing.EndpointReferenceType;
org.apache.axis.types.URI.MalformedURIException;
org.globus.wsrf.encoding.ObjectSerializer;
org.globus.wsrf.encoding.SerializationException;
org.pg.ti.lab5.impl.RegionQNames;
org.pg.ti.lab5.stubs.FactoryService.CreateResource;
org.pg.ti.lab5.stubs.FactoryService.CreateResourceResponse;
org.pg.ti.lab5.stubs.FactoryService.FactoryPortType;
org.pg.ti.lab5.stubs.FactoryService.service.FactoryServiceAddressingLocator;
org.pg.ti.lab5.stubs.RegionService_instance.Integrate;
org.pg.ti.lab5.stubs.RegionService_instance.RegionPortType;
org.pg.ti.lab5.stubs.RegionService_instance.SetRegion;
org.pg.ti.lab5.stubs.RegionService_instance.service.RegionServiceAddressingLocator;
org.oasis.wsrf.properties.GetResourcePropertyResponse;
org.oasis.wsrf.properties.InvalidResourcePropertyQNameFaultType;
org.oasis.wsrf.properties.ResourceUnknownFaultType;
public class Client {
public static void main(String[] args) throws ServiceException, MalformedURIException,
SerializationException, RemoteException, InterruptedException {
FactoryServiceAddressingLocator factoryLocator = new FactoryServiceAddressingLocator();
RegionServiceAddressingLocator instanceLocator = new RegionServiceAddressingLocator();
String factoryURI = args[0];
EndpointReferenceType factoryEPR, instanceEPR;
FactoryPortType regionFactory;
// Get factory portType
factoryEPR = new EndpointReferenceType();
factoryEPR.setAddress(new Address(factoryURI));
regionFactory = factoryLocator.getFactoryPortTypePort(factoryEPR);
// Create resource and get endpoint reference of WS-Resource.
// This resource is our "instance".
RegionPortType[] regionService = new RegionPortType[5];
for (int i=0; i<5; i++) {
CreateResourceResponse createResponse = regionFactory
.createResource(new CreateResource());
instanceEPR = createResponse.getEndpointReference();
// Get instance PortType
regionService[i] = instanceLocator.getRegionPortTypePort(instanceEPR);
regionService[i].setRegion(new SetRegion( i*100 , (i+1) *100));
regionService[i].integrate(new Integrate());
}
Set finished = new HashSet();
while ( true ) {
for ( int i=0; i< regionService.length; i++) {
RegionPortType pt = regionService[i];
if (finished.size() == 5) System.exit(0);
if (finished.contains(new Integer(i))) continue;
String
String
String
String
state = getResourceProperty(pt, RegionQNames.RP_STATE);
x1 = getResourceProperty(pt, RegionQNames.RP_X1);
x2 =getResourceProperty(pt, RegionQNames.RP_X2);
integral =getResourceProperty(pt, RegionQNames.RP_INTEGRAL);
if (state.equals("INTEGRATED")) {
System.out.println("Integral for range ( " + x1 + ", " + x2 + ") = " + integral
);
finished.add(new Integer(i));
}
if ( state.equals("ERROR")) {
System.err.println("Error while integrating range :( " + x1 + ", " + x2 + ")") ;
finished.add((new Integer(i)));
}
System.out.println("resource[" +( i +1) + "].state=" +state);
}
Thread.sleep(1000);
}
}
static String getResourceProperty(RegionPortType pt, QName qname)
throws InvalidResourcePropertyQNameFaultType,
ResourceUnknownFaultType, RemoteException{
GetResourcePropertyResponse resourcePropertyResponse = pt.getResourceProperty(qname);
String value = resourcePropertyResponse.get_any()[0].getValue();
return value;
}
}
Szczególn uwag nale y zwróci na metod getResourceProperty wykorzystuj c standardowego dostawc
tej usługi wstrzykni tego w kod usługi sieciowej. S jeszcze 3 inne metody dost pu do usługi zasobów:
SetResourceProperties, GetMultipleResourceProperties oraz QueryResourceProperties. Szczegółów nale y
szuka w rozdziale 6 samouczka.