Este é um post disponível para assinantes MVPArtigo Java Magazine 73 - Spring-WS de ponta a ponta
Contract-first através de um exemplo completo Aprenda como utilizar mapeamento Objeto/XML com JAXB e como configurar autenticação baseada no padrão WS-Security
[Artigo já está disponível no Leitor Digital DevMedia®. Clique aqui para acessá-lo]
> Clique aqui para ler todos os artigos da Java Magazine 73
Spring-WS de ponta a ponta
Contract-first
através de um exemplo completo
Aprenda como utilizar mapeamento Objeto/XML com JAXB e como
configurar autenticação baseada no padrão WS-Security
Michel Zanini
Do que se trata o artigo:
O artigo apresenta um exemplo prático completo de como
desenvolver um web service utilizando o framework Spring Web Services
(Spring-WS) e contract-first. E ainda, apresenta na prática as tecnologias de
mapeamento Objeto/XML e WS-Security.
Para que serve:
O exemplo apresentado pode ser utilizado como base para
construção de web services com requisitos semelhantes. De fato, o exemplo está
didaticamente apresentado de forma a tornar mais simples o entendimento do
processo de desenvolvimento contract-first.
Em que situação o tema é útil:
O assunto é relevante para web services de médio e grande
porte que necessitem manterem-se estáveis ao longo do tempo, garantindo
estabilidade, interoperabilidade e segurança.
Spring-WS de ponta a ponta:
Este artigo possui um foco prático, demonstrando através de
um exemplo real, como implementar web services contract-first. O objetivo é
construir um web service completo demonstrando a utilização de mapeamento
Objeto/XML e WS-Security.
A aplicação de exemplo é um sistema de consulta e reservas
de passagens para companhias aéreas, que tem por objetivo expor seus serviços
para integração com terceiros. Inicialmente, apresentamos todas as camadas da
aplicação antes de começarmos com o web service. Em seguida, construímos o web
service utilizando Spring-WS e OXM.
Mapeamento Objeto/XML (OXM) é um termo utilizado para
descrever tecnologias que são capazes de transformar objetos em XML e
vice-versa, sem que o programador precise criar código de parsing. Utilizamos o JAXB para mapear um XML Schema diretamente
para JavaBeans, e então evitar a utilização de um parser de XML.
Por fim, demonstramos como adicionar autenticação ao serviço
utilizando a especificação WS-Security. O Spring-WS utiliza endpoint
interceptors para adicionar WS-Security de forma transparente, tanto no
servidor como no cliente.
Este artigo é a segunda e última parte de uma série de
artigos sobre Spring Web Services (Spring-WS). Na primeira parte aprendemos as diferenças
entre os estilos de desenvolvimento Contract
First e Contract Last. Para
relembrar, vimos que com contract-last começamos pelo código Java e geramos o
WSDL automaticamente. Com contract-first focamos no XML Schema que fará parte
do contrato WSDL e após implementamos o contrato utilizando Java. Em seguida,
vimos que o contract-first possui vantagens em relação à consistência,
performance, versionamento e validação.
É aconselhável, mas não necessário, que o leitor leia o artigo “Introdução
ao Spring Web Services” presente na Edição 71. O artigo apresenta os conceitos
básicos relacionados à XML e web services como SOAP, XML schema e WSDL. Além
disso, apresenta um exemplo inicial de como criar web services com contract-first
no Spring-WS.
Dando seqüência ao anterior, este artigo possui um foco
prático, considerando que os conceitos como pré-requisito já foram abordados na
primeira parte. O objetivo é construir um web service completo começando do
zero. O caso de uso para sua criação deve ser realista, ou seja, deve ser
comparável em complexidade a web services em uso já publicados na Internet.
Entretanto, devido ao espaço limitado de um artigo, alguns detalhes serão
simplificados.
Em geral, um web service é desenvolvido sobre um sistema já
pronto, oferecendo apenas uma nova interface de acesso para fins de integração
com terceiros. Dessa forma, por exemplo, é comum termos um sistema web e um web
service que compartilhem a mesma lógica de negócios.
Primeiramente, iremos apresentar a aplicação sobre a qual o
web service será construído. Essa aplicação terá as camadas de negócio e persistência
desenvolvidas e testadas por testes de unidade. Em seqüência, concentraremos em
implementar um web service que irá expor os serviços desta aplicação para
acesso externo.
Apresentando a aplicação de exemplo
A aplicação de exemplo é um sistema de consulta e reservas
de passagens para companhias aéreas. Vamos supor que uma companhia do ramo nos
contratou para desenvolver tal aplicação. No levantamento de requisitos descobrimos
que devemos disponibilizar uma interface de consulta com os seguintes parâmetros:
cidade de origem e destino; data de partida e retorno; e a opção de incluir ou
não vôos com conexão. A reserva de passagem necessita apenas do código do vôo
desejado e do código de identificação do passageiro.
A companhia aérea também deseja integrar seu sistema com
aplicações de comparação de preços, como por exemplo, o excelente www.skyscanner.net. Considerando que
teremos um número relativamente grande de empresas diferentes acessando nosso
serviço, devemos manter um contrato bem definido e estável. É muito importante
que alterações subseqüentes no contrato não inviabilizem as empresas que já
estejam utilizando o serviço. Outro requisito levantado, na área de segurança,
é requerer autenticação para acesso utilizando usuário e senha.
É natural, neste caso, a escolha de XML sobre HTTP como meio
de comunicação, dado que não sabemos quais tecnologias tais empresas utilizam. Sendo
assim, o que nos resta é decidir entre web services REST ou SOAP.
Considerando a existência de um contrato rígido e estável, e a natureza dos
nossos serviços, o uso de SOAP é mais favorável. Porém, é importante deixar
claro que a utilização de REST seria completamente viável. Supondo que as
empresas que irão se integrar com nossa aplicação já estão no mercado há muitos
anos, e que já possuem integrações utilizando SOAP, decidimos seguir o mesmo
caminho.
REST ou SOAP: REST (Representational State Transfer) se
caracteriza pela simplicidade, utilizando apenas os recursos do HTTP e XML (ou
JSON, YAML, texto puro, etc.). Já o SOAP agrega um protocolo que adiciona
overhead e complexidade, entretanto, o fato da existência do WSDL garante um
contrato rígido entre cliente e servidor. A decisão entre qual arquitetura
utilizar é delicada. Em geral, deve-se sempre considerar a utilização de REST e
recorrer a SOAP apenas quando necessário.
ATENÇÃO! A exibição deste artigo foi interrompida.
Este é um post disponível para assinantes MVP
3 COMENTÁRIOS
11:19:19,497 INFO [STDOUT] [DEBUG,GenericMarshallingMethodEndpointAdapter,http-127.0.0.1-8080-2] Marshalling [br.com.jm.airline.ws.schema.HelloResponse@13ce16] to response payload
11:19:19,656 INFO [STDOUT] [DEBUG,SimpleSoapExceptionResolver,http-127.0.0.1-8080-2] Resolving exception from endpoint [public br.com.jm.airline.ws.schema.HelloResponse br.com.jm.airline.ws.server.AirlineWebServiceEndpoint.helloRequest(br.com.jm.airline.ws.schema.HelloRequest) throws br.com.jm.airline.service.impl.InvalidBookingException]: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
11:19:19,688 INFO [STDOUT] [DEBUG,SoapMessageDispatcher,http-127.0.0.1-8080-2] Endpoint invocation resulted in exception - responding with Fault
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at org.jboss.ws.core.soap.NodeImpl.getFirstChild(NodeImpl.java:287)
at org.jboss.ws.core.soap.SOAPContentElement.getFirstChild(SOAPContentElement.java:462)
at org.apache.xerces.jaxp.validation.DOMValidatorHelper.validate(Unknown Source)
at org.apache.xerces.jaxp.validation.DOMValidatorHelper.validate(Unknown Source)
at org.apache.xerces.jaxp.validation.ValidatorImpl.validate(Unknown Source)
at javax.xml.validation.Validator.validate(Unknown Source)
at org.springframework.xml.validation.Jaxp13ValidatorFactory$Jaxp13Validator.validate(Jaxp13ValidatorFactory.java:61)
at org.springframework.ws.server.endpoint.interceptor.AbstractValidatingInterceptor.handleResponse(AbstractValidatingInterceptor.java:216)
at org.springframework.ws.server.MessageDispatcher.triggerHandleResponse(MessageDispatcher.java:347)
at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:224)
at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:168)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:57)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:230)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Unknown Source)
11:19:19,689 INFO [STDOUT] [DEBUG,ws,http-127.0.0.1-8080-2] Fault: <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Header/><env:Body><env:Fault><faultcode xmlns:valueNS="http://schemas.xmlsoap.org/soap/envelope/">valueNS:Server</faultcode><faultstring xml:lang="en">Index: 0, Size: 0</faultstring></env:Fault></env:Body></env:Envelope>
11:19:19,689 INFO [STDOUT] [DEBUG,sent,http-127.0.0.1-8080-2] Sent response [SaajSoapMessage {http://schemas.xmlsoap.org/soap/envelope/}Fault] for request [SaajSoapMessage {http://www.javamagazine.com.br/spring-ws/schema/airline}HelloRequest]
11:19:19,701 INFO [STDOUT] [DEBUG,MessageDispatcherServlet,http-127.0.0.1-8080-2] Successfully completed request
Eu nao sei se este eh o problema, mas se sua versao for 4.2.2 ou menos talvez seja relacionado a implementacao do SAAJ:
http://blog.springsource.com/arjen/archives/2008/05/19/the-sorry-state-of-saaj
Se nao for isso, eh algo relacionado aos JARS e versoes incluidas no servidor.

<property name="messageFactory">
<bean class="com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl"/>
</property>
</bean>
Valeu pela resposta rápida, Abraços
Space do autor


0
0
