1 / 64

Contract-First Web Services with Spring-WS

Contract-First Web Services with Spring-WS. Craig Walls Gateway Software Symposium 2007 craig@habuma.com Blog: http://www.springinaction.com Wiki: http://wiki.habuma.com. Who are you?. Java: 6? 5? 1.4? 1.3? 1.2? 1.1? Spring: 1.2? 2.0? 2.1? Web-Services: Axis? X-Fire? Glue? Spring-WS?

ivie
Télécharger la présentation

Contract-First Web Services with Spring-WS

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Contract-First Web Serviceswith Spring-WS Craig Walls Gateway Software Symposium 2007 craig@habuma.com Blog: http://www.springinaction.com Wiki: http://wiki.habuma.com

  2. Who are you? • Java: 6? 5? 1.4? 1.3? 1.2? 1.1? • Spring: 1.2? 2.0? 2.1? • Web-Services: Axis? X-Fire? Glue? Spring-WS? • Favorite session so far? • What brings you to this session?

  3. About me • Agile developer with Semantra • Natural language business intelligence • Developing software professionally for over 13 years • Telecom, Finance, Retail, Education • Java for most of that • Also some C/C++, C#/.NET, Ruby • Spring fanatic

  4. Agenda • Spring remoting and web services • Contract-first • Designing the contract • Introducing Spring-WS • Building service endpoints • Wiring it all together • Final thoughts • Q&A

  5. Spring remoting and web services Building a service using XFire

  6. Spring Remoting Overview • Client side: • ProxyFactoryBean : Produces wire-able proxy to a remote service • Service side: • Remote exporter : Exports a Spring-configured POJO as a service • Available in RMI, Hessian, Burlap, HttpInvoker flavors • Spring doesn’t provide an exporter for SOAP web services…however…

  7. XFire • Full-featured web-services stack • Comes with full Spring remoting support • XFireClientFactoryBean : A client-side factory bean that produces a proxy for remote service • XFireExporter : A Spring remote exporter to export POJOs as web services • http://xfire.codehaus.org

  8. Exporting an XFire service • Configure the POJO as a Spring <bean> • Configure the XFireExporter to export the service • Configure Spring’s DispatcherServlet in web.xml • Configure a handler-mapping to map URLs to the XFireExporter

  9. Using JSR-181 annotations • Annotate bean class and methods • Declare as <bean> in Spring • Configure Spring DispatcherServlet • Configure a Jsr181HandlerMapping in Spring

  10. What if the POJO changes? • The focus is on the POJO, not the contract. • The service is method-centric, not message-centric • The service’s contract is only a by-product of the export. • Consequently, the contract is volatile. • (That’s a bad thing!)

  11. Contract Last • The most important piece of a service is NOT the implementation--it’s the contract. • Nevertheless, many service developers treat the contract as a second-class citizen. • Some don’t even think about it at all.

  12. Contract-first web services

  13. The solution: Contract-first • If the contract is so important, then why not elevate it to the position it deserves. • Create the contract first • Then write code that satisfies the contract • Not necessarily implement the contract.

  14. WSDL-first is NOT contract-first • In the WSDL-first approach, WSDL is used to generate service skeletons. • Not unlike using IDL compilers to generate CORBA service skeletons • Resulting skeletons are coupled to the contract. • Changes to the contract change the skeletons

  15. It’s all in the message! • Contract-last services are operation-centric • A service is defined by its operations (which translate to methods) • Contract-first services are message-centric • A service is defined by the messages it processes and returns.

  16. The contract • WSDL + XSD • Operational contract: WSDL describes what the service can do. • Data contract: XSD describes the messages sent to the service.

  17. Contact-first: Basic steps • Define the messages (XML) • Create the data contract (XSD) • Create the operational contract (WSDL) • Develop an endpoint to process the messages (Spring-WS) • Map messages to endpoints • Deploy

  18. Defining the contract Don’t leave…it ain’t as bad as you think!!!

  19. Create sample messages • Write out XML that resembles what you want passed in and out of your service. • Believe it or not, this is the hardest part.

  20. PokerHandRequest <EvaluateHandRequest xmlns="http://www.springinaction.com/poker/schemas"> <card> <suit>HEARTS</suit> <face>TEN</face> </card> <card> <suit>SPADES</suit> <face>KING</face> </card> <card> <suit>HEARTS</suit> <face>KING</face> </card> <card> <suit>DIAMONDS</suit> <face>TEN</face> </card> <card> <suit>CLUBS</suit> <face>TEN</face> </card> </EvaluateHandRequest>

  21. PokerHandResponse <EvaluateHandResponse xmlns= "http://www.springinaction.com/poker/schemas"> <handName>Full House</handName> </EvaluateHandResponse>

  22. Create the data contract • Create XML Schema that can be used to validate sample messages • Options: • Write it by hand (not much fun) • Infer it • Inferred XSD is never perfect. Will require some fine-tuning by hand. • But at least you don’t have to write it all by hand.

  23. XSD Inference tools • Microsoft’s XSD inference tool • http://msdn2.microsoft.com/en-us/xml/Bb190622.aspx • Trang • http://www.thaiopensource.com/relaxng/trang.html • Nocternity (Perl script) • http://projects.nocternity.net/xsd-inference/

  24. Create operational contract • Write WSDL • Options: • Write it by hand (not much fun) • Infer it • Generated WSDL is never perfect. Will require some fine-tuning by hand. • Again, you didn’t write it all by hand.

  25. Introducing Spring-WS

  26. What is Spring-WS • Web services framework that encourages contract-first development • Web services are implemented as service endpoints • Endpoints process XML messages • Conceptually similar to Spring MVC • Includes Object-XML Mapping framework • http://static.springframework.org/spring-ws/site • Current version 1.0.1 (released yesterday!!!)

  27. Spring MVC DispatcherServlet Handler mapping Controller Command controller SimpleMapping ExceptionResolver Spring-WS MessageDispatcher Endpoint mapping Endpoint Marshalling endpoint SoapFaultMapping ExceptionResolver Spring-WS and Spring MVC

  28. Spring OXM • Abstraction framework over several popular XML marshalling APIs. • Used by Spring-WS to (un)marshal objects for endpoints. • Can also be used for general purpose XML marshalling.

  29. Supported marshalling APIs • Castor XML • JAXB (v1 and v2) • JiBX • XMLBeans • XStream

  30. Building service endpoints

  31. Service endpoints • Process XML message • Several Spring-WS base classes: • AbstractDom4jPayloadEndpoint • AbstractDomPayloadEndpoint • AbstractJDomPayloadEndpoint • AbstractMarshallingPayloadEndpoint • AbstractSaxPayloadEndpoint • AbstractStaxEventPayloadEndpoint • AbstractStaxStreamPayloadEndpoint • AbstractXomPayloadEndpoint • Spring-WS 1.0.0 added support for annotation-based endpoints • @Endpoint, @PayloadRoot, @XPathParam

  32. AbstractJDomPayloadEndpoint • Endpoint is given a JDom Element to process and must return a JDom Element: • Can use XPath queries to pull info out of Element objects. public class EvaluateHandJDomEndpoint extends AbstractJDomPayloadEndpoint implements InitializingBean { protected Element invokeInternal(Element element) throws Exception { … // process message } }

  33. AbstractMarshallingPayloadEndpoint • Given an Object and must return an Object. • Uses Spring’s OXM framework. • XML message is unmarshalled into Object. Returned object is marshalled into XML. public class EvaluateHandMarshallingEndpoint extends AbstractMarshallingPayloadEndpoint { protected Object invokeInternal(Object object) throws Exception { PurchaseOrder po = (PurchaseOrder) object; … // Process purchase order } }

  34. Annotation-based endpoint • Uses annotations to declare endpoints • Minimizes Spring XML configuration • Allows for more POJO(ish) endpoints • Helps with XML parsing • Three annotations… • @Endpoint - Declares a class as an endpoint • @PayloadRoot - Specifies a method as the destination for a payload message • @XPathParam - Defines how to parse message into method parameter

  35. Annotation-based endpoint package com.springinaction.poker.webservice; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import com.springinaction.poker.PokerHand; import com.springinaction.poker.PokerHandEvaluator; import com.springinaction.poker.PokerHandType; @Endpoint public class EvaluateHandAnnotatedEndpoint { @PayloadRoot(namespace = "http://www.springinaction.com/poker/schemas", localPart = "EvaluateHandRequest") public EvaluateHandResponse evaluateHand(EvaluateHandRequest request) { PokerHandType handType = pokerHandEvaluator.evaluateHand(new PokerHand( request.getHand())); return new EvaluateHandResponse(handType); } // injected private PokerHandEvaluator pokerHandEvaluator; public void setPokerHandEvaluator(PokerHandEvaluator pokerHandEvaluator) { this.pokerHandEvaluator = pokerHandEvaluator; } }

  36. Wiring it all together in Spring

  37. Spring-WS: The big picture Maps message payloads to endpoints Endpoint Implementation Business logic happens here Marshals XML messages to/from POJOs Magically generates WSDL from XSD Converts exceptions to SOAP faults

  38. MessageDispatcherServlet • Spring-WS is based on Spring MVC • Must configure a DispatcherServlet in web.xml… • Actually, MessageDispatcherServlet <servlet> <servlet-name>poker</servlet-name> <servlet-class> org.springframework.ws.transport.http.MessageDispatcherServlet </servlet-class> <init-param> <param-name>transformWsdlLocations</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>poker</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>poker</servlet-name> <url-pattern>*.wsdl</url-pattern> </servlet-mapping>

  39. Endpoint mappings When this kind of message arrives… Send it to this endpoint • Helps message dispatcher decide where messages should be sent • Two kinds: • PayloadRootQNameEndpointMapping • SoapActionEndpointMapping <bean id="payloadMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping"> <property name="endpointMap"> <map> <entry key="{http://www.springinaction.com/poker/schemas}EvaluateHandRequest" value-ref="evaluateHandEndpoint" /> </map> </property> </bean>

  40. Annotation endpoint mappings • If using annotation-based endpoints… <bean class="o.sf.ws.server.endpoint.mapping. PayloadRootAnnotationMethodEndpointMapping"> <property name="order" value="1"/> </bean> • Note that namespace/local-name of message are specified in @PayloadRoot • If marshaling, you’ll need a MarshallingMethodEndpointAdapter: <bean class="o.sf.ws.server.endpoint.adapter. MarshallingMethodEndpointAdapter"> <constructor-arg ref="marshaller"/> </bean>

  41. Wiring the endpoint <bean id="evaluateHandEndpoint" class= "com.springinaction.poker.webservice.EvaluateHandJDomEndpoint"> <property name="pokerHandEvaluator" ref="pokerHandEvaluator" /> </bean> <bean id="pokerHandEvaluator" class="com.springinaction.poker.PokerHandEvaluatorImpl"/>

  42. A marshalling endpoint <bean id="evaluateHandEndpoint" class="com.springinaction.poker.webservice. EvaluateHandMarshallingEndpoint"> <property name="marshaller" ref="marshaller" /> <property name="unmarshaller" ref="marshaller" /> <property name="pokerHandEvaluator" ref="pokerHandEvaluator" /> </bean> Automatically maps XML to/from objects

  43. An (un)marshaller: Castor <bean id="marshaller" class= "org.springframework.oxm.castor.CastorMarshaller"> <property name="mappingLocation" value="classpath:mapping.xml" /> </bean>

  44. Loose-end: Exceptions • What about exceptions? • How are they mapped to SOAP faults? • SoapFaultMappingExceptionResolver <bean id="endpointExceptionResolver” class= "org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver"> <property name="defaultFault" value="RECEIVER,Server error" /> <property name="exceptionMappings"> <props> <prop key="org.springframework.oxm.UnmarshallingException"> SENDER,Invalid request</prop> <prop key="org.springframework.oxm.ValidationFailureException"> SENDER,Invalid request</prop> </props> </property> </bean>

  45. Loose-end: Service location • The service location is hard-coded in the WSDL? • What if the service is deployed somewhere other than localhost? • SimpleWsdl11Definition serves WSDL, transforming locations to match request’s server and context. <bean id="poker" class= "org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition"> <property name="wsdl" value="/PokerService.wsdl"/> </bean>

  46. Or…DynamicWsdl11Definition • DynamicWsdl11Definition automatically generates WSDL from the message XSD <bean id="poker" class= "org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition"> <property name="builder"> <bean class="o.sf.ws.wsdl.wsdl11.builder. XsdBasedSoap11Wsdl4jDefinitionBuilder"> <property name="schema" value="/PokerTypes.xsd"/> <property name="portTypeName" value="Poker"/> <property name="locationUri" value="http://localhost:8080/Poker-WS/services"/> </bean> </property> </bean>

  47. Consuming Spring-WS services

  48. A word about writing clients • Proxy-based client APIs typically won’t work with Spring-WS • Proxies are method-centric and very RPC-ish in nature. • What does work is… • WSDL2Java-generated client stubs • Anything that can wrap supplied XML in a SOAP wrapper • Spring-WS client-side templates

  49. Using Spring-WS’ client API • Template-based • Much like Spring JDBC, Spring JMS, etc • Choices to make: • To marshal or not to marshal? • Basic template or gateway support?

  50. Spring-WS Client API • WebServiceTemplate - Centerpiece of Spring-WS client API (similar in concept to Spring’s JDBC Template) • Message factory - Produces message • Message sender - Sends message • (Un)Marshaler (optional)- Converts XML to/from POJO

More Related