SlideShare a Scribd company logo
Building RESTful
applications with
   Spring MVC

     Craig Walls
Who Am I?
                       Java, Spring, and OSGi fanatic
              Principal Consultant with Improving
                                                       Author
                                             XDoclet in Action (Manning)

                                              Spring in Action (Manning)

                                       Modular Java (Pragmatic Bookshelf)




 E-mail: craig@habuma.com Blog: http://www.springinaction.com   Twitter: @habuma Slides: http://www.slideshare.net/habuma
What REST is NOT!!!



                 Web Services
                  with URLs




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
It’s about Resources

                                        Things, not actions


                                  Requests, not demands


                                  Resources, not services


                                 Transfer of state, not RPC

      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
The Pillars of REST

        Resources

       URIs/URLs

     HTTP Methods

     Representations




       E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
The Pillars of REST

                   Resources
    Produced as model data in Spring MVC Controllers


                  URIs/URLs
      Supported in handler methods by @PathParam


               HTTP Methods
 @RequestMapping, HiddenHttpMethodFilter, <form:form>


              Representations
              Rendered by view resolvers
      HTML, XML, JSON, RSS, Atom, PDF, Excel, etc.
     Negotiated by ContentNegotiatingViewResolver




                  E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Identifying Resources




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Demanding URLs

                       Direct Imperative                                    Resource identifier
                          Command                                             is pushed into
                                                                            a query parameter



http://www.somestore.com/displayProduct?sku=1234


                       Very service-y
                                                                     Not very cacheable or
                                                                     search engine friendly




           E-mail: craig@habuma.com   Blog: http://www.springinaction.com    Twitter: habuma
Resourceful URLs

                              The focus is
                            on the product,                       We’re requesting
                             not the action                       a product’s info



   http://www.somestore.com/product/1234


                   Cacheable                                                This URL also
                                                                         identifies a product
                                                                          (within a context)




        E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Spring MVC overview




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
DispatcherServlet

