Web Services Usando Maven, Spring e JAXB [Parte 3]

No post anterior mostramos o XML que o serviço espera como entrada e XML que esperamos de retorno do serviço. Foi colocado como exemplo as classes mapeadas com as anotações fornecidas pelo JAXB API para fazer a conversão dos XMLs em objetos Java e a conversão dos objetos Java em XML. Neste post iremos continuar explorando este serviço e vamos mostrar como criar a classe do endpoint que irá receber o XML e devolver a lista de erros em XML, como configurar o Maven e os arquivos necessários para que o serviço funcione corretamente e também como chamar esse serviço usando o Eclipse IDE.

Criando o WS: Endpoint

O Endpoint representa a parte do serviço responsável por receber uma requisição, executar alguma lógica de négocio e tratamento dos dados, e então gerar uma resposta. A Listagem 1 apresenta o código do enpoint ConsultaErrosEndpoint. O exemplo limita-se a repassar o parâmetro de requisição para uma consulta na base dados e retornar a resposta obtida.

@XmlTransient
@Endpoint
public class ConsultaErrosEndpoint {

public final static String CONSULTA_ERROS_REQUEST = "ConsultaErrosRequest";

@PayloadRoot(namespace = Namespaces.NAMESPACE, localPart = CONSULTA_ERROS_REQUEST)
@ResponsePayload
public ConsultaErrosResponse consultaMensagensErro(@RequestPayload ConsultaErrosRequest consultaErrosRequest) throws SOAPException {
// Faz a consulta ao banco de dados
ConsultaErrosResponse consultaErroResponse = consultaBancoDados(consultaErrosRequest);
return consultaErroResponse;
}
}
Listagem 1 – Definição da classe ConsultaErrosEndpoint. As anotações Spring permitem a configuração do endpoint. Por motivos de espaço a definição do método consultaBancoDados foi omitida.

A configuração do serviço é feita através de um conjunto de anotações disponibilizadas pelo framework Spring. Uma breve explicação de cada uma delas.
@Endpoint – Indica que é um Endpoint.
@PayloadRoot – Indica que o método irá tratar as requisições. Deve ser configurado o atributo localPart indicando qual requisição deve ser usada
@RequestPayload – Indica que o parâmetro do método deve ser uma classe para tratar request
@ResponsePayload – Indica qual objeto o método irá retornar como mensagem de response.

Note ainda a presença da anotação @XmlTransient em nível de classe. Essa anotação é utilizada pelo JAXB para ignorar a classe durante a geração do arquivo XSD.
Configurando o Deployment Descriptor

Para que as mensagens XML sejam tratadas corretamente pelo nosso serviço é preciso definir um servlet padrão para tratar as requisições. A Listagem 2 mostra a inclusão do servlet MessageDispatcherServlet no deployment descriptor (web.xml).

<servlet>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/context-ws.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>webservices</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
Listagem 2 – Configuração do deployment descriptor para inclusão do servlet MessageDispatcherServlet. O arquivo pode ser encontrado em webservicesrcmainwebappWEB-INFweb.xml.

Configurando o contex-ws.xml

No arquivo web.xml foi configurado o arquivo de configuração contex-ws.xml para o Spring. Crie este arquivo em /src/main/resources. E coloque as configurações necessárias para o serviço.
O Spring-WS é capaz de criar o WSDL a partir de um XSD. O XML a seguir configura o Spring para gerar o WSDL automaticamente.

<sws:dynamic-wsdl id="ExemploWS"
portTypeName="WebserviceExemplo"
locationUri="/services/"
requestSuffix="Request"
responseSuffix="Response"
targetNamespace="http://www.matera.com/services/exemplo/schemas">
<sws:xsd location="classpath:/schema_exemplo.xsd" />
</sws:dynamic-wsdl>
Listagem 3 – Trecho do arquivo de configuração context-ws.xml mostrando como gerar o WSDL automaticamente.

Também pode ser incluído um validador para as mensagens enviadas e recebidas. O Spring fornece um interceptor que verifica todas as mensagens com um XSD fornecido.

<sws:interceptors>
<bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="classpath:/schema_exemplo.xsd"></property>
<property name="validateRequest" value="true"></property>
<property name="validateResponse" value="true"></property>
</bean>
</sws:interceptors>
Listagem 4 – Trecho do arquivo de configuração context-ws.xml mostrando como validar os XMLs enviados e recebidos.

Deve ser colocado também as outras configurações para o Spring-WS, como qual marshaller deve ser usado e configurações para o Spring usar as annotations.

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" />
<bean class="org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping" />
<bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
<constructor-arg ref="marshaller" />
</bean>
Listagem 5 – Trecho do arquivo de configuração context-ws.xml mostrando como escolher o Marshaller que deve ser utilizado.

