Mé implementace služeb mají nakonec ve výsledku obvykle čtyři anotace, jsou kompatibilní s JEE5 i JEE6 a Glassfish je vypisuje v seznamu webových služeb vystavených na instanci - k tomu navíc aplikáč (alespoň SGES 2.1.1) potřebuje sun-ejb.xml, u Glassfish 3 si nejsem jist, jestli nějaké XML vůbec je zapotřebí.
Stateless
@Stateless(name = "Hell", mappedName = "ejb/Hell")- name odpovídá ejb-name v sun-ejb.xml; slouží k propojení bean přes její název napříč komponentou. - mappedName je globální identifikátor bean přes JNDI. To je trochu kámen úrazu mezi JEE5 a JEE6, jelikož v JEE6 došlo na standradizaci JNDI názvů, ale u JEE5 to dělá každý aplikáč jinak.
SchemaValidation
@SchemaValidationTato anotace způsobí, že pokud klient pošle nevalidní SOAP dotaz, vrátí mu AS jen SoapFault s "client error". Ovšem je to dvojsečné a stejně tak pokud v implementaci služby vytvoříte odpověď, která neprojde validací, klient dostane opět SoapFault, ale se "server error" a HTTP kódem 500. To by se samozřejmě nikdy nemělo stát a je to zodpovědnost autora implementace služby.
Atributem lze také říct, že chceme použít jinou než default implementaci validace.
Poznámka pod čarou - na klienta anotace nemá vůbec žádný vliv.
HandlerChain
@HandlerChain(file="generated/HellPort_handler.xml")
jaxws-maven-plugin, resp. wsimport, umí vygenerovat i
tento soubor - dělá jeden zvlášť pro službu i port, stačí dodat
příslušné elementy do xjb souboru používaného pro custom binding. Navíc
přidá i tuto anotaci k rozhraní i klientovi, jenže má to háček - cesta k
souboru se generuje relativně k souboru třídy a proto jí musíte
zopakovat (pokud tedy nejste ve stejném balíku, což by pro změnu mohlo
dopadnout nepěkně).
Druhá možnost je všechny handlery
přidávat programově, pokud ovšem považujete určitý handler za
neoddělitelnou vlastnost služby, se kterou si navíc nechcete "plevelit"
kód implementace služby, toto je vhodný způsob.
U mých
služeb takto konfiguruji handler pro zalogování SOAP požadavku i
odpovědi; téměř téhož mohu docílit i nastavením JVM option, leč bez
možnosti logování vypínat nebo směrovat za běhu aplikace. O tom zase
jindy ;-)
WebService
@WebService( serviceName = "HellService", portName="HellPort", targetNamespace = "urn:cz:dmatej:services:Hell", endpointInterface = "cz.dmatej.ws.generated.HellPort", wsdlLocation = "META-INF/wsdl/Hell.wsdl" )Na tuhle anotaci se mrkneme podrobněji, ať už nikoho nebolí hlava :-)
name
- tenhle atribut chybí, protože v JEE5 se <port-component-name>
v sun-ejb-xml váže na název implementující třídy. Pokud atribut přeci
jen přidáte a vyplníte i shodné port-component-name, Glassfish3 s tím
nemá problém a vystaví službu pod novým názvem. Problém ale přijde se
SGES2, kde sice nasazení projde, ale do logu hlásí WARNING se
stacktrace, že atribut name se vylučuje s atributem endpointInterface.
-
otázkou pro mě je, jestli je to drobná chybička SGES, nebo požadovaná
vlastnost JEE5 (?). Buď jak buď, zřejmě je lepší věci nekomplikovat a
implementaci služby pojmenovat, jak se sluší.
serviceName
- musí odpovídat tagu <service name=... ve WSDL
- pokud neodpovídá, glassfish upozorní, že ve WSDL jsou jiné služby ale takováhle ne, a deploy selže.
portName
- musí odpovídat tagu <port name=... ve WSDL
- pokud neodpovídá, glassfish několikrát do logu zařve, že "... could not get binding from WSDL! service ...", a deploy selže.
targetNamespace
- implicitně se generuje z názvu balíku a třídy (a s http:// na začátku), ale musí odpovídat WSDL.
-
pokud wsdlLocation nenastavíte, nasazení bude nejspíš úspěšné, jenže
žádný klient se se službou neodmluví - namespaces jsou směrodatné pro
(un)marshalling SOAP zpráv.
- ve výsledku je tedy nejsnazší zkopírovat namespace z interface
endpointInterface
- jak říká javadoc, celý název implementovaného rozhraní
-
finta je v tom, že samotná třída nemusí plně implementovat všechny
metody rozhraní, k čemuž by nás Java jinak nutila. Nikdy jsem to ovšem
nezkoušel ;)
- pokud chybí, Glassfish odmítne nasazení, protože nenajde mapování operací na metody.
wsdlLocation
- cesta k WSDL, přičemž za kořen se bere adresář classes (v jar).
- pokud atribut chybí nebo soubor není nalezen, aplikáč vygeneruje svoje vlastní WSDL podle anotací.
- pozor ještě na jednu věc, WSDL musí být v podadresáři wsdl, jinak aplikáč odmítne nasazení aplikace