In /WEB-INF/web.xml
<servlet>
 <servlet-name>spitter</servlet-name>
  <servlet-class>
   org.springframework.web.servlet.DispatcherServlet
  </servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>spitter</servlet-name>
  <url-pattern>/app/*</url-pattern>
</servlet-mapping>




                 E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
ContextLoaderListener
In /WEB-INF/web.xml
<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>
  /WEB-INF/spitter-security.xml
  classpath:service-context.xml
  classpath:persistence-context.xml
  classpath:dataSource-context.xml
  classpath:setup-context.xml
 </param-value>
</context-param>

<listener>
 <listener-class>
  org.springframework.web.context.ContextLoaderListener
 </listener-class>
</listener>




                   E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
UrlRewriteFilter
In /WEB-INF/web.xml
<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>
        org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

                                                     In /WEB-INF/urlrewrite.xml
                                                     <urlrewrite default-match-type="wildcard">
                                                       <rule>
                      1234
           /pr oduct/                                    <from>/resources/**</from>
                                                         <to>/resources/$1</to>
                         /1234
                                                       </rule>
                     uct
          /ap p/prod                                   <rule>
                                                         <from>/**</from>
                                                         <to>/app/$1</to>
                                                       </rule>
                                                       <outbound-rule>
                                                         <from>/app/**</from>
                                                         <to>/$1</to>
                                                       </outbound-rule>
                                                     </urlrewrite>
                     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Essential Configuration
Scan for controller (and other) components
     <context:component-scan
              base-package="com.habuma.sample.mvc" />



                             Resolve JSP views
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/jsp/"/>
  <property name="suffix" value=".jsp"/>
</bean>




                 Handle annotation-driven request mappings
                                             <mvc:annotation-driven/>



                  E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Use-case-based controllers
                                                                                      VERB!!!
@Controller
public class DisplayProductController {
  @RequestMapping(value="/displayProduct.htm")
  public String showProductBySku(String sku,
      Map<String,Object> model) {
    Product product = // ... lookup product ...
    model.put("product", product);
    return "product";
  }
  // ...
}


        http://host/myApp/displayProduct.htm?sku=1234

            E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Resource-oriented controller
                                                                           Noun
@Controller                                Verb
@RequestMapping("/product")
public class ProductController {
  @RequestMapping(value="/{sku}", method=GET)
  public String showProductBySku(
        @PathVariable String sku,
        Map<String,Object> model) {
    Product product = // ... lookup product ...
    model.put("product", product);
    return "product";
  }
}
              http://host/myApp/product/1234

          E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
HTTP Methods

              GET, DELETE, PUT
                      Idempotent
    Transfers state of resource
                                POST
                Not Idempotent
    Sends data (not nec. state)


     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
PUT vs. POST

                                      PUT
      Used to transfer state to server
  Useful when the resource’s URL is known
                                     POST
        Used to send data to server
 Useful when the resource’s URL is unknown
     or when transferring partial state

          E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Handling DELETE

@Controller
@RequestMapping("/product")
public class ProductController {

    ...

    @RequestMapping(value="/{sku}", method=DELETE)
    public String deleteProduct(
          @PathVariable String sku) {
      // ... delete product ...
      return "redirect:home";
    }
}

                 http://host/myApp/product/1234
             E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Handling PUT
@Controller
@RequestMapping("/product")
public class ProductController {

    ...

    @RequestMapping(value="/{sku}", method=PUT)
    public String saveProduct(
          @PathVariable String sku,
          Product product) {
      // ... save product ...
      return "redirect:/product/" + sku;
    }
}
                 http://host/myApp/product/1234
             E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Handling POST
@Controller
@RequestMapping("/product")
public class ProductController {

    ...

    @RequestMapping(method=POST)
    public String setPrice(String sku,
                           double price) {
      // ... update price ...
      return "redirect:/product/" + sku;
    }
}
                      http://host/myApp/product
                         FORM DATA: sku=1234
                                    price=5.99
             E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Using PUT/DELETE in forms
 Most browsers only support GET and POST
    Spring’s <form:form> supports all
   <form:form method="DELETE"
       action="http://host/myApp/product/1234">
   ...
   </form:form>


                                                             Hidden method field
   <form method="POST"
       action="http://host/myApp/product/1234">
     <input type="hidden" name="_method"
             value="DELETE">
   ...
   </form>
           E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
HiddenHttpMethodFilter
 <filter>
   <filter-name>httpMethodFilter</filter-name>
   <filter-class>
     org.springframework.web.filter.HiddenHttpMethodFilter
   </filter-class>
 </filter>

 <filter-mapping>
   <filter-name>httpMethodFilter</filter-name>
   <url-pattern>/*</url-pattern>
 </filter-mapping>



                                               HiddenHttpMethodFilter
      POST
                                                                                      DELETE
 _method=DELETE




              E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Data representation


                                      PDF                                     RSS/Atom

                         Spring MVC
                            Views
 JSON



                                                                   Excel

        E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Negotiating Content

          Request



        Content
       Negotiating
         View
        Resolver




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Choosing a view

                                 1. Determine the media type
                                     URL path extension/mediaTypes
                                            format parameter
                                              URL path extension/JAF
                                                   HTTP Accept header


                                  2. Find a view resolver that
                                     serves that media type



      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
ContentNegotiatingViewResolver

 <bean class="org.springframework.web.servlet.view.
                              ContentNegotiatingViewResolver">
   <property name="mediaTypes">
     <map>
       <entry key="htm" value="text/html"/>
       <entry key="json" value="application/json"/>
     </map>
   </property>
   <property name="defaultViews">
     <list>
       <bean class="org.springframework.web.servlet.view.json.
                                    MappingJacksonJsonView" />
     </list>
   </property>
 </bean>

 <bean id="spittles"
       class="com.habuma.spitter.mvc.view.SpittlesAtomView"/>



              E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Spring’s new views
        MappingJacksonJsonView
                  MarshallingView
         AbstractAtomFeedView
            AbstractRssFeedView




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
XML Marshalling View


<bean id="oxmMarshaller"
      class="org.springframework.oxm.xstream.XStreamMarshaller" />

<bean id="marshallingHttpMessageConverter"
      class="org.springframework.http.converter.xml.
                                 MarshallingHttpMessageConverter">
  <property name="marshaller" ref="oxmMarshaller" />
  <property name="unmarshaller" ref="oxmMarshaller" />
</bean>




                E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Sample RSS View
 public class SpittlesRssView extends AbstractRssFeedView {

     @Override
     protected List<Item> buildFeedItems(
             Map<String, Object> model,
             HttpServletRequest request,
             HttpServletResponse response) throws Exception {

         @SuppressWarnings("unchecked")
         List<Spittle> spittles = (List<Spittle>) model.get("spittles");
         List<Item> items = new ArrayList<Item>();
         for (Spittle spittle : spittles) {
           Item item = new Item();
           item.setTitle(spittle.getText());
           item.setPubDate(spittle.getWhen());
           item.setAuthor(spittle.getSpitter().getFullName());
           items.add(item);
         }

         return items;
     }
 }


                  E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Sample Atom View
  public class SpittlesAtomView extends AbstractAtomFeedView {

      @Override
      protected List<Entry> buildFeedEntries(
              Map<String, Object> model,
              HttpServletRequest request,
              HttpServletResponse response) throws Exception {

          @SuppressWarnings("unchecked")
          List<Spittle> spittles = (List<Spittle>) model.get("spittles");
          List<Entry> entries = new ArrayList<Entry>();
          for (Spittle spittle : spittles) {
            Entry entry = new Entry();
            entry.setTitle(spittle.getText());
            entry.setCreated(spittle.getWhen());
            entry.setAuthors(asList(spittle.getSpitter().getFullName()));
            entries.add(entry);
          }

          return entries;
      }
  }


                   E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
ETags
   Returns HTTP 304 if content is unmodified
                               if-none-match
                            (MD5 Hash comparison)
                                    Saves bandwidth

<filter>
  <filter-name>etagFilter</filter-name>
  <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>etagFilter</filter-name>
  <servlet-name>spitter</servlet-name>
</filter-mapping>




                   E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
RestTemplate
    In Spring context: (or yes, it could just be new’d up in Java)
    <bean id="restTemplate"
          class="org.springframework.web.client.RestTemplate">




In Java:
RestTemplate rest = (RestTemplate) context.getBean("restTemplate");
Map result = rest.getForObject(
        "http://localhost:8080/mugbooks/book/1.json", Map.class);




                    E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Summary



• Spring provides a flexible web MVC
  framework

• Full support for REST as of Spring 3.0
• Can consume REST services via a template


         E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Thank You

Don’t forget the evals!

More Related Content

PDF
Building RESTful applications using Spring MVC
PPTX
Spring MVC
PDF
Spring mvc
ODP
Java Spring MVC Framework with AngularJS by Google and HTML5
PPTX
Spring Web Services
PDF
Spring Web Services: SOAP vs. REST
PPTX
Implicit object.pptx
KEY
Multi Client Development with Spring
Building RESTful applications using Spring MVC
Spring MVC
Spring mvc
Java Spring MVC Framework with AngularJS by Google and HTML5
Spring Web Services
Spring Web Services: SOAP vs. REST
Implicit object.pptx
Multi Client Development with Spring

What's hot (19)

PPTX
Implicit objects advance Java
PPT
Java Server Pages
PPTX
Integration of Backbone.js with Spring 3.1
PPT
Backbone js
PDF
Jsp & Ajax
PDF
Rest web service_with_spring_hateoas
PPTX
Spring Web Flow. A little flow of happiness.
PPTX
Rest with Java EE 6 , Security , Backbone.js
ODP
springmvc-150923124312-lva1-app6892
PDF
the Spring 4 update
PDF
jQuery and Rails: Best Friends Forever
ODP
Spray - Build RESTfull services in scala
PPT
jQuery and AJAX with Rails
PDF
Java Configuration Deep Dive with Spring
PPTX
Spring Web Webflow
PDF
JavaServer Faces 2.0 - JavaOne India 2011
KEY
An Introduction to Ruby on Rails
PPTX
Jsp (java server page)
KEY
MVC on the server and on the client
Implicit objects advance Java
Java Server Pages
Integration of Backbone.js with Spring 3.1
Backbone js
Jsp & Ajax
Rest web service_with_spring_hateoas
Spring Web Flow. A little flow of happiness.
Rest with Java EE 6 , Security , Backbone.js
springmvc-150923124312-lva1-app6892
the Spring 4 update
jQuery and Rails: Best Friends Forever
Spray - Build RESTfull services in scala
jQuery and AJAX with Rails
Java Configuration Deep Dive with Spring
Spring Web Webflow
JavaServer Faces 2.0 - JavaOne India 2011
An Introduction to Ruby on Rails
Jsp (java server page)
MVC on the server and on the client
Ad

Viewers also liked (20)

PDF
What's new in Spring 3?
PDF
SpringMVC
PPTX
Design REST-ful Web Service
PDF
Rest with Spring
PPTX
Designing REST services with Spring MVC
DOCX
k-means Clustering and Custergram with R
PPTX
Program_Cluster_Analysis
KEY
Modular Java - OSGi
PDF
That old Spring magic has me in its SpEL
PDF
Spring boot
PDF
Boot It Up
PPT
Spring MVC
PPT
Spring Boot in Action
PDF
Spring MVC
PDF
Spring Framework 4.0 to 4.1
PDF
slides Céline Beji
PDF
Introduction to Spring Boot!
PPTX
Spring Boot Tutorial
PDF
Implantación de Geoportales con soporte técnico profesionalizado en softwar...
ODP
WP-Polls en castellano
What's new in Spring 3?
SpringMVC
Design REST-ful Web Service
Rest with Spring
Designing REST services with Spring MVC
k-means Clustering and Custergram with R
Program_Cluster_Analysis
Modular Java - OSGi
That old Spring magic has me in its SpEL
Spring boot
Boot It Up
Spring MVC
Spring Boot in Action
Spring MVC
Spring Framework 4.0 to 4.1
slides Céline Beji
Introduction to Spring Boot!
Spring Boot Tutorial
Implantación de Geoportales con soporte técnico profesionalizado en softwar...
WP-Polls en castellano
Ad

Similar to Spring Mvc Rest (20)

PDF
Codeigniter : Custom Routing - Manipulate Uri
PDF
Choosing a Javascript Framework
PDF
Doing REST Right
PDF
Web applications with Catalyst
PPTX
Basics of AngularJS
PDF
Jlook web ui framework
PDF
The Rails Way
PPT
Angular data binding by Soft Solutions4U
PDF
Ride on the Fast Track of Web with Ruby on Rails- Part 2
PPTX
Overview of RESTful web services
PPTX
PDF
XamarinとAWSをつないでみた話
PDF
Make your App Frontend Compatible
PDF
Spca2014 hillier 3rd party_javascript_libraries
PDF
Rich Portlet Development in uPortal
PPTX
Camel as a_glue
PDF
AngularJS Basic Training
DOCX
Sharing Data between controllers in different ways.
DOCX
Different way to share data between controllers in angular js
KEY
Rest experience-report
Codeigniter : Custom Routing - Manipulate Uri
Choosing a Javascript Framework
Doing REST Right
Web applications with Catalyst
Basics of AngularJS
Jlook web ui framework
The Rails Way
Angular data binding by Soft Solutions4U
Ride on the Fast Track of Web with Ruby on Rails- Part 2
Overview of RESTful web services
XamarinとAWSをつないでみた話
Make your App Frontend Compatible
Spca2014 hillier 3rd party_javascript_libraries
Rich Portlet Development in uPortal
Camel as a_glue
AngularJS Basic Training
Sharing Data between controllers in different ways.
Different way to share data between controllers in angular js
Rest experience-report

Spring Mvc Rest

  • 1. Building RESTful applications with Spring MVC Craig Walls
  • 2. Who Am I? Java, Spring, and OSGi fanatic Principal Consultant with Improving Author XDoclet in Action (Manning) Spring in Action (Manning) Modular Java (Pragmatic Bookshelf) E-mail: [email protected] Blog: http://www.springinaction.com Twitter: @habuma Slides: http://www.slideshare.net/habuma
  • 3. What REST is NOT!!! Web Services with URLs E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 4. It’s about Resources Things, not actions Requests, not demands Resources, not services Transfer of state, not RPC E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 5. The Pillars of REST Resources URIs/URLs HTTP Methods Representations E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 6. The Pillars of REST Resources Produced as model data in Spring MVC Controllers URIs/URLs Supported in handler methods by @PathParam HTTP Methods @RequestMapping, HiddenHttpMethodFilter, <form:form> Representations Rendered by view resolvers HTML, XML, JSON, RSS, Atom, PDF, Excel, etc. Negotiated by ContentNegotiatingViewResolver E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 7. Identifying Resources E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 8. Demanding URLs Direct Imperative Resource identifier Command is pushed into a query parameter http://www.somestore.com/displayProduct?sku=1234 Very service-y Not very cacheable or search engine friendly E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 9. Resourceful URLs The focus is on the product, We’re requesting not the action a product’s info http://www.somestore.com/product/1234 Cacheable This URL also identifies a product (within a context) E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 10. Spring MVC overview E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 11. DispatcherServlet In /WEB-INF/web.xml <servlet> <servlet-name>spitter</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spitter</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 12. ContextLoaderListener In /WEB-INF/web.xml <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spitter-security.xml classpath:service-context.xml classpath:persistence-context.xml classpath:dataSource-context.xml classpath:setup-context.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 13. UrlRewriteFilter In /WEB-INF/web.xml <filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class> org.tuckey.web.filters.urlrewrite.UrlRewriteFilter </filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> In /WEB-INF/urlrewrite.xml <urlrewrite default-match-type="wildcard"> <rule> 1234 /pr oduct/ <from>/resources/**</from> <to>/resources/$1</to> /1234 </rule> uct /ap p/prod <rule> <from>/**</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/**</from> <to>/$1</to> </outbound-rule> </urlrewrite> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 14. Essential Configuration Scan for controller (and other) components <context:component-scan base-package="com.habuma.sample.mvc" /> Resolve JSP views <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> Handle annotation-driven request mappings <mvc:annotation-driven/> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 15. Use-case-based controllers VERB!!! @Controller public class DisplayProductController { @RequestMapping(value="/displayProduct.htm") public String showProductBySku(String sku, Map<String,Object> model) { Product product = // ... lookup product ... model.put("product", product); return "product"; } // ... } http://host/myApp/displayProduct.htm?sku=1234 E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 16. Resource-oriented controller Noun @Controller Verb @RequestMapping("/product") public class ProductController { @RequestMapping(value="/{sku}", method=GET) public String showProductBySku( @PathVariable String sku, Map<String,Object> model) { Product product = // ... lookup product ... model.put("product", product); return "product"; } } http://host/myApp/product/1234 E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 17. HTTP Methods GET, DELETE, PUT Idempotent Transfers state of resource POST Not Idempotent Sends data (not nec. state) E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 18. PUT vs. POST PUT Used to transfer state to server Useful when the resource’s URL is known POST Used to send data to server Useful when the resource’s URL is unknown or when transferring partial state E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 19. Handling DELETE @Controller @RequestMapping("/product") public class ProductController { ... @RequestMapping(value="/{sku}", method=DELETE) public String deleteProduct( @PathVariable String sku) { // ... delete product ... return "redirect:home"; } } http://host/myApp/product/1234 E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 20. Handling PUT @Controller @RequestMapping("/product") public class ProductController { ... @RequestMapping(value="/{sku}", method=PUT) public String saveProduct( @PathVariable String sku, Product product) { // ... save product ... return "redirect:/product/" + sku; } } http://host/myApp/product/1234 E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 21. Handling POST @Controller @RequestMapping("/product") public class ProductController { ... @RequestMapping(method=POST) public String setPrice(String sku, double price) { // ... update price ... return "redirect:/product/" + sku; } } http://host/myApp/product FORM DATA: sku=1234 price=5.99 E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 22. Using PUT/DELETE in forms Most browsers only support GET and POST Spring’s <form:form> supports all <form:form method="DELETE" action="http://host/myApp/product/1234"> ... </form:form> Hidden method field <form method="POST" action="http://host/myApp/product/1234"> <input type="hidden" name="_method" value="DELETE"> ... </form> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 23. HiddenHttpMethodFilter <filter> <filter-name>httpMethodFilter</filter-name> <filter-class> org.springframework.web.filter.HiddenHttpMethodFilter </filter-class> </filter> <filter-mapping> <filter-name>httpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> HiddenHttpMethodFilter POST DELETE _method=DELETE E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 24. Data representation PDF RSS/Atom Spring MVC Views JSON Excel E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 25. Negotiating Content Request Content Negotiating View Resolver E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 26. Choosing a view 1. Determine the media type URL path extension/mediaTypes format parameter URL path extension/JAF HTTP Accept header 2. Find a view resolver that serves that media type E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 27. ContentNegotiatingViewResolver <bean class="org.springframework.web.servlet.view. ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="htm" value="text/html"/> <entry key="json" value="application/json"/> </map> </property> <property name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view.json. MappingJacksonJsonView" /> </list> </property> </bean> <bean id="spittles" class="com.habuma.spitter.mvc.view.SpittlesAtomView"/> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 28. Spring’s new views MappingJacksonJsonView MarshallingView AbstractAtomFeedView AbstractRssFeedView E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 29. XML Marshalling View <bean id="oxmMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller" /> <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml. MarshallingHttpMessageConverter"> <property name="marshaller" ref="oxmMarshaller" /> <property name="unmarshaller" ref="oxmMarshaller" /> </bean> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 30. Sample RSS View public class SpittlesRssView extends AbstractRssFeedView { @Override protected List<Item> buildFeedItems( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { @SuppressWarnings("unchecked") List<Spittle> spittles = (List<Spittle>) model.get("spittles"); List<Item> items = new ArrayList<Item>(); for (Spittle spittle : spittles) { Item item = new Item(); item.setTitle(spittle.getText()); item.setPubDate(spittle.getWhen()); item.setAuthor(spittle.getSpitter().getFullName()); items.add(item); } return items; } } E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 31. Sample Atom View public class SpittlesAtomView extends AbstractAtomFeedView { @Override protected List<Entry> buildFeedEntries( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { @SuppressWarnings("unchecked") List<Spittle> spittles = (List<Spittle>) model.get("spittles"); List<Entry> entries = new ArrayList<Entry>(); for (Spittle spittle : spittles) { Entry entry = new Entry(); entry.setTitle(spittle.getText()); entry.setCreated(spittle.getWhen()); entry.setAuthors(asList(spittle.getSpitter().getFullName())); entries.add(entry); } return entries; } } E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 32. ETags Returns HTTP 304 if content is unmodified if-none-match (MD5 Hash comparison) Saves bandwidth <filter> <filter-name>etagFilter</filter-name> <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class> </filter> <filter-mapping> <filter-name>etagFilter</filter-name> <servlet-name>spitter</servlet-name> </filter-mapping> E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 33. RestTemplate In Spring context: (or yes, it could just be new’d up in Java) <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> In Java: RestTemplate rest = (RestTemplate) context.getBean("restTemplate"); Map result = rest.getForObject( "http://localhost:8080/mugbooks/book/1.json", Map.class); E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma
  • 34. Summary • Spring provides a flexible web MVC framework • Full support for REST as of Spring 3.0 • Can consume REST services via a template E-mail: [email protected] Blog: http://www.springinaction.com Twitter: habuma