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

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: craig@habuma.com Blog: http://www.springinaction.com Twitter: @habuma Slides: http://www.slideshare.net/habuma
  • 3. What REST is NOT!!! Web Services with URLs E-mail: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 5. The Pillars of REST Resources URIs/URLs HTTP Methods Representations E-mail: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 7. Identifying Resources E-mail: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 10. Spring MVC overview E-mail: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 24. Data representation PDF RSS/Atom Spring MVC Views JSON Excel E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 25. Negotiating Content Request Content Negotiating View Resolver E-mail: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  • 28. Spring’s new views MappingJacksonJsonView MarshallingView AbstractAtomFeedView AbstractRssFeedView E-mail: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com 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: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma