Java Web Services Cookbook

Transcrição

Java Web Services Cookbook
Departamento de Engenharia Informática
Sistemas Distribuídos
Java Web Services Cookbook
12 de Maio de 2009
Java Web Services Cookbook
Índice
Nota prévia ................................................................................................................ 3
Criar um Web Service ............................................................................................... 4
Estratégia............................................................................................................... 4
Passos básicos ....................................................................................................... 4
Variantes ............................................................................................................... 8
Diagnóstico de erros ...................................................................................... 8
Usar Eclipse ................................................................................................... 8
Activar um JAX-WS Handler no servidor .....................................................10
Registar o Web Service no UDDI .................................................................10
Criar um servidor com dois endpoints ...........................................................12
Criar um cliente de Web Service ..............................................................................15
Estratégia..............................................................................................................15
Passos básicos ......................................................................................................15
Variantes ..............................................................................................................17
Diagnóstico de erros .....................................................................................17
Usar Eclipse ..................................................................................................17
Activar um JAX-WS Handler no cliente .......................................................18
Obter a localização do Web Service a partir do UDDI ...................................19
Criar um cliente de dois Web Services ..........................................................21
2
Java Web Services Cookbook
Nota prévia
Este livro de "receitas" descreve procedimentos para o desenvolvimento de Web
Services. Não explica nem pretende explicar todos os conceitos envolvidos, que
deverão ser estudados e compreendidos em pormenor antes da utilização deste guia.
A infra-estrutura de software que se assume é: Java 5, JWSDP 2.0+, Ant 1.7.0+ e
ImportAnt 5.5.1+. São também apresentadas variantes que usam o Eclipse Java
Enterprise Europa+.
A estrutura base de directorias dos projectos (ImportAnt) é a seguinte:
project
build.xml
Project Ant build file:
- import modules
- define properties
- define classpaths
- define build targets
build.properties
Property overrides
config
configuration files
lib
src
library (jar) files
source code
java
Java classes
web
Web resources
(JSP, HTML, ...)
xml
WSDL, XSD and
other XML sources
etc
additional files
build
temporary build
directory
dist
temporary
application or
library distribution
directory
3
Java Web Services Cookbook
Criar um Web Service
Estratégia
Um Web Service é uma aplicação servidora que responde a pedidos de clientes
formatados em XML e transportados em mensagens SOAP.
O procedimento consiste em criar uma estrutura de directórios e ficheiros para o
projecto, definir o Web Service através de WSDL e XSD, gerar código Java para
tratamento da comunicação e da conversão de dados e, finalmente, escrever o restante
código.
Aqui o Web Service é genericamente designado como MyWS. Este e outros nomes
relacionados deverão ser ajustados caso a caso, de acordo com o pretendido.
Passos básicos
1. Criar projecto Ant
a. Criar estrutura de directorias e ficheiros para o projecto.
import-ant
my-ws
config
resources
jax-ws-server
web.xml
sun-jaxws.xml
server-custom-binding.xml
src
java
xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<display-name>JAX-WS @ant.project.name@</display-name>
<description>JAX-WS application: @ant.project.name@</description>
<listener>
<listenerclass>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listenerclass>
</listener>
<servlet>
<servlet-name>jax-ws-servlet</servlet-name>
<display-name>JAX-WS servlet</display-name>
<description>JAX-WS endpoint</description>
<servletclass>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jax-ws-servlet</servlet-name>
<url-pattern>/endpoint</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
4
Java Web Services Cookbook
</session-config>
</web-app>
sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint name="endpoint"
interface="@jax-ws-server.ties.interface.name@"
implementation="@jax-ws-server.impl.class.name@"
wsdl="WEB-INF/wsdl/@jax-ws-server.wsdl.file-name@"
service="{@jax-ws-server.wsdl.namespace@}@jax-wsserver.wsdl.service-name@"
port="{@jax-ws-server.wsdl.namespace@}@jax-wsserver.wsdl.port-name@"
url-pattern="/endpoint" />
</endpoints>
server-custom-binding.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="@jax-ws-server.wsdl.file-name@"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
@jax-ws-server.handler-chains@
</bindings>
</bindings>
Todos estes ficheiros contêm itens de substituição (@...@) que serão
substituídos pelo ImportAnt durante o processo de construção. Deste
modo, estes ficheiros permanecem sempre iguais e o que muda é o
build.xml.
b. Criar ficheiro de construção build.xml:
<project name="MyWS" default="build" basedir=".">
<property name="import-ant" value="../import-ant" />
<!-- IMPORTS -->
<import file="${import-ant}/core.xml" />
<import file="${import-ant}/tomcat.xml" />
<import file="${import-ant}/jwsdp.xml" />
<import file="${import-ant}/jax-ws-server.xml" />
<!-- Web Service definitions -->
<property name="jax-ws-server.wsdl.file-name" value="" />
<property name="jax-ws-server.wsdl.namespace" value="" />
<property name="jax-ws-server.wsdl.service-name" value="" />
<property name="jax-ws-server.wsdl.port-name" value="" />
<property name="jax-ws-server.ties.package" value="" />
<property name="jax-ws-server.ties.interface.simple-name" value="" />
<property name="jax-ws-server.impl.package" value="" />
<property name="jax-ws-server.impl.class.simple-name" value="" />
<!-- CLASSPATHS -->
<path id="compile.classpath">
<pathelement location="${build.classes.rel-dir}" />
<path refid="project.lib.path" />
<path refid="jwsdp.jars.path" />
</path>
5
Java Web Services Cookbook
<!-- TARGETS -->
<target name="build"
depends="config,build-jax-ws-server"
description="Builds the project">
</target>
</project>
c. Criar directorias temporárias build e dist e confirmar que sintaxe do
build.xml está correcta:
$ ant init
2. Definir contrato do serviço
a. Criar ficheiro MyWS.wsdl em src/xml que especifica as operações do
Web Service com o vocabulário WSDL. Os tipos de dados são definidos
com o vocabulário XSD.
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MyWS"
targetNamespace="http://myWS"
xmlns:tns="http://my-ws"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema elementFormDefault="qualified"
targetNamespace="http://my-ws">
<xsd:complexType name="MyOperationType">
<xsd:sequence>
<xsd:element name="i" type="xsd:int" />
<xsd:element name="z" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="myOperation" type="tns:MyOperationType" />
<xsd:complexType name="MyOperationResponseType">
<xsd:sequence>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="myOperationResponse" type="tns:MyOperationResponseType"
/>
<message name="myOperation">
<part name="parameters" element="tns:myOperation" />
</message>
<message name="myOperationResponse">
<part name="result" element="tns:myOperationResponse" />
</message>
<portType name="MyPortType">
<operation name="myOperation">
<input message="tns:myOperation" name="myOperation"/>
<output message="tns:myOperationResponse" name="myOperationResponse"/>
</operation>
</portType>
<binding name="MyBinding" type="tns:MyPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="myOperation">
<soap:operation soapAction="" />
<input>
6
Java Web Services Cookbook
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</operation>
</binding>
<service name="MyService">
<port name="MyPort" binding="tns:MyBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL" />
</port>
</service>
</definitions>
b. Definir nomes seguindo a convenção dos sufixos: ...Service, ...Port,
...PortType, ...Binding, ...
3. Criar serviço
a. Gerar ties
i. Definir valores de propriedades de Web Service no build.xml
de acordo com os valores definidos no WSDL
<!-- Web Service definitions -->
<property name="jax-ws-server.wsdl.file-name" value="MyWS.wsdl" />
<property name="jax-ws-server.wsdl.namespace" value="http://my-ws"
/>
<property name="jax-ws-server.wsdl.service-name" value="MyService"
/>
<property name="jax-ws-server.wsdl.port-name" value="MyPort" />
<property name="jax-ws-server.ties.package" value="my.ws.ties" />
<property name="jax-ws-server.ties.interface.simple-name"
value="MyPortType" />
<property name="jax-ws-server.impl.package" value="my.ws" />
<property name="jax-ws-server.impl.class.simple-name"
value="MyServiceImpl" />
ii. Executar wsimport
$ ant build-jax-ws-server
iii. Consultar ties gerados pelo wsimport em build/jax-wsserver/wsimport,
em
particular
MyService.java
e
MyPortType.java
7
Java Web Services Cookbook
b. Criar implementação do serviço
i. Criar classe em src/java/my/ws, implementando todos os
métodos definidos em MyPortType
package my.ws;
import my.ws.ties.*;
@javax.jws.WebService (endpointInterface="my.ws.ties.MyPortType")
public class MyServiceImpl implements MyPortType {
public void myOperation(int i, String s) {
return;
}
}
c. Construir Web Service e instalar
$ catalina start
$ ant deploy
d. Confirmar instalação correcta
http://localhost:8080/MyWS/endpoint
http://localhost:8080/MyWS/endpoint?wsdl
Variantes
Diagnóstico de erros
Consultar ficheiro de log: %CATALINA_HOME%\logs\launcher.server.log
$ ant rebuild
$ ant quick-redeploy
O ficheiro de log pode ser consultado continuamente com o comando tail:
$ tail -f
%CATALINA_HOME%\logs\launcher.server.log
Usar Eclipse
(Antes do passo 2)
Iniciar o Eclipse e criar novo projecto
File, New, Project, Java Project, Project name: MyWS
Create project from existing source, Next
Source, Source folder, src/java, Default output folder: build/eclipse
Libraries, Add library, User library: jwsdp-essd-2008, Finish
Add class folder: build/classes, Finish
O conjunto de bibliotecas (user library) jwsdp-essd-2008 pode ser importado a
partir do ficheiro contido na directoria %JWSDP_HOME%\eclipse.
8
Java Web Services Cookbook
Configurar Ant
Windows, Show View, Ant View
build.xml ~drag-and-drop~> Ant View
Hide internal targets
(Apoio ao passo 2, a)
Criar WSDL
New, Other..., XML, WSDL
Next
Parent folder: src/xml
File name: MyWS.wsdl, Next
Target namespace: http://my-ws
Namespace prefix: tns
Create WSDL Skeleton
Protocol: SOAP
SOAP Binding options: document literal
Finish
Indentar XML
WSDL, View Source
Select All Text
Source, Format, Document
(Depois do passo 3, a, ii)
Refrescar Eclipse
Project, Refresh
(Apoio ao passo 3, b, i)
Criar classe
File, New, Class
package: my.ws
name: MyServiceImpl
superclass: java.lang.Object
interfaces: my.ws.ties.MyPortType
inherit abstract methods
generate comments
Anotar classe
@javax.jws.WebService (endpointInterface="my.ws.ties.MyPortType")
Escrever código Java dos métodos.
9
Java Web Services Cookbook
Activar um JAX-WS Handler no servidor
Acrescentar o seguinte target ao build.xml.
<target name="-replace-jax-ws-server-custom-tokens(dir)">
<replace dir="${dir}" token="@jax-ws-server.handler-chains@">
<replacevalue><![CDATA[
<jws:handler-chains
xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handlerclass>my.ws.handler.MyHandler</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
]]></replacevalue>
</replace>
</target>
A classe my.ws.handler.MyHandler deverá existir e ser um JAX-WS Handler.
Registar o Web Service no UDDI
Obter uma biblioteca com as classes step.framework.ws.registry.* e colocar
numa das directorias lib do projecto:
lib
my-ws
lib
Criar e preencher ficheiros de configuração de registo Registry.properties
(dados do servidor UDDI) e Registration.properties (dados de registo).
my-ws
config
ws-registry
Registry.properties
Registration.properties
Registry.properties
#
# Registry
#
[email protected]@
[email protected]@
[email protected]@
#locale=
optionOutputMessages=true
#optionValidateURI=false
#optionWarnAboutLocale=true
Registration.properties
#
# Registration
#
organizationName=My Organization
serviceName=My Service
serviceBindingAccessURI=http://myserver:8080/MyWS/endpoint
classificationScheme=unspsc-org:unspsc:3-1
10
Java Web Services Cookbook
classificationName=Research and Science Based Services
classificationValue=81000000
Criar ou editar ficheiro build.properties para acrescentar:
ws-registry.username=testuser
ws-registry.password=testuser
Modificar build.xml, acrescentando a importação de um novo módulo:
<import file="${import-ant}/ws-registry.xml" />
As propriedades relacionadas com o registo UDDI:
<property name="ws-registry.url"
value="http://localhost:8080/RegistryServer/" />
<property name="ws-registry.main-class"
value="step.framework.ws.registry.Main" />
<property name="dir" value="${build.config.ws-registry.rel-dir}" />
<property name="ws-registry.publish.args" value="${dir}/Registry.properties
publish ${dir}/Registration.properties ${dir}/RegistrationKey.properties" />
<property name="ws-registry.delete.args" value="${dir}/Registry.properties
delete key ${dir}/RegistrationKey.properties" />
<property name="ws-registry.query.args" value="${dir}/Registry.properties
query classification ${dir}/Registration.properties" />
Uma nova dependência no build.xml:
<target name="build"
depends="config,build-ws-registry,build-jax-ws-server"
description="Builds the project">
</target>
Efectuar o registo:
$ ant build-ws-registry ws-publish
Consultar o registo:
$ ant build-ws-registry ws-query
Apagar o registo:
$ ant build-ws-registry ws-delete
11
Java Web Services Cookbook
Criar um servidor com dois endpoints
É possível que o mesmo servidor disponibilize dois endpoints, neste caso,
Hello e Calc. No entanto, os itens de substituição (@...@) do ImportAnt já não
funcionam correctamente e é necessário efectuar a configuração directamente
nos ficheiros.
Criar dois ficheiros de custom bindings:
my-ws
config
resources
jax-ws-server
web.xml
sun-jaxws.xml
server-custom-binding_hello.xml
server-custom-binding_calc.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<display-name>JAX-WS Application</display-name>
<description>JAX-WS Application</description>
<listener>
<listenerclass>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listenerclass>
</listener>
<servlet>
<servlet-name>JAX-WS Servlet</servlet-name>
<display-name>JAX-WS Servlet</display-name>
<description>JAX-WS endpoint</description>
<servletclass>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-WS Servlet</servlet-name>
<url-pattern>/endpoint_hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JAX-WS Servlet</servlet-name>
<url-pattern>/endpoint_calc</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint name="endpoint_hello"
interface="hello.ties.HelloPortType"
implementation="hello.HelloServiceImpl"
wsdl="WEB-INF/wsdl/Hello.wsdl"
service="{http://hello}HelloService"
port="{http://hello}HelloPort"
url-pattern="/endpoint_hello" />
<endpoint name="endpoint_calc"
interface="calc.ties.CalcPortType"
implementation="calc.CalcServiceImpl"
12
Java Web Services Cookbook
wsdl="WEB-INF/wsdl/Calc.wsdl"
service="{http://calc}CalcService"
port="{http://calc}CalcPort"
url-pattern="/endpoint_calc" />
</endpoints>
server-custom-binding_hello.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="Hello.wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handler-class>util.HelloLoggingHandler</jws:handlerclass>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
</bindings>
</bindings>
server-custom-binding_calc.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="Calc.wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handler-class>util.CalcLoggingHandler</jws:handlerclass>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
</bindings>
</bindings>
13
Java Web Services Cookbook
O build.xml deverá ter agora os seguintes targets:
<target name="build"
depends="config,build-jax-ws-server-ties_hello,build-jax-wsserver-ties_calc,compile,create-jax-ws-server-war"
description="Builds the project">
</target>
<target name="build-jax-ws-server-ties_hello">
<echo level="info" message="Creating Hello ties..." />
<antcall target="build-jax-ws-server-ties" inheritAll="false">
<param name="jax-ws-server.wsdl.file-name" value="Hello.wsdl" />
<param name="jax-ws-server.wsimport.bindings.file-pattern"
value="*binding*hello.xml" />
<param name="jax-ws-server.ties.package" value="hello.ties" />
</antcall>
</target>
<target name="build-jax-ws-server-ties_calc">
<echo level="info" message="Creating Calc ties..." />
<antcall target="build-jax-ws-server-ties" inheritAll="false">
<param name="jax-ws-server.wsdl.file-name" value="Calc.wsdl" />
<param name="jax-ws-server.wsimport.bindings.file-pattern"
value="*binding*calc.xml" />
<param name="jax-ws-server.ties.package" value="calc.ties" />
</antcall>
</target>
As propriedades relativas a Web Services (jax-ws-server.wsdl.file-name, jaxws-server.wsdl.namespace, etc.) devem desaparecer, porque as definições são
agora feitas directamente nos ficheiros de configuração e não através do
mecanismo de substituição (@...@).
14
Java Web Services Cookbook
Criar um cliente de Web Service
Estratégia
Um cliente de Web Service é uma aplicação que invoca um Web Service. Nesta
receita cria-se um cliente que se executa a partir da linha de comando, no entanto, o
procedimento é idêntico para aplicações Web ou de outro tipo.
O procedimento consiste em criar uma estrutura de directórios e ficheiros para o
projecto, gerar código Java de invocação e de conversão de dados e, finalmente,
escrever o restante código.
Aqui o cliente de Web Service é genericamente designado como MyWSCli. Este e
outros nomes relacionados deverão ser ajustados caso a caso, de acordo com o
pretendido.
Passos básicos
1. Criar projecto Ant
a. Criar estrutura de directorias e ficheiros para o projecto.
import-ant
my-ws
config
resources
jax-ws-client
client-custom-binding.xml
src
java
client-custom-binding.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="@jax-ws-client.wsdl.url@"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
@jax-ws-client.handler-chains@
</bindings>
</bindings>
Este ficheiro contêm itens de substituição (@...@) que serão substituídos
pelo ImportAnt durante o processo de construção. Deste modo, o ficheiro
permanece sempre igual e o que muda é o build.xml.
b. Criar ficheiro de construção build.xml:
<project name="MyWSCli" default="build" basedir=".">
<property name="import-ant" value="../import-ant" />
<!-- IMPORTS -->
15
Java Web Services Cookbook
<import
<import
<import
<import
file="${import-ant}/core.xml" />
file="${import-ant}/console-app.xml" />
file="${import-ant}/jwsdp.xml" />
file="${import-ant}/jax-ws-client.xml" />
<!-- Console application -->
<property name="run.main-class" value="my.MyClient" />
<property name="run.args" value="http://localhost:8080/MyWS/endpoint"
/>
<!-- Web Service client -->
<property name="jax-ws-client.wsdl.url"
value="http://localhost:8080/MyWS/endpoint?wsdl" />
<property name="jax-ws-client.stubs.package" value="my.ws.stubs" />
<!-- CLASSPATHS -->
<path id="compile.classpath">
<pathelement location="${build.classes.rel-dir}" />
<path refid="project.lib.path" />
<path refid="jwsdp.jars.path" />
</path>
<path id="run.classpath">
<path refid="compile.classpath" />
</path>
<target name="build"
depends="config,build-jax-ws-client,compile"
description="Build the project">
</target>
</project>
c. Criar directorias temporárias build e dist e confirmar que sintaxe do
build.xml está correcta:
$ ant init
2. Criar cliente
a. Gerar stubs
i. Executar wsimport
$ ant build-jax-ws-client
ii. Consultar stubs gerados pelo wsimport em build/jax-wsclient/wsimport,
em
particular
MyService.java
e
MyPortType.java
b. Criar classe do cliente em src/java/my
package my;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceException;
import my.ws.stubs.*;
public class MyServiceClient {
public static void main(String[] args) {
try {
System.out.println("begin");
16
Java Web Services Cookbook
// web service endpoint address
String endpointURL = args[0];
System.out.println("Web Service endpoint URL: " +
endpointURL);
//
// create Web Service stub
//
MyService service = new MyService();
MyPortType port = service.getMyPort();
BindingProvider bindingProvider = (BindingProvider)
port;
// set endpoint address
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_AD
DRESS_PROPERTY, endpointURL);
//
// invoke Web Service operation
//
port.myOperation(123, "abc");
} catch(WebServiceException e) {
// handle Web Service exception
System.out.println("Caught web service exception: ");
System.out.println(e.getClass().toString());
System.out.println(e.getMessage());
} catch(Exception e) {
// handle general exception
System.out.println("Caught exception: ");
System.out.println(e.getClass().toString());
System.out.println(e.getMessage());
} finally {
System.out.println("end");
}
}
}
c. Construir cliente e executar
$ ant run
Variantes
Diagnóstico de erros
Consultar tipo e mensagem da excepção produzida.
Usar Eclipse
(Antes do passo 2)
Iniciar o Eclipse e criar novo projecto
File, New, Project, Java Project, Project name: MyWSCli
Create project from existing source, Next
Source, Source folder, src/java, Default output folder: build/eclipse
Libraries, Add library, User library: jwsdp-essd-2008, Finish
Add class folder: build/classes, Finish
17
Java Web Services Cookbook
O conjunto de bibliotecas (user library) jwsdp-essd-2008 pode ser importado a
partir do ficheiro contido na directoria %JWSDP_HOME%\eclipse.
Configurar Ant
Windows, Show View, Ant View
build.xml ~drag-and-drop~> Ant View
Hide internal targets
(Depois do passo 2, a, i)
Refrescar Eclipse
Project, Refresh
(Apoio ao passo 2, b)
Criar classe
File, New, Class
package: my
name: MyServiceClient
superclass: java.lang.Object
inherit abstract methods
public static void main(String[] args)
generate comments
Activar um JAX-WS Handler no cliente
Acrescentar o seguinte target ao build.xml.
<target name="-replace-jax-ws-client-custom-tokens(dir)">
<replace dir="${dir}" token="@jax-ws-client.handler-chains@">
<replacevalue><![CDATA[
<jws:handler-chains
xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handlerclass>my.handler.MyClientHandler</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
]]></replacevalue>
</replace>
</target>
A classe my.handler.MyClientHandler deverá existir e ser um JAX-WS
Handler.
18
Java Web Services Cookbook
Obter a localização do Web Service a partir do UDDI
Obter uma biblioteca com as classes step.framework.ws.registry.* e colocar
numa das directorias lib do projecto:
lib
my-ws
lib
Criar e preencher ficheiros de configuração de registo Registry.properties
(dados do servidor UDDI), ClassificationQuery.properties (dados de pesquisa
por classificação) ou NamePatternQuery.properties (dados de pesquisa por
nome).
my-ws
config
ws-registry
Registry.properties
ClassificationQuery.properties
NamePatternQuery.properties
Registry.properties
#
# Registry
#
[email protected]@
[email protected]@
[email protected]@
#locale=
optionOutputMessages=true
#optionValidateURI=false
#optionWarnAboutLocale=true
ClassificationQuery.properties
#
# Classification Query
#
queryClassificationScheme=unspsc-org:unspsc:3-1
queryClassificationName=Research and Science Based Services
queryClassificationValue=81000000
NamePatternQuery.properties
#
# Name Pattern Query
#
queryNamePattern=%Organization%
Criar ou editar ficheiro build.properties para acrescentar:
ws-registry.username=testuser
ws-registry.password=testuser
Modificar build.xml, acrescentando a importação de um novo módulo:
<import file="${import-ant}/ws-registry.xml" />
As propriedades relacionadas com a pesquisa UDDI:
<property name="ws-registry.url"
value="http://localhost:8080/RegistryServer/" />
<property name="ws-registry.main-class"
value="step.framework.ws.registry.Main" />
19
Java Web Services Cookbook
<property name="dir" value="${build.config.ws-registry.rel-dir}" />
<property name="ws-registry.query.args" value="${dir}/Registry.properties
query classification ${dir}/ClassificationQuery.properties" />
Uma nova dependência no build.xml:
<target name="build"
depends="config,build-ws-registry,build-jax-ws-client"
description="Builds the project">
</target>
Testar a pesquisa em tempo de compilação:
$ ant build-ws-registry ws-query
Efectuar a pesquisa no código do cliente:
package my;
import
import
import
import
javax.xml.ws.BindingProvider;
javax.xml.ws.WebServiceException;
step.framework.ws.registry.*;
my.ws.stubs.*;
public class MyServiceClient {
public static void main(String[] args) {
try {
System.out.println("begin");
//
// query web services registry
//
Registry registry = null;
ClassificationQuery query = null;
Registration[] registrationArray = null;
try {
registry = new Registry("/Registry.properties");
query = new
ClassificationQuery("/ClassificationQuery.properties");
registry.setOptionOutputMessages(false); // no output
registry.connect(false); // no authentication is required for
querying
registrationArray = registry.query(query);
if(registrationArray == null) {
System.out.println("No web service registrations found in
registry server " + registry.getURL());
return;
} else {
System.out.println("Found " + registrationArray.length + " web
service registrations in registry server " + registry.getURL());
}
} finally {
if(registry != null)
registry.disconnect();
}
//
// create Web Service stub
//
MyService service = new MyService();
MyPortType port = service.getMyPort();
BindingProvider bindingProvider = (BindingProvider) port;
//
// for each web service, invoke Web Service operation
//
System.out.println("Invoking operation on all found web service
20
Java Web Services Cookbook
registrations");
for(int i=0; i < registrationArray.length; i++) {
try {
String endpointURL =
registrationArray[i].getServiceBindingAccessURI();
// set endpoint address
System.out.println("Web Service endpoint URL: " +
endpointURL);
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
endpointURL);
port.myOperation(123, "abc");
} catch(WebServiceException e) {
// handle Web Service exception
System.out.println("Caught web service exception: ");
System.out.println(e.getClass().toString());
System.out.println(e.getMessage());
System.out.println("Proceed to next endpoint");
}
}
} catch(Exception e) {
// handle general exception
System.out.println("Caught exception: ");
System.out.println(e.getClass().toString());
System.out.println(e.getMessage());
} finally {
System.out.println("end");
}
}
}
Criar um cliente de dois Web Services
Para invocar dois Web Services a partir do mesmo cliente, suponhamos Hello
e Calc, é necessário criar duas directorias de configuração:
my-ws-cli
config
jax-ws-client_hello
client-custom-binding.xml
jax-ws-client_hello
client-custom-binding.xml
E modificar o build.xml:
<target name="build"
depends="config,build-jax-ws-client-stubs_hello,build-jax-ws-clientstubs_calc,compile"
description="Build the project">
</target>
<target name="build-jax-ws-client-stubs_hello">
<echo level="info" message="Creating Hello stubs..." />
<antcall target="build-jax-ws-client-stubs" inheritAll="false">
<param name="jax-ws-client.dir-name" value="jax-ws-client_hello" />
<param name="jax-ws-client.wsdl.url"
value="http://localhost:8080/ExemploHelloWS/endpoint?wsdl" />
<param name="jax-ws-client.stubs.package" value="hello.ws.stubs" />
<param name="jax-ws-client.custom-tokens.target-name" value="replace-jax-ws-client-custom-tokens(dir)_hello" />
</antcall>
</target>
<target name="-replace-jax-ws-client-custom-tokens(dir)_hello">
<replace dir="${dir}" token="@jax-ws-client.handler-chains@">
21
Java Web Services Cookbook
<replacevalue><![CDATA[
<jws:handler-chains
xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handlerclass>step.framework.ws.handler.LoggingHandler</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
]]></replacevalue>
</replace>
</target>
<target name="build-jax-ws-client-stubs_calc">
<echo level="info" message="Creating Calc stubs..." />
<antcall target="build-jax-ws-client-stubs" inheritAll="false">
<param name="jax-ws-client.dir-name" value="jax-ws-client_calc" />
<param name="jax-ws-client.wsdl.url"
value="http://localhost:8080/ExemploCalcWS/endpoint?wsdl" />
<param name="jax-ws-client.stubs.package" value="calc.ws.stubs" />
<param name="jax-ws-client.custom-tokens.target-name" value="replace-jax-ws-client-custom-tokens(dir)_calc" />
</antcall>
</target>
<target name="-replace-jax-ws-client-custom-tokens(dir)_calc">
<replace dir="${dir}" token="@jax-ws-client.handler-chains@">
<replacevalue><![CDATA[
<jws:handler-chains
xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain>
<jws:handler>
<jws:handlerclass>step.framework.ws.handler.LoggingHandler</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
]]></replacevalue>
</replace>
</target>
Os targets -replace-jax-ws-client-custom-tokens(dir)_hello e -replace-jax-wsclient-custom-tokens(dir)_calc são definidos para permitir uma configuração
individual de JAX-WS Handlers.
O código do cliente deve importar e usar os stubs dos dois Web Services:
import hello.ws.stubs.*;
import calc.ws.stubs.*;
...
22