Webserv_Vers08_Ora

Werbung
Prof. Dr.(PL) Unterstein
257779055
1
Datenbankzugriffe als Services auf Basis von PL/SQL Prozeduren
Allgemeine Bemerkungen zu SOA als Allheilmittel für Vieles insb. für die
Datenintegration
Die folgenden Ausführungen beschreiben ***
Jdeveloper 11, Weblogic Server 10
1
Vorbereitungen
SQL Plus
Jdev
Standalone Domain für Weblogic Server eingerichtet, Admin Server für die Domain
gestartet
2
Weblogic neue Domain erstellen
Fusion Middleware Configuration Wizard -> Create New Weglogic Domain
… configured automatically mit Unterstützung für Oracle JRF
Name geändert: SIM_Domain
Benutzer weblogic, pw oracle12
1
Prof. Dr.(PL) Unterstein
257779055
2
2
Prof. Dr.(PL) Unterstein
257779055
3
3
Prof. Dr.(PL) Unterstein
257779055
4
Schritte beschrieben in http://onlineappsdba.com/index.php/2009/02/01/deploy-adfapplication-to-oracle-weblogic-server/
4
Prof. Dr.(PL) Unterstein
257779055
5
Weblogic Server Domain starten: base_domain
(Start > Programme > Oracle ... > user_projects > base_domain
3
Datenbank anlegen
Skripte für Versand08
4
Datenbankverbindung erzeugen
5
PL/SQL Package erzeugen
6
PL/SQL Package als Webservice publizieren
Kontextmenü des Package | Publish as Webservice
Schritt 2: dem Projekt (WSProj_Artikel) zuordnen
Schritt 3: Zielplattform festlegen
Datenbankverbindung und Package festlegen
Webservice Name: WS_Artikel
5
Prof. Dr.(PL) Unterstein
257779055
6
Zu publizierende Funktion auswählen
6
Prof. Dr.(PL) Unterstein
257779055
7
Keine Angaben für User Defined Type Mappings
Keine Angaben für WLS Policies
Keine Angaben für Handler Details
Was wir hier sehen ****
Login in Webserver Admin Console im Webbrowser
http://localhost:7001/console/
Anmelden mit Admin Benutzerdaten, wie bei Erzeugen der Domain angegeben:
z.B. weblogic
oracle
Webserver für Veränderung durch andere Benutzer sperren
[Lock & Edit]
Wenn diese Funktion nicht zur Verfügung steht, unter Preferences automatisches
Sperren auschecken
7
Prof. Dr.(PL) Unterstein
7
257779055
8
Datasource anlegen
[new]
Name <datenquellenname>DS (soll zwingend sein, Grund unklar)
!! Bei Fehlermeldungen während Deploy auf Namen achten, insb. auch auf Groß- /
Kleinschreibung !!
hier: versand08DS
JNDI Name (Java Naming and Directory)
hier: jdbc/versand08DS
Database Type und Driver (hier die Vorgabewerte)
8
Prof. Dr.(PL) Unterstein
257779055
9
Nächste Seite tw. Wiederholung, aber Achtung
Datenbank URL: jdbc:oracle:thin:@localhost:1521:XE
9
Prof. Dr.(PL) Unterstein
257779055
10
[Test Configuration]
[Activate Changes]
Target zuordnen
Klick auf versand08DS
Register Targets
Admin Server checken
10
Prof. Dr.(PL) Unterstein
257779055
11
[Save]
[Apply Changes]
Aus Jdeveloper Projekt auf Webserver installieren
Aus Projekt-Kontextmenü: Deploy
Wenn erfolgreich, zeigt Messagefenster in Jdev etwa folgendes:
[01:33:14 PM] ---- Deployment started. ---[01:33:14 PM] Target platform is (Weblogic 10.3).
[01:33:16 PM] Retrieving existing application information
[01:33:16 PM] Running dependency analysis...
[01:33:16 PM] Building...
[01:33:18 PM] Deploying profile...
[01:33:18 PM] Wrote Web Application Module to
F:\userdata\Oradata\Versand_WS\WSProj_Artikel\deploy\Versand_WSWSProj_Artikel-context-root.war
[01:33:18 PM] Deploying Application...
[01:33:19 PM] [Deployer:149192]Operation 'deploy' on application
'/Versand_WS-WSProj_Artikel-context-root' is in progress on 'AdminServer'
[01:33:19 PM] [Deployer:149194]Operation 'deploy' on application
'/Versand_WS-WSProj_Artikel-context-root' has succeeded on 'AdminServer'
[01:33:19 PM] Application Deployed Successfully.
[01:33:19 PM] Elapsed time for deployment: 5 seconds
[01:33:19 PM] ---- Deployment finished. ----
In der Admin console des Webservers findet man jetzt unter Deployments
Klick auf WS_Artikel
Registerkarte Testing
11
Prof. Dr.(PL) Unterstein
257779055
12
Klick auf Test Client
Eingabe einer gültigen Artikelnummer, z.B. G001
Eingabe einer ungültigen Artikelnummer zeigt unter Service Response die
Fehlermeldung.
12
Prof. Dr.(PL) Unterstein
8
257779055
13
Weitere Services für Artikel
Rückgabe eines numerischen Fehlercodes
Wir implementieren dazu eine Variante der oben eingeführten Funktion, die als
Rückgabeparameter einen Fehlercode an den aufrufenden Dienst zurückgibt, damit
dieser darüber informiert ist, ob die Operation erfolgreich war (hier, ob ein Artikel zu
der eingegebenen Nummer gefunden wurde) oder nicht. Wir setzen den Wert auf 0,
wenn kein Fehler passiert ist, auf -1, wenn keine Daten gefunden wurden und auf -99
in allen anderen Fällen.
FUNCTION get_artbez_by_nr2 (ip_artnr IN VARCHAR2, op_errorcode
OUT INTEGER)
RETURN VARCHAR2 AS
lv_artbez VARCHAR2(20);
BEGIN
op_errorcode := 0;
SELECT bezeichnung INTO lv_artbez
FROM
artikel
WHERE artikel_nr = ip_artnr;
RETURN lv_artbez;
EXCEPTION
WHEN no_data_found THEN
op_errorcode := -1;
RETURN null;
WHEN others THEN
op_errorcode := -99;
RETURN null;
END get_artbez_by_nr2;
Danach muss der Webservice neu generiert und auf dem Webserver aktualisiert
(deploy) werden, damit die Änderung wirksam wird.
Dazu erforderliche Schritte sind:
Package compilieren (Save all), was beim Speichern automatisch erfolgt.
Gegebenenfalls Fehler korrigieren.
Im Database Navigator das geänderte Package markieren. Dann aus dem
Hauptmenü VIEW | REFRESH auswählen. Leider steht diese Funktion nicht im
Kontextmenü des Package zur Verfügung. Erst danach werden die neuen
Funktionen und Prozeduren in der Hierarchiedarstellung der Datenbankverbindung
dargestellt.
Im Application Navigator das Kontextmenü des Webservice aufrufen: Properties.
Webservice Kontextmenü: Properties; unter Program Units die neue Funktion
anhaken.
13
Prof. Dr.(PL) Unterstein
257779055
14
Im Application Navigator das Kontextmenü des Webservice aufrufen: regenerate
from source
Danach sollte die WSDL Datei Angaben über die neuen Programmelemente
enthalten.
Artikelobjekt als Ganzes zurückgeben
Hierzu wird ein benutzerdefinierter Datentyp erstellt, der die Struktur der
Artikeltabelle nachbildet. Auf Basis dieses Typs erstellen wir einen Objektview, der
die in der Artikeltabelle enthaltenen Tupel als Instanzen des Objekttyps enthält.1
CREATE TYPE otyp_artikel AS OBJECT (
artikel_nr
CHAR(4) ,
mwst
SMALLINT ,
bezeichnung
VARCHAR(20),
listenpreis
DECIMAL(15,2),
bestand
INTEGER,
mindestbestand
INTEGER,
verpackung
VARCHAR(10),
lagerplatz
SMALLINT,
kann_wegfallen
SMALLINT,
bestellvorschlag
TIMESTAMP,
nachbestellung
TIMESTAMP,
nachbestellmenge
INTEGER);
/
CREATE VIEW ov_artikel OF otyp_artikel
AS SELECT * FROM artikel;
/
CREATE TYPE list_otyp_artikel AS TABLE OF otyp_artikel;
/
In das Package wird eine neue Funktion eingeführt:
1
Näheres dazu in MaUn08 S. 394
14
Prof. Dr.(PL) Unterstein
257779055
15
FUNCTION get_obj_artikel (ip_art_nr char, op_errorcode OUT
INTEGER) RETURN otyp_artikel AS
lv_obj_artikel otyp_artikel;
BEGIN
op_errorcode := 0;
SELECT value(a) INTO lv_obj_artikel
FROM
ov_artikel a
WHERE a.artikel_nr = ip_art_nr;
RETURN lv_obj_artikel;
EXCEPTION
WHEN no_data_found THEN
op_errorcode := -1;
RETURN null;
WHEN others THEN
op_errorcode := -99;
RETURN null;
END get_obj_artikel;
15
Prof. Dr.(PL) Unterstein
257779055
16
**** Diskussion: wann soll man Werte zurückgeben, wann ein komplettes Objekt?
Schreibender Zugriff
Operation soll Lagerbestand eines ausgewählten Artikels aktualisieren. Dazu
passend eine Operation, die den aktuellen Lagerbestand zurückgibt. Immer dabei ist
die Ausnahmebehandlung in Form eines numerischen OUT Parameters, der im
Fehlerfall 0 zurückgibt, sonst eine negative Zahl.
FUNCTION get_artbestand (ip_artnr IN VARCHAR2, op_errorcode OUT
INTEGER)
RETURN INTEGER
Diese Funktion wird nicht weiter ausgeführt, da sie den zuvor behandelten stark
ähnelt.
16
Prof. Dr.(PL) Unterstein
257779055
17
PROCEDURE upd_artbestand (ip_artnr IN VARCHAR2, ip_entnahme
INTEGER,
op_errorcode OUT INTEGER) AS
lv_bestand INTEGER;
lv_bestand_negativ EXCEPTION;
BEGIN
op_errorcode := 0;
-- BEGIN TRANSACTION;
SELECT bestand INTO lv_bestand
FROM
artikel
FOR UPDATE OF bestand;
IF lv_bestand < ip_entnahme THEN
RAISE lv_bestand_negativ;
-- Bei IF niemals END IF vergessen!
END IF;
UPDATE artikel
SET
bestand = bestand - ip_entnahme
WHERE artikel_nr = ip_artnr;
COMMIT;
EXCEPTION
WHEN no_data_found THEN
ROLLBACK;
op_errorcode := -1;
WHEN lv_bestand_negativ THEN
-- Bestand ist negativ
ROLLBACK;
op_errorcode := -11;
WHEN OTHERS THEN
ROLLBACK;
op_errorcode := -99;
END upd_artbestand;
Überblick über die weiteren Webserviceoperationen
Klassendiagramm. Nicht kanonisch für den Entwurf von Webservices, aber geeignet
für unsere Zwecke.
17
Prof. Dr.(PL) Unterstein
257779055
18
BESTELLPOSITION
+
+
+
+
MWST
BESTELLMENGE
LIEFERMENGE
GESAMTPREIS
:
:
:
:
DECIMAL(3,3)
int
int
DECIMAL(15,2)
+
+
+
+
get_gesamtpreis (int ip_bestnr, int ip_artnr, int op_errorcode)
set_liefermenge (int ip_bestnr, int ip_artnr, int op_liefmenge, int op_errorcode)
set_gesamtpreis (int ip_bestnr, int ip_artnr, int op_gesamtpreis, int op_errorcode)
upd_liefermenge (int ip_bestnr, int ip_artnr, int ip_gesamtpreis, int op_errorcode)
double
void
void
void
0..*
0..1
1..1
1..1
BESTELLUNG
ARTIKEL
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
+
+
+
+
+
+
+
+
+
+
+
ARTIKEL_NR
BEZEICHNUNG
LISTENPREIS
BESTAND
MINDESTBESTAND
VERPACKUNG
LAGERPLATZ
KANN_WEGFALLEN
BESTELLVORSCHLAG
NACHBESTELLUNG
NACHBESTELLMENGE
String
String
DECIMAL(15,2)
int
int
String
short
short
Date
Date
int
+
+
+
+
+
get_artbez_by_nr (int ip_artnr)
get_artbez_by_nr2 (int ip_artnr, int op_errorcode)
get_obj_artikel (int ip_artnr, int op_errorcode)
get_artbestand (int ip_artnr, int op_errorcode)
upd_artbestand (int ip_artnr, int ip_entnahme, int op_errorcode)
+
+
+
+
BESTELL_NR
BESTELLDATUM
LIEFERDATUM
RECHNUNGSBETRAG
:
:
:
:
int
Date
Date
DECIMAL(15,2)
+
+
+
+
get_rechnungsbetrag (int ip_bestnr, int op_errorcode)
: double
set_rechnungsbetrag (int ip_bestnr, int ip_rechnungsbetrag, int op_errorcode) : void
get_all_pos (int ip_bestnr, int op_errorcode, int op_anzpos)
: BESTELLPOSITION[]
get_kunde ()
: KUNDE
1..1
R_1
0..*
:
:
:
:
:
0..*
1..1
R_2
MWSTSATZ
String
String
ARTIKEL
int
void
KUNDE
+
+
+
+
+
+
+
+
+
KUNDEN_NR
STATUS
NAME
STRASSE
PLZ
ORT
LETZTE_BESTELLUNG
LETZTE_WERBEAKTION
ZAHLUNGSART
:
:
:
:
:
:
:
:
:
int
String
String
String
CHAR( 5)
String
Date
Date
String
GIROKONTO
1..1
R_5
0..*
+ KONTOINHABER : String
+ BLZ
: CHAR( 8)
+ KONTONR
: String
+ get_obj_kunde (int ip_kundnr, int op_errorcode) : KUNDE
+ MWST
: short
+ PROZENT
: DECIMAL(3,2)
+ BESCHREIBUNG : String
Für die Rückgabe eines Kundenobjekts muss ein benutzerdefinierter Typ definiert
werden2:
CREATE TYPE otyp_kunde_a AS OBJECT
( kunden_nr
INTEGER,
status
CHAR(1),
name
VARCHAR2(30),
strasse
VARCHAR2(30),
plz
CHAR( 5),
ort
VARCHAR2(25),
letzte_bestellung DATE,
letzte_werbeaktion DATE,
zahlungsart
CHAR(1)
);
Ein Viewobjekt, das die Daten der Kundentabelle als Objekte enthält, definieren wir
mit:
CREATE VIEW ov_kunde_a OF otyp_kunde_a WITH OBJECT IDENTIFIER
(kunden_nr)
AS SELECT * FROM kunde;
/
Auch für Bestellpositionen wird ein Typ benötigt.
2
In der Datenbank erstellen wir die benutzerdefinierten Typen zwecks Vermeidung von
Verwechslungen mit Tabellen- und Attributbezeichnern mit dem Präfix otyp_. Daher weicht die
Angabe des Rückgabedatentyps im Diagramm von der Implementierung als PL/SQL-Funktion
ab. Ein wenig macht sich hier das bekannte Problem des „impedence mismatch“ - das Hin und
Her zwischen relationalen und objektorientierten Strukturen – unschön bemerkbar.
18
Prof. Dr.(PL) Unterstein
257779055
19
CREATE TYPE otyp_bestellposition AS OBJECT
( bestell_nr
INTEGER,
artikel_nr
CHAR(4),
mwst
DECIMAL(3,3),
bestellmenge
INTEGER,
liefermenge
INTEGER,
gesamtpreis
DECIMAL(15,2)
)
CREATE VIEW ov_bestellposition OF otyp_bestellposition WITH
OBJECT OID (bestell_nr, artikel_nr)
AS SELECT * FROM bestellposition;
/
show errors
CREATE OR REPLACE TYPE LIST_OTYP_BESTPOS AS TABLE OF
otyp_bestellposition;
19
Prof. Dr.(PL) Unterstein
257779055
20
Alle Positionen einer bestimmten Bestellung als Webservice zurückgeben
Dieser Service wird benötigt, um folgende Transaktion zu konstruieren: Zu allen
Positionen einer Bestellung soll der Lagerbestand des Artikels um die Liefermenge
reduziert werden. Um dies zu erreichen, müssen alle zutreffenden Positionen als
Kollektion zurückgegeben werden. Als Kollektionstypen bietet PL/SQL an: TABLE
und VARRAYs. Beide können als Rückgabewert von stored functions verwendet
werden.
Um mit einer Tabelle als Rückgabe zu arbeiten, wird sie zunächst als Typ deklariert:
CREATE OR REPLACE TYPE ttyp_bestpos_obj AS TABLE OF
otyp_bestellposition_a;
So ist die folgende Funktion gültig, führt aber zu einem Laufzeitfehler als Webservice
.
FUNCTION get_all_obj_pos (ip_bestnr INTEGER,
op_errorcode OUT INTEGER)
RETURN ttyp_bestpos_obj AS
lv_tab_bestpos ttyp_bestpos_obj := ttyp_bestpos_obj();
CURSOR c_bestpos IS
SELECT VALUE(p)
FROM
ov_bestellposition_a p
WHERE p.bestell_nr = ip_bestnr
ORDER BY p.bestell_nr, p.artikel_nr;
BEGIN
op_errorcode := 0;
OPEN c_bestpos;
FETCH c_bestpos BULK COLLECT INTO lv_tab_bestpos;
CLOSE c_bestpos;
RETURN lv_tab_bestpos;
EXCEPTION
WHEN OTHERS THEN
op_errorcode := SQLCODE;
END get_all_obj_pos;
Die Verwendung eines VARRAY als Kollektionstyp funktioniert hingegen:
CREATE OR REPLACE TYPE varr_bestpos AS VARRAY (10) OF
otyp_bestellposition_a;
Eine schöne Lösung ist das nicht, wegen der notwendigen Dimensionierung des
VARRAY, die die zu erwartende maximale Anzahl von Bestellpositionen reflektieren
muss.
Die folgende Funktion mit Rückgabetyp VARRAY wird als Serviceoperation
problemlos ausgeführt und gibt ein XML-Dokument zurück.
20
Prof. Dr.(PL) Unterstein
257779055
21
FUNCTION get_all_obj_pos_as_varr (ip_bestnr INTEGER,
op_errorcode OUT INTEGER)
RETURN varr_bestpos AS
lv_v_bp varr_bestpos;
lv_obj_bestpos otyp_bestellposition_a;
CURSOR c_bestpos IS
SELECT VALUE(p)
FROM
ov_bestellposition_a p
WHERE p.bestell_nr = ip_bestnr
ORDER BY p.bestell_nr, p.artikel_nr;
BEGIN
op_errorcode := 0;
OPEN c_bestpos;
FETCH c_bestpos BULK COLLECT INTO lv_v_bp;
CLOSE c_bestpos;
RETURN lv_v_bp;
EXCEPTION
WHEN OTHERS THEN
op_errorcode := SQLCODE;
END get_all_obj_pos_as_varr;
Ergebnis auszugsweise:
<env:Body>
<m:getAllObjPosAsVarrResponse
xmlns:m="http://versand08/WS_BESTPOS3.wsdl">
<result>
<m:OtypBestellpositionAUser>
<m:liefermenge>4</m:liefermenge>
<m:mwst>0.19</m:mwst>
<m:artikelNr>G002</m:artikelNr>
<m:bestellNr>151</m:bestellNr>
<m:gesamtpreis>49.8</m:gesamtpreis>
<m:bestellmenge>4</m:bestellmenge>
</m:OtypBestellpositionAUser>
<m:OtypBestellpositionAUser>
<m:liefermenge>3</m:liefermenge>
<m:mwst>0.19</m:mwst>
<m:artikelNr>G003</m:artikelNr>
<m:bestellNr>151</m:bestellNr>
<m:gesamtpreis>15.6</m:gesamtpreis>
<m:bestellmenge>3</m:bestellmenge>
</m:OtypBestellpositionAUser>
...
Transaktion Verminderung des Lagerbestands um die jeweilige Liefermenge
des Artikels, bezogen auf eine Bestellung
Die Webserviceoperation, die dies erledigt, benutzt den soeben beschriebenen sowie
die folgende Operation aus dem Artikel-bezogenen Webservice:
PROCEDURE upd_artbestand (ip_artnr IN VARCHAR2, ip_entnahme
INTEGER, op_errorcode OUT INTEGER);
21
Prof. Dr.(PL) Unterstein
257779055
22
Zu lösen sind zwei Probleme: (1) Erstellen eines WS, der andere WS aufruft, (2)
Iteration über ein XML-Dokument, das eine Liste von Bestellpositionen enthält und
Extrahieren jeweils eines Werts von Liefermenge, der dann in der UPDATEAnweisung bzw. in der Operation upd_artbestand als Parameter eingesetzt werden
muss.
Aufruf eines Webservice in einer Anwendung
How to Call an External Service Programmatically
To call a web service from an application module, you create a web service proxy
class for the service you want to invoke. A web service proxy is a generated Java
class that represents the web service inside your application. It encapsulates the
service URL of the web service and handles the lower-level details of making the call.
To work with a web service, you need to know the URL that identifies its WSDL
document. If you have received the WSDL document as an email attachment, for
example, and saved it to your local hard drive, the URL could be similar to:
file:///D:/temp/SomeService.wsdl
Alternatively, the URL could be an HTTP-based URL like:
http://someserver.somecompany.com/SomeService/SomeService.wsdl
Some web services make their WSDL document available by using a special
parameter to modify the service URL. For example, a web service that expects to
receive requests at the HTTP address of
http://someserver.somecompany.com/SomeService
might publish the corresponding WSDL document using the same URL with an
additional parameter on the end, like this:
http://someserver.somecompany.com/SomeService?WSDL
[Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development
Framework 11g Release 1 (11.1.1) B31974-03 May 2009 page 531]
Hier:
http://192.168.123.157:7001/Versand_WS-WSProj_BestPos3-contextroot/WS_BESTPOS3Port?WSDL
To call a web service from an application module using a proxy class, you perform
the following tasks:
1. Create a web service proxy class for the web service. To create a web service
proxy class for a web service you need to call, use the Create Web Service Proxy
wizard.
2. Implement the methods in the proxy class to access the desired web services.
3. Create an instance of the web service proxy class in your application module and
invoke one or more methods on the web service proxy object. [ebenda]
Neue Applikation angelegt (generic) Neues Projekt (Java, XML, Webservice)
[Oracle Cue Cards: Cue Card Work with Web Services]
Create a Web Service Proxy
22
Prof. Dr.(PL) Unterstein
257779055
23
Open the Create Generic Project wizard to create a new generic project.
Enter RatingProxy as the project name and click Finish. In the
Application Navigator, select the project you just created and launch
the Create Web Service Proxy wizard. On the Welcome page of the
wizard, click Next.
On step 2, Select Client Style, select JAX-WS Style. Click Next. On step 3,
Select Web Service Description, in the WSDL Document URL field,
enter the WSDL URL that you noted from the analyzer window in the
previous cue card. Then click Next.
On step 4, Specify Default Mapping Options, enter ratingproxy.proxy as
the package name and ratingproxy.proxy.types as the root package
name. Click Next. On step 5, Port Endpoints, select Run against a
service deployed to Integrated WLS. (* hier nicht, da der integrierte
Weblogic Server nicht benutzt wird *) Click Finish to end the wizard.
Click Save All to save your work.
[rcl] Projekt. Hier
Typ JAX WS Style
Die WSDL_Url aus dem Weblogic Server ermitteln.
Copy WSDL Into Project anhaken,
23
Prof. Dr.(PL) Unterstein
257779055
24
[next]
Step 5 abweichend von cue card
Weitere Festlegungen werden nach cue card nicht getroffen: [finish]
Next step: Create a Java Client to Invoke the Web Service Proxy
If it is not already open, double-click
CreditRatingSoap12HttpPortClient.java in the Application Navigator to
open it in the Java source editor. In the editor, add code in the main
method to call the desired method.
Use sample code Click Save All to save your work. In the Application
Navigator, right-click the CreditRatingSoap12HttpPortClient.java node
and choose Run. [Cue Card Work with Web Services]
24
Prof. Dr.(PL) Unterstein
257779055
25
Proxy-Client zum Test des Webservice benutzen
package artikelproxy.proxy;
import javax.xml.ws.WebServiceRef;
// !THE CHANGES MADE TO THIS FILE WILL BE DESTROYED IF
REGENERATED!
// This source file is generated by Oracle tools
// Contents may be subject to change
// For reporting problems, use the following
// Version = Oracle WebServices (11.1.1.0.0, build
090601.1016.39267)
public class WS_ArtikelPortClient
{
@WebServiceRef
private static WS_Artikel_Service wS_Artikel_Service;
public static void main(String [] args)
{
wS_Artikel_Service = new WS_Artikel_Service();
WS_Artikel wS_Artikel =
wS_Artikel_Service.getWS_ArtikelPort();
// Add your code to call the desired methods.
// here is my own code ******
System.out.println(wS_Artikel.getArtbezByNr("G001"));
// end of own code ******
}
}
Zwischenfazit
Die Java-Anwendung zum Aufruf des Webservices wurde erstellt aufgrund der
WSDL-Beschreibung und residiert in einer eigenen Applikation, die keinen direkten
Zugriff auf die Quellen des Webservices beinhaltet.
Proxy für eine Clientanwendung mit parametrisierten Methoden
25
Prof. Dr.(PL) Unterstein
257779055
26
package kundeproxy.proxy;
import javax.xml.ws.WebServiceRef;
import javax.xml.ws.Holder;
public class WS_KundePortClient
{
@WebServiceRef
private static WS_Kunde_Service wS_Kunde_Service;
public static void main(String [] args)
{
Holder<Integer> h1 = new Holder<Integer>(0);
Holder<Integer> h2 = new Holder<Integer>(0);
wS_Kunde_Service = new WS_Kunde_Service();
WS_Kunde wS_Kunde = wS_Kunde_Service.getWS_KundePort();
// Add your code to call the desired methods.
System.out.println(wS_Kunde.getObjKunde(101,h2).getName());
}
}
Die Originalmethode getObjKunde erwartet einen Integerwert für die Kunden_nr und
eine Integervariable für den Errorcode. Funktionieren tut es aber nicht mit einfachen
Integers, nicht jedenfalls für den Rückgabewert. Hier muss eine Holder – Instanz
erstellt werden, wobei es nicht egal ist, aus welchem Package der Holder kommt.
Schnellste Hilfe wäre die Betrachtung des Quelltextes von WS_Kunde.java
(generiert). Hier findet man die Importanweisung:
import javax.xml.ws.Holder;
Diese muss auch in der Clientanwendung (s.o.) verwendet werden, da andere Holder
Implementierungen aus anderen Klassenbibliotheken nicht funktionieren. Dumm,
dass das Ganze nicht dokumentiert ist!
Webservice-Proxy für Bestellpositionen
Von Testanwendung aus Proxy erstellen.
26
Prof. Dr.(PL) Unterstein
257779055
27
public class WS_BESTPOS3PortClient
{
@WebServiceRef
private static WS_BESTPOS3_Service wS_BESTPOS3_Service;
public static void main(String [] args)
{
Holder<Integer> h = new Holder<Integer>(0);
wS_BESTPOS3_Service = new WS_BESTPOS3_Service();
WS_BESTPOS3 wS_BESTPOS3 =
wS_BESTPOS3_Service.getWS_BESTPOS3Port();
// Add your code to call the desired methods.
System.out.println(wS_BESTPOS3.getGesamtpreis(151,"G002",h));
}
}
Aufgabe: alle Positionen einer Bestellung sollen mit Angabe der Artikelbezeichnung
ausgegeben werden. Benutzt wird dazu die Operation getAllObjPosAsVarr des
Webservice WS_BESTPOS3 und die Operation getArtbezByNr2 des Webservice
WS_Artikel.
@WebMethod(action="http://versand08/WS_BESTPOS3.wsdl/getAllObjPosAsVarr")
@Action(input="http://versand08/WS_BESTPOS3.wsdl/getAllObjPosAsVarr",
output="http://versand08/WS_BESTPOS3.wsdl/WS_BESTPOS3/getAllObjPosAsVarrRes
ponse")
@WebResult(partName="result", name="result")
public artikelproxy.proxy.types.OtypBestellpositionAUserArray
getAllObjPosAsVarr(@WebParam(partName="ipBestnr",
name="ipBestnr")
int ipBestnr, @WebParam(partName="opErrorcode_out",
name="opErrorcode_out",
mode=Mode.INOUT)
Holder<Integer> opErrorcode_out);
@WebMethod(action="http://versand08/WS_Artikel.wsdl/getArtbezByNr2")
@Action(input="http://versand08/WS_Artikel.wsdl/getArtbezByNr2",
output="http://versand08/WS_Artikel.wsdl/WS_Artikel/getArtbezByNr2Response"
)
@WebResult(partName="result", name="result")
public String getArtbezByNr2(@WebParam(partName="ipArtnr",
name="ipArtnr")
String ipArtnr, @WebParam(partName="opErrorcode_out",
name="opErrorcode_out",
mode=Mode.INOUT)
Holder<Integer> opErrorcode_out);
27
Prof. Dr.(PL) Unterstein
257779055
28
Zur Vorbereitung wird einmal versucht, die Ausgabe der Methode
getAllObjPosAsVarr, ein XML-Dokument, zu drucken.
Hinzufügen der Zeile:
System.out.println(wS_BESTPOS3.getAllObjPosAsVarr(151,h));
Ergebnis ist Hinweis, dass das Resultat ein Typ ist:
artikelproxy.proxy.types.OtypBestellpositionAUserArray@9db992
Aber kein Laufzeitfehler.
public class OtypBestellpositionAUserArray {
@XmlElement(name = "OtypBestellpositionAUser", nillable = true)
protected List<OtypBestellpositionAUser> otypBestellpositionAUser;
Aufgabe: das erste Listenelement ausgeben. Danach durch die Liste iterieren.
komplette Lösung:
28
Prof. Dr.(PL) Unterstein
257779055
29
package artikelproxy.proxy;
import artikelproxy.proxy.types.OtypBestellpositionAUser;
import artikelproxy.proxy.types.OtypBestellpositionAUserArray;
//import artikelproxy.proxy.WS_ArtikelPortClient;
//import artikelproxy.proxy.WS_Artikel_Service;
//import artikelproxy.proxy.types.OtypArtikelUser;
//import java.util.ArrayList;
//import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.xml.ws.WebServiceRef;
import javax.xml.ws.Holder;
// !THE CHANGES MADE TO THIS FILE WILL BE DESTROYED IF
REGENERATED!
// This source file is generated by Oracle tools
// Contents may be subject to change
// For reporting problems, use the following
// Version = Oracle WebServices (11.1.1.0.0, build
090601.1016.39267)
public class WS_BESTPOS3PortClient
{
@WebServiceRef
private static WS_BESTPOS3_Service wS_BESTPOS3_Service;
@WebServiceRef
private static WS_Artikel_Service wS_Artikel_Service;
public static void main(String [] args)
{
String lv_artnr;
String lv_artbez;
Holder<Integer> h = new Holder<Integer>(0);
// Webservices Instanzen erzeugen
wS_BESTPOS3_Service = new WS_BESTPOS3_Service();
WS_BESTPOS3 wS_BESTPOS3 =
wS_BESTPOS3_Service.getWS_BESTPOS3Port();
wS_Artikel_Service = new WS_Artikel_Service();
WS_Artikel wS_Artikel =
wS_Artikel_Service.getWS_ArtikelPort();
29
Prof. Dr.(PL) Unterstein
257779055
30
// hier die einzelnen Positionen abarbeiten und zu jeder
die
// Artikelbezeichnung per Benutzung der entsprechenden
// Serviceoperation anzeigen
OtypBestellpositionAUserArray poslist;
// Alle Positionen einer ausgewählten Bestellung als Array
poslist = wS_BESTPOS3.getAllObjPosAsVarr(151,h);
//
// Unklar, wieso aus dem Array erst eine Liste gemacht
werden muss
//
List<OtypBestellpositionAUser> poslist2 =
poslist.getOtypBestellpositionAUser();
// poslist2 enthaelt die Positionen
// Jetzt Iterator erzeugen und die einzelnen Positionen
// in einer Schleife durcharbeiten
System.out.println("Anzahl Positionen: "+ poslist2.size());
ListIterator itpos2 = poslist2.listIterator();
while (itpos2.hasNext()) {
OtypBestellpositionAUser act_pos =
(OtypBestellpositionAUser)itpos2.next();
lv_artnr = act_pos.getArtikelNr();
System.out.print(act_pos.getBestellNr()+" ");
System.out.print(lv_artnr+ " ");
lv_artbez = wS_Artikel.getArtbezByNr(lv_artnr);
System.out.println(lv_artbez);
}
}
}
Benutzung mehrerer Operationen verschiedener Webservices in einer ClientAnwendung
Dies im Rahmen der Testanwendung TestWS
Proxies für Artikel-, Kunde-, Bestellung-, Bestellposition-Webservices
****
Interessant wäre die kompletten Darstellung der Klassen, die für das Resultat
zusammen arbeiten.
Zugriff auf andere Datenbanken über Webservices
Bsp. MySQL / Access / HSQLDB (Open Office Datenbank)
30
Herunterladen