No [passo 1], nós configuramos o plugin CXF Eclipse para usar o CXF 2.4.2 e criamos um Dynamic Web Project vazio com Tomcat 7.
Neste artigo, nós vamos criar um exemplo de classe Java HelloServiceImpl e publicá-lo como WebService utilizando o wizard CXF Eclipse. Basicamente, esse wizard vai:
- Modificar HelloServiceImpl para adicionar anotações JAX-WS bem formadas.
- Modificar ou criar o arquivo Spring beans.xml que declara o WebService (no nosso caso, HelloServiceImpl) para publicar.
- Modificar o web.xml para declarar o Spring CXF Servlet usado para emitir o devido WebService declarado no beans.xml.
Download
Você pode baixar o arquivo jaxwswithcxf_step2.zip, que é um zip que contém o Dynamic Web Project jaxwswithcxf com os WebServicesHelloWorldImpl explicados neste artigo.
Criando a classe HelloServiceImpl
Crie no Dynamic Web Project jaxwswithcxf a classe org.sample.ws.HelloServiceImpl da seguinte forma:
01 package org.sample.ws;
02
03 public class HelloServiceImpl {
04
05 public String getVersion() {
06 return "1.0";
07 }
08
09 public String hello(String user) {
10 return "Hello " + user + "!";
11 }
12 }
Criando o WebService HelloServiceImpl
Web services podem ser criados utilizando dois métodos:
- Desenvolvimento top-down: envolve a criação de um Web service a partir do arquivo WSDL. Um arquivo WSDL descreve os services (métodos, parâmetros) e define o contrato para o WebService. Esse arquivo WSDL pode também ser usado para gerar o consumidor do WebService (que pode ser de uma tecnologia diferente (PHP, .Net etc.) do WebService).
- Desenvolvimento bottom-up: envolve a criação de um Web service a partir de um Java bean ou um de enterprise bean.
No nosso caso, vamos utilizar um desenvolvimento bottom-up: nós vamos usar a classe Java HelloServiceImpl para criar o Web service.
Passo 1: selecionar a classe Java
Clique com o botão direito do mouse em HelloServiceImpl e selecione o item de menu Web Services/Create Web Service:
Passo 2: selecionar CXF runtime
Esta ação abre o wizard genérico Web Service para gerar o WebService com Axis, Axis2, CXF etc.:
No nosso caso, queremos gerar o código CXF. Para isso, clique em Web service runtime: Apache Axis, o Service Deployment Configuration abre. Selecione Apache CXF 2.x para Web service runtime:
Clique no botão OK para fechar o diálogo Service Deployment Configuration:
Você pode notar que o Web service runtime é o Apache CXF 2.x. Por default, o Start service é selecionado, o que significa que assim que o wizard for fechado, o servidor vai iniciar. Eu prefiro iniciar meu servidor manualmente, então eu uso Install Service para evitar a inicialização do servidor no final do wizard.
Passo 3: Starting Point Configuration
Clique no botão Next, e a página Starting Point Configuration do wizard aparece. Essa página é usada para gerar a interface (para o HelloServiceImpl) com anotações JAX-WS. No nosso caso, não alteramos nada, e o HelloServiceImpl conterá a anotação JAX-WS:
Passo 4: Web Service JAX-WS Annotations Configuration
Clique no botão Next, e a página Web Service JAX-WS Annotations Configuration do wizard aparece. Essa página fornece vários checkbox que você pode selecionar/desmarcar para gerar anotações JAX-WS.
Você pode visualizar o código gerado no final dessa página. No nosso caso, nós não alteramos os valores pré-definidos. Vamos brincar com esses checkbox em um artigo futuro:
Passo 5: Web Service Java2WS Configuration
Clique no botão Next, e a página Web Service Java2WS Configuration do wizard aparece. Essa página fornece alguns checkbox para selecionar o que você quer gerar:
- Generate Client gera um cliente simples com JAX-WS Service.create().
- Generate Server gera um servidor simples do WebService. Esse código inicia um servidor (com EmbeddingJetty) e publica o WebService utilizando JAX-WS Endpoint#publish.
- Generate Wrapper and Fault Beans gera a classe Java com anotação JAXB. Essas classes são geradas no pacote *.jaxws (no nosso caso, org.sample.ws.jaxws). Nós vamos ver o uso dessas classes em próximos artigos.
- Generate WSDL gera o WSDL do WebService.
o WSDL File: nome do arquivo WSDL a ser gerado.
o Default SOAP Binding.
o Generate seperate XSD for the types: se esta opção está selecionada, o arquivo WSDL gerado não vai conter o XML Schema que declara o tipo da estrutura usada nos parâmetros do método.
Passo 6: Web Service Publication
Clique no botão Next, e a página Web Service Publication do wizard aparece:
Clique no botão Finish para gerar o WebService JAX-WS e o componente CXF (Spring beans e web.xml).
Resultado do wizard CXF
Após o término da geração do wizard CXF, sua área de trabalho se parece com o seguinte:
O wizard gera muitas coisas, entre elas:
- [1] HelloServiceImpl: modifica a classe Java HelloServiceImpl com anotações JAX-WS:
01 package org.sample.ws;
02
03 import javax.jws.WebService;
04
05 @WebService(targetNamespace = "http://ws.sample.org/", portName = "HelloServiceImplPort", serviceName = "HelloServiceImplService")
06 public class HelloServiceImpl {
07
08 public String getVersion() {
09 return "1.0";
10 }
11
12 public String hello(String user) {
13 return "Hello " + user + "!";
14 }
15 }
A anotação JAX-WS javax.jws.WebService é usada para indicar que essa classe é um WebService.
- [2] Gera algumas classes no pacote org.sample.ws.jaxws. Essas classes são geradas porque o checkbox Generate Wrapper and Fault Beans da página Web Service Java2WS Configuration estava marcado. Neste passo, essas classes não são utilizadas.
- [3] CXF libraries. Se você abrir este item, verá que o wizard usa o JAR inteiro da distribuição CXF:
Não tenha medo da quantidade de JARs, o CXF precisa de poucos JARs.
- [4] beans.xml: este arquivo Spring é usado para declarar com Spring bean a classe do Java HelloServiceImpl que deve ser publicada como WebService:
01 <?xml version="1.0" encoding="UTF-8"?>
02 <beans xmlns="http://www.springframework.org/schema/beans"
03 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
04 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
05 <import resource="classpath:META-INF/cxf/cxf.xml" />
06 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
07 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
08 <jaxws:endpoint xmlns:tns="http://ws.sample.org/" id="helloservice"
09 implementor="org.sample.ws.HelloServiceImpl" wsdlLocation="wsdl/helloserviceimpl.wsdl"
10 endpointName="tns:HelloServiceImplPort" serviceName="tns:HelloServiceImplService"
11 address="/HelloServiceImplPort">
12 <jaxws:features>
13 <bean class="org.apache.cxf.feature.LoggingFeature" />
14 </jaxws:features>
15 </jaxws:endpoint>
16 </beans>
– A seguinte declaração:
1 <jaxws:endpoint ... implementor="org.sample.ws.HelloServiceImpl"
é usada para publicar a classe HelloServiceImpl.
– A seguinte declaração:
1 <jaxws:endpoint ... address="/HelloServiceImplPort"
é usada para atribuir o diretório para a URL de HelloServiceImpl. No nosso caso, nosso service estará disponível em http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort. (NÃO ABRE)
– A seguinte declaração:
1 <jaxws:endpoint ... wsdlLocation="wsdl/helloserviceimpl.wsdl"
atribui a localização do WSDL. Se você remove esse atributo wsdlLocation, o WSDL será gerado se você acessá-lo pela URL http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort?wsdl. (NÃO ABRE)
- [5] web.xml é modificado para declarar o Servlet CXF baseado no Spring
1 <servlet>
2 <description>Apache CXF Endpoint</description>
3 <display-name>cxf</display-name>
4 <servlet-name>cxf</servlet-name>
5 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
6 <load-on-startup>1</load-on-startup>
7 </servlet>
Disponível em http://localhost:8080/jaxwswithcxf/services/: (NÃO ABRE)
1 <servlet-mapping>
2 <servlet-name>cxf</servlet-name>
3 <url-pattern>/services/*</url-pattern>
4 </servlet-mapping>
Esse servlet é usado para expedir os WebServices apropriados. Para conhecer os WebServices implantados, esse servlet usa o Spring ApplicationContext carregado a partir do beans.xml:
1 <context-param>
2 <param-name>contextConfigLocation</param-name>
3 <param-value>WEB-INF/beans.xml</param-value>
4 </context-param>
5
6 <listener>
7 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
8 </listener>
Aqui está o código completo do web.xml:
01 <?xml version="1.0" encoding="UTF-8"?>
02 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
03 <display-name>jaxwswithcxf</display-name>
04 <welcome-file-list>
05 <welcome-file>index.html</welcome-file>
06 <welcome-file>index.htm</welcome-file>
07 <welcome-file>index.jsp</welcome-file>
08 <welcome-file>default.html</welcome-file>
09 <welcome-file>default.htm</welcome-file>
10 <welcome-file>default.jsp</welcome-file>
11 </welcome-file-list>
12 <servlet>
13 <description>Apache CXF Endpoint</description>
14 <display-name>cxf</display-name>
15 <servlet-name>cxf</servlet-name>
16 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
17 <load-on-startup>1</load-on-startup>
18 </servlet>
19 <servlet-mapping>
20 <servlet-name>cxf</servlet-name>
21 <url-pattern>/services/*</url-pattern>
22 </servlet-mapping>
23 <session-config>
24 <session-timeout>60</session-timeout>
25 </session-config>
26 <context-param>
27 <param-name>contextConfigLocation</param-name>
28 <param-value>WEB-INF/beans.xml</param-value>
29 </context-param>
30 <listener>
31 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
32 </listener>
33 </web-app>
- [6] helloserviceimpl_schema1.xsd: esse XML Schema descreve a estrutura usada no WebService. Esse arquivo é gerado porque o checkbox Generate seperate XSD for the types da página Web Service Java2WS Configuration estava marcado. Aqui está o conteúdo desse arquivo:
01 <?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.sample.org/" elementFormDefault="unqualified" targetNamespace="http://ws.sample.org/" version="1.0">
02 <xs:element name="getVersion" type="tns:getVersion"/>
03 <xs:element name="getVersionResponse" type="tns:getVersionResponse"/>
04 <xs:element name="hello" type="tns:hello"/>
05 <xs:element name="helloResponse" type="tns:helloResponse"/>
06 <xs:complexType name="getVersion">
07 <xs:sequence/>
08 </xs:complexType>
09 <xs:complexType name="getVersionResponse">
10 <xs:sequence>
11 <xs:element minOccurs="0" name="return" type="xs:string"/>
12 </xs:sequence>
13 </xs:complexType>
14 <xs:complexType name="hello">
15 <xs:sequence>
16 <xs:element minOccurs="0" name="arg0" type="xs:string"/>
17 </xs:sequence>
18 </xs:complexType>
19 <xs:complexType name="helloResponse">
20 <xs:sequence>
21 <xs:element minOccurs="0" name="return" type="xs:string"/>
22 </xs:sequence>
23 </xs:complexType>
24 </xs:schema>
- [7] helloserviceimpl.wsdl: é o WSDL gerado. Esse arquivo é gerado porque o checkbox Generate WSDL da página Web Service Java2WS Configuration estava marcado. Aqui está o conteúdo desse arquivo:
01 <?xml version="1.0" encoding="UTF-8"?>
02 <wsdl:definitions name="HelloServiceImplService" targetNamespace="http://ws.sample.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.sample.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
03 <wsdl:types>
04 <schema xmlns="http://www.w3.org/2001/XMLSchema">
05 <import namespace="http://ws.sample.org/" schemaLocation="helloserviceimpl_schema1.xsd"/>
06 </schema>
07 </wsdl:types>
08 <wsdl:message name="hello">
09 <wsdl:part name="parameters" element="tns:hello">
10 </wsdl:part>
11 </wsdl:message>
12 <wsdl:message name="getVersion">
13 <wsdl:part name="parameters" element="tns:getVersion">
14 </wsdl:part>
15 </wsdl:message>
16 <wsdl:message name="helloResponse">
17 <wsdl:part name="parameters" element="tns:helloResponse">
18 </wsdl:part>
19 </wsdl:message>
20 <wsdl:message name="getVersionResponse">
21 <wsdl:part name="parameters" element="tns:getVersionResponse">
22 </wsdl:part>
23 </wsdl:message>
24 <wsdl:portType name="HelloServiceImpl">
25 <wsdl:operation name="getVersion">
26 <wsdl:input name="getVersion" message="tns:getVersion">
27 </wsdl:input>
28 <wsdl:output name="getVersionResponse" message="tns:getVersionResponse">
29 </wsdl:output>
30 </wsdl:operation>
31 <wsdl:operation name="hello">
32 <wsdl:input name="hello" message="tns:hello">
33 </wsdl:input>
34 <wsdl:output name="helloResponse" message="tns:helloResponse">
35 </wsdl:output>
36 </wsdl:operation>
37 </wsdl:portType>
38 <wsdl:binding name="HelloServiceImplServiceSoapBinding" type="tns:HelloServiceImpl">
39 <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
40 <wsdl:operation name="getVersion">
41 <soap:operation soapAction="" style="document"/>
42 <wsdl:input name="getVersion">
43 <soap:body use="literal"/>
44 </wsdl:input>
45 <wsdl:output name="getVersionResponse">
46 <soap:body use="literal"/>
47 </wsdl:output>
48 </wsdl:operation>
49 <wsdl:operation name="hello">
50 <soap:operation soapAction="" style="document"/>
51 <wsdl:input name="hello">
52 <soap:body use="literal"/>
53 </wsdl:input>
54 <wsdl:output name="helloResponse">
55 <soap:body use="literal"/>
56 </wsdl:output>
57 </wsdl:operation>
58 </wsdl:binding>
59 <wsdl:service name="HelloServiceImplService">
60 <wsdl:port name="HelloServiceImplPort" binding="tns:HelloServiceImplServiceSoapBinding">
61 <soap:address location="http://localhost:9090/HelloServiceImplPort"/>
62 </wsdl:port>
63 </wsdl:service>
64 </wsdl:definitions>
Você pode reparar que você tem o item de menu JAX-WS Web Services que te mostra informações sobre as classes Java que estão anotadas com JAX-WS:
Lançando a Aplicação WEB
Neste passo, nós não temos nenhum cliente (consumidor do HelloServiceImpl) mas podemos testá-lo.
Uma informação importante é que nosso WebService é declarado com org.apache.cxf.feature.LoggingFeature:
1 <jaxws:endpoint id="helloservice"
2 ...>
3 <jaxws:features>
4 <bean class="org.apache.cxf.feature.LoggingFeature" />
5 </jaxws:features>
6 </jaxws:endpoint>
Esse recurso é muito útil porque ele te fornece a capacidade de rastrear, por exemplo, a mensagem SOAP recebida (IN) e a mensagem SOAP enviada (OUT). Nós vamos verificar isso no Eclipse Console View.
Lance jaxwswithcxf para publicar nosso WebService. Depois da inicialização da Aplicação Web, você pode ver alguns logs interessantes no Eclipse Console View.
- Você pode notar que WEB-INF/beans.xml está aberto:
1 ...
2 INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/beans.xml]
3 ...
E verificar que HelloServiceImpl está publicado:
1 ...
2 INFO: Creating Service {http://ws.sample.org/}HelloServiceImplService from WSDL: wsdl/helloserviceimpl.wsdl
3 22 août 2011 17:16:13 org.apache.cxf.endpoint.ServerImpl initDestination
4 INFO: Setting the server's publish address to be /HelloServiceImplPort
5 ...
URLs
Neste ponto, você pode brincar com diferentes URLs.
Lista de services CXF
Se você for em http://localhost:8080/jaxwswithcxf/services (NÃO ABRE), você pode ver uma lista de WebServices (e services REST):
WSDL
Se você clica no link
WSDL: {http://ws.sample.org/}HelloServiceImplService (NÃO ABRE)
você vai ver o WSDL:
A URL do WSDL é http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort?wsdl (NÃO ABRE)
Se você for no Eclipse Console View, você verá alguns logs (porque nós temos LoggingFeatures):
Método getVersion
É possível chamar nosso método getVersion com a seguinte URL
http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/getVersion (NÃO ABRE) que retorna a mensagem SOAP:
1 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2 <soap:Body>
3 <ns2:getVersionResponse xmlns:ns2="http://ws.sample.org/">
4 <return>1.0</return>
5 </ns2:getVersionResponse>
6 </soap:Body>
7 </soap:Envelope>
Se você for noEclipse Console View, você verá alguns logs (porque nós temos LoggingFeatures):
Com esse log, você pode ver, por exemplo, a mensagem SOAP enviada.
Método hello
É possível chamar o método com parâmetro. Se você chama hello desta forma, você verá que:
http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/hello (NÃO ABRE)
1 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2 <soap:Body>
3 <ns2:helloResponse xmlns:ns2="http://ws.sample.org/">
4 <return>Hello null!</return>
5 </ns2:helloResponse>
6 </soap:Body>
7 </soap:Envelope>
1 Hello null!
é retornado porque nós não atribuímos o parâmetro.
Para atribuir um parâmetro, você deve acessar esta URL:http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/hello?arg0=world (NÃO ABRE)
Essa URL vai retornar a seguinte mensagem SOAP:
1 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2 <soap:Body>
3 <ns2:helloResponse xmlns:ns2="http://ws.sample.org/">
4 <return>Hello world!</return>
5 </ns2:helloResponse>
6 </soap:Body>
7 </soap:Envelope>
Por que arg0? Porque se você verificar o XML Schema, você tem:
1 <xs:complexType name="hello">
2 <xs:sequence>
3 <xs:element minOccurs="0" name="arg0" type="xs:string"/>
4 </xs:sequence>
5 </xs:complexType>
Conclusão
Neste artigo, nós geramos, a partir de um wizard CXF Eclipse, um WebService com JAX-WS. Esse wizard inicializa o CXF criando o beans.xml, que declara as classes Java que devem ser publicadas e o CXF Servlet. Você pode reparar que o HelloServiceImpl não está conectado com o CXF e poderia ser utilizado com outra implementação JAX-WS.
No próximo artigo [passo 3], nós vamos criar e gerar um cliente com JAX-WS (e CXF) que irá consumir nosso WebService.
?
Texto original disponível em http://angelozerr.wordpress.com/2011/08/24/jaxwscxf_step2/