Upload
sam-brannen
View
23.014
Download
3
Embed Size (px)
DESCRIPTION
SOAP Web Services have a well established role in the enterprise, but aside from the many benefits of the WS-* standards, SOAP and XML also carry additional baggage for developers. Consequently, REST Web Services are gaining tremendous popularity within the developer community. This session will begin by comparing and contrasting the basic concepts of both SOAP and REST Web Services. Building on that foundation, Sam Brannen will show attendees how to implement SOAP-based applications using Spring-WS 2.0. He will then demonstrate how to build a similar REST-ful application using Spring MVC 3.0. The session will conclude with an in-depth look at both server-side and client-side development as well as efficient integration testing of Web Services using the Spring Framework.
Citation preview
Spring Web Services:SOAP vs. REST
SamBrannenSwi+mindGmbH
SpeakerProfile
• SeniorSo+wareConsultant–Swi+mindGmbH• Javadeveloperwith13+years'experience• SpringFrameworkCoreDeveloper– AuthoroftheSpringTestContextFramework
• PreviousSpringSourcedmServer™developer• RegularspeakeratconferencesonSpring,dmServer,Java,OSGi,andtesOng
• LeadauthorofSpringinaNutshell;chieftechnicalreviewerforSpringRecipes
Agenda
• WebServicesConcepts• SpringEventsApplicaOon• Spring‐WS
• SpringREST• Server‐side• Client‐side• Q&A
WebServices
Concepts
• Client/ServerarchitectureovertheWeb– ServerexposesServices– ClientsendsaRequesttotheServer• foraspecificexposedService• withaPayloadtobeprocessedbytheService
– ServiceprocessestheRequestandreturnsaResponse
MarshallingandUnmarshalling
• Marshalling:Objectexternalformat• Unmarshalling:externalformatObject
• arequestorresponsecontainsapayload– o+enintheformofanXMLdocument– mayalsobebinary,JSON,etc.
• applicaOoncodehasitsowndomainmodel– maynotmapdirectlytoformatofpayload
SpringEventsApplica?on
IntroducingSpringEvents
• SimplePOJOdomainmodel:Event• TransacOonalservicelayer• Hibernaterepositorylayer– Withanin‐memoryHSQLdatabase
• Spring@MVCpresentaOonlayer– RESTful@Controller
• Spring‐WS@Endpoint
SpringEventsApplicaOon
Demo
SOAPWebServices
WhatisSpring‐WS?
SpringWebServicesaimstofacilitatecontract‐firstSOAPservicedevelopment,allowingforthecreaAonofflexiblewebservicesusingoneofthemanywaystomanipulateXMLpayloads.(Spring‐WSWebsite)
WhatisSOAP?
• SimpleObjectAccessProtocol– ProtocolforexchanginginformaOonviaWebServices
– UsesXMLasitsmessageformat– TypicallyoverHTTP
• Structure– Envelope– Header– Body(a.k.a.,payload)– Documentliteral
ContractLast
• DefineAPIinprogramminglanguage(e.g.,Java)
• UsetoolstogenerateXSDsandWSDLfromcode
• Pros– easy,no‐brainerfordevelopers
• Cons– horriblyfragile– anychangetocodebreakspreviouslypublishedcontract
– clientsmustbeupdated
ContractFirst
• DefinepublicAPItoservicesviaXSDschemasfirst– onerequestandresponseperexposedservice– generateWSDLfromXSDsusingconvenOonsforporttypes,etc.• potenOallyauto‐generated
– generateJavacodefromXSDs(e.g.,JAXB2)– createJavamappingcodemanually– oruseXPath,etc.toparseXMLdirectly
RESTWebServices
WhatisSpringREST?
• RESTfulWebServicesbuiltontopofSpring@MVC
• CombinesnicelywithexisOng@MVCcode
• LowlearningcurvefordevelopersfamiliarwithSpring@MVC
• SupportsmulOplemarshallingtechnologiessuitableforwebapplicaOons(e.g.,JSON)
• SpringREST!=JAX‐RS
WhatisREST?
• REpresentaOonalStateTransfer• HTTPProtocol– Standard– Ubiquitous– Scalable
• Stateless• Focusesonresources– NounsandVerbs
Nouns,Verbs,&Errors
• Nouns– Resourcesthatyouwanttointeractwith
• Verbs– Whatyoucandowitharesource• POST:createnewresource• GET:getsingleresourceoralistofresources• PUT:updateresource• DELETE:deleteresource
• Errorhandling– StandardHTTPresponsecodes
RESTfulURLs
• POST– hip://example.com/events
• GET– hip://example.com/events– hip://example.com/events/1
• PUT– hip://example.com/events/1
• DELETE– hip://example.com/events/1
Server‐side
Spring‐WSontheServer
• Bootstrappedinweb.xmlwithMessageDispatcherServlet
• <sws:annotaOon‐driven/>enables@Endpointmappings(ala@Controller)
• @PayloadRootmapshandlermethods
• @RequestPayloadmapspayloadtomethodparameter
• @ResponsePayloadmapsreturnvaluetoresponsepayload
GetEventEndpoint(1/2)@Endpointpublic class GetEventEndpoint {
private static final String NAMESPACE_URI = "http://example.com/schemas";
private final EventService eventService;
@Autowired public GetEventEndpoint(EventService eventService) { this.eventService = eventService; }
GetEventEndpoint(2/2)@PayloadRoot(localPart="GetEventRequest", namespace=NAMESPACE_URI)@ResponsePayloadpublic GetEventResponse getEvent( @RequestPayload GetEventRequest request) throws Exception {
Event event = eventService.findById(request.getId().longValue());
return toGetEventResponse(event);}
SpringRESTontheServer
• RESTWebServiceendpointsare@Controllers– @RequestMapping:mapstohandlermethods– @RequestBody:payloadofrequest– @ResponseBody:payloadofresponse– @ResponseStatus:setHTTPresponsecode– @PathVariableandUriTemplate• FormappingandcreaOngRESTfulURIs
• AutomaOcmarshallingofpayloads• ContentnegoOaOon
EventController(1/4)@RequestMapping("/events")@Controllerpublic class EventController {
protected final EventService eventService;
@Autowired public EventController(EventService eventService) { this.eventService = eventService; }
EventController(2/4)@RequestMapping(method = GET)@ResponseBodypublic List<Event> retrieveAllEvents() { return eventService.findAllEvents();}
@RequestMapping(value = "/{id}", method = GET)@ResponseBodypublic Event retrieveEvent(@PathVariable Long id) { return eventService.findById(id);}
EventController(3/4)@RequestMapping(method = POST)@ResponseStatus(HttpStatus.CREATED)public void createEvent(@RequestBody Event postedEvent, HttpServletRequest request, HttpServletResponse response) {
Event savedEvent = eventService.save(postedEvent);
String newLocation = buildNewLocation(request, savedEvent.getId());
response.setHeader("Location", newLocation);}
EventController(4/4)@RequestMapping(value = "/{id}", method = DELETE)@ResponseStatus(HttpStatus.NO_CONTENT)public void deleteEvent(@PathVariable Long id) { eventService.deleteById(id);}
private String buildNewLocation(HttpServletRequest request, Long id) {
String url = request.getRequestURL() .append("/{id}").toString();
UriTemplate uriTemplate = new UriTemplate(url); return uriTemplate.expand(id).toASCIIString();}
HiddenHipMethodFilter
• WebbrowserstypicallyonlysupportGETandPOST
• HiddenHipMethodFilter– providessupportforPUTandDELETErequestsfromwebbrowsers
– transparentlyconvertsPOSTrequestswithhidden_methodparameter
• Configuredinweb.xml
• CanbeusedinconjuncOonwithSpring’sJSPformtaglibrary
URITemplatesinJSPs
• Usethe<spring>taglibrarytoconstructdynamicURItemplatesinJSPs
• SimilartotheJSPcoretaglibrarysupportforbuildingURLswithparameters
<spring:urlvar="jsonUrl"value="/rest/events/{id}">
<spring:paramname="id"value="${event.id}"/></spring:url>
Client‐side
WebServiceTemplate
• InteractwithSOAPWebServicesasaclient• SupportscallbacksaswellasautomaOcmarshallingandunmarshallingofpayloads– sendAndReceive(…)– marshalSendAndReceive(…)
– etc.
EventsSoapClientTest(1/2)@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class EventsSoapClientTest {
@Autowired private WebServiceTemplate webServiceTemplate;
<oxm:jaxb2-marshaller id="marshaller” contextPath="com.swiftmind.samples.events.web.schema" />
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate” p:marshaller-ref="marshaller" p:unmarshaller-ref="marshaller" />
EventsSoapClientTest(2/2)@Testpublic void getEventRequest() {
String url = "http://localhost:8080/spring/soap";
GetEventRequest request = new GetEventRequest(); request.setId(BigInteger.valueOf(5L));
GetEventResponse response = (GetEventResponse) webServiceTemplate.marshalSendAndReceive(url, request);
assertNotNull(response); assertEquals("Spring I/O in Madrid", response.getEventData().getDescription()); }
RestTemplate
• InteractwithanyRESTWebServices– notlimitedtoSpringRESTservices
• SupportsURItemplatesandautomaOcmarshallingandunmarshallingofpayloads– postForLocaOon(…)– postForObject(…)– getForObject(…)– delete(…)– put(…)– etc.
EventsRestClient(1/3)public class EventsRestClient {
private final RestTemplate restTemplate = new RestTemplate(); private String url;
public URI createEvent(String name) { Event event = new Event(); event.setName(name);
return restTemplate.postForLocation(url, event); }
EventsRestClient(2/3)public void deleteEventByLocation(URI location) { restTemplate.delete(location);}
public void deleteEventById(Long id) { String deletionUrl = url + "/{id}";
restTemplate.delete(deletionUrl, id);}
EventsRestClient(3/3)public void retrieveEvent(URI location) { Event event = restTemplate.getForObject(location, Event.class);}
public void retrieveAllEvents() { Event[] events = restTemplate.getForObject(url, Event[].class);}
SpringSOAPWebServices
Demo
SpringRESTWebServices
Demo
FurtherResources
• SpringFramework– IncludingSpringREST– hip://springframework.org
• Spring‐WS– hip://staOc.springsource.org/spring‐ws/sites/2.0/
• GenerateXSDfromXML– hip://bit.ly/fLI1Bt
Q&A
SamBrannen
sam.brannen[at]swi+mind[dot]com
hip://www.swi+mind.com
hip://twiier.com/sam_brannen
“SpringinaNutshell” hip://oreilly.com/catalog/9780596801946 availablefromO’Reillyin2011