Deve ser configurado também quais classes o marshaller irá usar. Todas as classes devem ser listadas dentro da tag <list>.

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.matera.webservice.ConsultaErrosResponse</value>
<value>com.matera.webservice.ConsultaErrosRequest</value>
<value>com.matera.webservice.ConsultaErrosEndpoint</value>
<value>com.matera.webservice.ErroSistema</value>
<value>com.matera.webservice.TipoErro</value>
</list>
</property>
<property name="schema" value="classpath:schema_exemplo.xsd" />
</bean>
Listagem 6 – Trecho do arquivo de configuração context-ws.xml mostrando quais as classes que serão usadas pelo Marshaller.

Gerando o XSD

No arquivo context-ws.xml foi configurado que o Spring irá usar o arquivo schema_exemplo.xsd para fazer as validações do request e response, gerar o WSDL e o JAXB irá usar para fazer o marshaller dos objetos.
O XSD é gerado por um plugin do Maven que deve ser configurado no pom.xml. Edite o pom.xml incluindo o plugin jaxb2-maven-plugin.

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>schemagen</id>
<goals>
<goal>schemagen</goal>
</goals>
</execution>
</executions>
<configuration>
<transformSchemas>
<transformSchema>
<uri>http://www.matera.com/services/exemplo/schemas</uri>
<toFile>schema_exemplo.xsd</toFile>
</transformSchema>
</transformSchemas>
<includes>
<include>com/matera/webservice/adapter/*.java</include>
<include>com/matera/webservice/*.java</include> </includes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</plugin>
Listagem 7 – Trecho do arquivo de configuração pom.xml mostrando a configuração do plugin para gerar o XSD.

Na tag transformSchema deve informar para qual namespace o XSD será gerado. No caso todos as classes anotadas para terem a namespace http://www.matera.com/services/exemplo/schemas será incluída no arquivo schema_exemplo.xsd.
Na tag includes deve informar quais classes o plugin incluir nos XSDs. No exemplo existe apenas um XSD porque todas as classes estão anotadas para essa namespace.

Executando o serviço

O serviço está pronto para ser gerado. Execute o comando do Maven mvn clean install para gerar o arquivo webservice.war e faça deploy em algum servidor. Acesse o endereço http://localhost:8080/webservice/services/ExemploWS.wsdl para visualizar o WSDL gerado pelo Spring-WS.

Para testar o serviço usando o Eclipse, clique em File -> Import. Selecione na lista Web Services e depois o item Web Service. Clique Next e depois Finish. No canto superior direito escolha WSDL Page e coloque o endereço do WSDL gerado (http://localhost:8080/webservice/services/ExemploWS.wsdl) e clique em Go. O serviço ConsultaErro deve ser exibido. Clique nele e preencha o formulário com os dados que quer enviar para o serviço.

A ferramenta mostra o pacote SOAP enviado e o pacote SOAP recebido. Se tudo estiver certo, o pacote enviado deve ser parecido com o XML a seguir.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://www.matera.com/services/exemplo/schemas" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:ConsultaErrosRequest>
<tipoErro>WARNING</tipoErro>
<dataInicio>2013-07-12</dataInicio>
<dataFim>2013-07-27</dataFim>
</q0:ConsultaErrosRequest>
</soapenv:Body>
</soapenv:Envelope>
Listagem 8 – Pacote enviado para o serviço.

E o pacote de resposta.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns3:ConsultaErrosResponse xmlns:ns3="http://www.matera.com/services/exemplo/schemas">
<tipoErro>WARNING</tipoErro>
<erros>
<erro>
<data>2013-07-10</data>
<tipoErro>ERRO</tipoErro>
<mensagem>Erro mensagem 1</mensagem>
</erro>
<erro>
<data>2013-07-12</data>
<tipoErro>SISTEMA</tipoErro>
<mensagem>Erro de sistema mensagem 2</mensagem>
</erro>
<erro>
<data>2013-07-13</data>
<tipoErro>WARNING</tipoErro>
<mensagem>Alerta mensagem 3</mensagem>
</erro>
</erros>
</ns3:ConsultaErrosResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Listagem 9 – Pacote enviado pelo serviço.

Encerramos assim a parte de criação e configuração do nosso serviço. No próximo post vamos mostrar como fazer testes automáticos  para este serviços. Serão testes de unidade para testar a entrada e saída de XMLs e também alguns testes com a chamada real ao serviço usando o Jetty Embeded.

Por MATERA SYSTEMS

Postado em: 13 de fevereiro de 2014

Confira outros artigos do nosso blog

REST não é JSON

21 de agosto de 2017

Bruno Sofiato

[Webinar] Profile de aplicações Java com Oracle Mission Control e Flight Recorder

24 de julho de 2017

Danival Calegari

Criando Mocks de serviços REST com SoapUI

27 de junho de 2017

Monise Costa

JavaScript 6: diferença entre var, let e const

09 de maio de 2017

Otávio Felipe do Prado

Deixe seu comentário