Your SlideShare is downloading. ×
0
What’s New in
  Spring 3
Who Am I?




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Who Am I?
     Java, Spring, and OSGi fanatic




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Tw...
Who Am I?
      Java, Spring, and OSGi fanatic
   Principal Consultant with Improving




      E-mail: craig@habuma.com  ...
Who Am I?
      Java, Spring, and OSGi fanatic
   Principal Consultant with Improving
                                   A...
Who Am I?
      Java, Spring, and OSGi fanatic
   Principal Consultant with Improving
                                   A...
Where we’ve
   been

Spring: This is your life!
Evolution of Spring




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Evolution of Spring
      Spring 1.x
 <bean class="...">
 </bean>




         E-mail: craig@habuma.com   Blog: http://www...
Evolution of Spring
      Spring 1.x
 <bean class="...">
 </bean>
                                                        ...
Evolution of Spring
      Spring 1.x
 <bean class="...">
 </bean>
                                                        ...
Evolution of Spring
      Spring 1.x
 <bean class="...">
 </bean>
                                                        ...
Evolution of Spring
      Spring 1.x
 <bean class="...">
 </bean>
                                                        ...
Spring 1.0




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


              Dependency injection




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com  ...
Spring 1.0


              Dependency injection

      POJO-oriented development




      E-mail: craig@habuma.com   Blog...
Spring 1.0


              Dependency injection

      POJO-oriented development

    Declarative AOP and transactions



...
Spring 1.0


              Dependency injection

      POJO-oriented development

    Declarative AOP and transactions

  ...
Spring 2.0




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Spring 2.0
              Problem-specific XML




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Tw...
Spring 2.0
              Problem-specific XML

          Extensible configuration




      E-mail: craig@habuma.com   Blog:...
Spring 2.0
              Problem-specific XML

          Extensible configuration

                          Bean scoping


...
Spring 2.0
              Problem-specific XML

          Extensible configuration

                          Bean scoping

 ...
Spring 2.0
              Problem-specific XML

          Extensible configuration

                          Bean scoping

 ...
Spring 2.0
              Problem-specific XML

          Extensible configuration

                          Bean scoping

 ...
Spring 2.5




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


         Annotation-driven wiring




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   ...
Spring 2.5


         Annotation-driven wiring

     Automatic bean configuration




      E-mail: craig@habuma.com   Blog...
Spring 2.5


           Annotation-driven wiring

       Automatic bean configuration

   New annotation-driven MVC framewo...
Spring 2.5


           Annotation-driven wiring

       Automatic bean configuration

   New annotation-driven MVC framewo...
Spring 1.0




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Spring 1.0
<bean id="linus"
      class="com.springinaction.peanuts.Linus">
  <property name="blanket">
    <ref bean="bla...
Spring 1.1




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


<bean id="linus"
      class="com.springinaction.peanuts.Linus">
  <property name="blanket" ref="blanket" />
...
Spring 2.0




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


<bean id="linus"
      class="com.springinaction.peanuts.Linus"
      p:blanket-ref="blanket" />

<bean id="b...
Spring 2.5




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



<context:component-scan
   base-package="com.springinaction.peanuts" />

<bean id="blanket"
      class="com...
Annotation-Driven Wiring




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Annotation-Driven Wiring

    Java:




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: ha...
Annotation-Driven Wiring
                             @Component
                             public class Linus {

    Ja...
Annotation-Driven Wiring
                             @Component
                             public class Linus {

    Ja...
Annotation-Driven Wiring
                                      @Component
                                      public cla...
What’s new in
 Spring 3?
Spring Expression Language




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Spring Expression Language
  Wires values evaluated from expressions
      Works in XML and annotations




         E-mai...
Spring Expression Language
  Wires values evaluated from expressions
        Works in XML and annotations



<bean class="...
Spring Expression Language
  Wires values evaluated from expressions
      Works in XML and annotations
        @Component...
Expression variables




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

                        Any bean ID




      E-mail: craig@habuma.com   Blog: http://www.springinac...
Expression variables

                        Any bean ID
                 systemProperties




      E-mail: craig@habuma...
Expression variables

                        Any bean ID
                 systemProperties

      Scope/Context-specific.....
SpEL examples




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
SpEL examples
     Referencing bean properties




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   ...
SpEL examples
     Referencing bean properties
             "#{settingBean.databaseUrl}"




      E-mail: craig@habuma.co...
SpEL examples
     Referencing bean properties
             "#{settingBean.databaseUrl}"


    Referencing system properti...
SpEL examples
     Referencing bean properties
             "#{settingBean.databaseUrl}"


    Referencing system properti...
SpEL examples
     Referencing bean properties
             "#{settingBean.databaseUrl}"


    Referencing system properti...
SpEL examples
     Referencing bean properties
               "#{settingBean.databaseUrl}"


    Referencing system proper...
SpEL examples
     Referencing bean properties
               "#{settingBean.databaseUrl}"


    Referencing system proper...
SpEL examples
     Referencing bean properties
               "#{settingBean.databaseUrl}"


    Referencing system proper...
SpEL examples
     Referencing bean properties
               "#{settingBean.databaseUrl}"


    Referencing system proper...
SpEL examples
         Referencing bean properties
                   "#{settingBean.databaseUrl}"


        Referencing s...
One more SpEL example




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
One more SpEL example




    Collection projection




      E-mail: craig@habuma.com   Blog: http://www.springinaction.c...
One more SpEL example




    Collection projection
     "#{snoopyPersonas.![name]}"




      E-mail: craig@habuma.com   ...
@PathVariable




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


                                      Spring 2.5:
 @Controller
 public class SpittleListController {
   @R...
@PathVariable


                                      Spring 3.0:
 @Controller
 public class SpittleListController {
   @R...
@RequestHeader




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


                               Spring 2.5:
   @Controller
   public class HomeController {
     @RequestM...
@RequestHeader


                                      Spring 3.0:
 @Controller
 public class HomeController {
   @Request...
@CookieValue




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


                               Spring 2.5:
   @Controller
   public class HomeController {
     @RequestMap...
@CookieValue


                                      Spring 3.0:
 @Controller
 public class HomeController {
   @RequestMa...
default values




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


              New for @RequestParam
  @RequestParam(value="productId", defaultValue="1234") String produc...
default values


              New for @RequestParam
  @RequestParam(value="productId", defaultValue="1234") String produc...
default values


                New for @RequestParam
   @RequestParam(value="productId", defaultValue="1234") String pro...
default values


                New for @RequestParam
   @RequestParam(value="productId", defaultValue="1234") String pro...
<spring:url>




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
<spring:url>
                          New JSP tag
    Generates context-senstive URL




       E-mail: craig@habuma.com ...
<spring:url>
                               New JSP tag
        Generates context-senstive URL

 <spring:url value="/spitt...
Declarative Validation




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


       Based on JSR-303 validators




      E-mail: craig@habuma.com   Blog: http://www.springin...
Declarative Validation


          Based on JSR-303 validators

 Hibernate Validator as default implementation




       ...
Declarative Validation


          Based on JSR-303 validators

 Hibernate Validator as default implementation

   Primari...
Declarative Validation


          Based on JSR-303 validators

 Hibernate Validator as default implementation

   Primari...
More on validation
                                                        @Column(name="spittleText")
                   ...
ETag Support




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
ETag Support
      ShallowEtagHeaderFilter




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitt...
ETag Support
          ShallowEtagHeaderFilter
    <filter>
      <filter-name>etagFilter</filter-name>
      <filter-clas...
ETag Support
             ShallowEtagHeaderFilter
       <filter>
         <filter-name>etagFilter</filter-name>
         ...
HTTP Method Conversion




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
HTTP Method Conversion
     HTTP defines four methods:
         GET, POST, DELETE, and PUT




      E-mail: craig@habuma.c...
HTTP Method Conversion
     HTTP defines four methods:
         GET, POST, DELETE, and PUT
         HTML only supports 2:
 ...
HTTP Method Conversion
         HTTP defines four methods:
             GET, POST, DELETE, and PUT
             HTML only s...
HTTP Method Conversion
         HTTP defines four methods:
              GET, POST, DELETE, and PUT
              HTML only...
HTTP Methods in Spring MVC




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
HTTP Methods in Spring MVC
 Spring MVC form tags support hidden HTTP
                 methods




         E-mail: craig@h...
HTTP Methods in Spring MVC
  Spring MVC form tags support hidden HTTP
                  methods
<form:form method="delete"...
HTTP Methods in Spring MVC
  Spring MVC form tags support hidden HTTP
                  methods
<form:form method="delete"...
HTTP Methods in Spring MVC
  Spring MVC form tags support hidden HTTP
                  methods
<form:form method="delete"...
Content negotiation




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

      ContentNegotiatingViewResolver
 Chooses a view based on HTTP Accepts header, JAF
  content type...
Content negotiation

      ContentNegotiatingViewResolver
 Chooses a view based on HTTP Accepts header, JAF
  content type...
REST consumption




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
REST consumption
                 New RestTemplate




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com...
REST consumption
                                  New RestTemplate

Read
RestTemplate template = new RestTemplate();
temp...
REST consumption
                                  New RestTemplate

Read
RestTemplate template = new RestTemplate();
temp...
REST consumption
                                  New RestTemplate

Read
RestTemplate template = new RestTemplate();
temp...
JavaConfig




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
JavaConfig
    @Configuration
    public class PeanutsConfiguration {

        @Bean
        public Linus linus() {
      ...
JavaConfig in Components




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
JavaConfig in Components
      @Component
      public class KiteEatingTree
         implements DeciduousTree {

         ...
Asynchronous Methods




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

    Annotate a bean method
    @Async
    public void backgroundJob()
    { ... }




     E-mail: c...
Asynchronous Methods

    Annotate a bean method
    @Async
    public void backgroundJob()
    { ... }




     In Spring...
Scheduling




     E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Scheduling
    @Scheduled(fixedDelay=3000L)
      public void ping() { ... }




       E-mail: craig@habuma.com   Blog: h...
Scheduling
    @Scheduled(fixedDelay=3000L)
      public void ping() { ... }



    @Scheduled(fixedRate=3000L)
      publ...
Scheduling
    @Scheduled(fixedDelay=3000L)
      public void ping() { ... }



    @Scheduled(fixedRate=3000L)
      publ...
Miscellaneous




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



  Object-to-XML mapping from Spring-WS




       E-mail: craig@habuma.com   Blog: http://www.springinact...
Miscellaneous



  Object-to-XML mapping from Spring-WS
  Embracing Java 5 (generics, autoboxing,
            annotations,...
What’s going
   away
Bye bye




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

   Spring MVC controller hierarchy                                                    (deprecated)




       E-m...
Bye bye

   Spring MVC controller hierarchy                                                    (deprecated)



           ...
Bye bye

   Spring MVC controller hierarchy                                                    (deprecated)



           ...
Bye bye

   Spring MVC controller hierarchy                                                    (deprecated)



           ...
Bye bye

   Spring MVC controller hierarchy                                                    (deprecated)



           ...
Bye bye

   Spring MVC controller hierarchy                                                    (deprecated)



           ...
Bye bye




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
What else?
Keep your eye on...




      E-mail: craig@habuma.com   Blog: http://www.springinaction.com   Twitter: habuma
Keep your eye on...
             Spring Web Flow 2.0




      E-mail: craig@habuma.com   Blog: http://www.springinaction....
Keep your eye on...
             Spring Web Flow 2.0
                    Spring BlazeDS




      E-mail: craig@habuma.com...
Keep your eye on...
             Spring Web Flow 2.0
                    Spring BlazeDS
               Spring Security 3.0...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
Keep your eye on...
               Spring Web Flow 2.0
                      Spring BlazeDS
                 Spring Securi...
In summary...
Spring simplifies




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


   Spring’s initial focus was to simplify
              enterprise Java




        E-mail: craig@habu...
Spring simplifies


   Spring’s initial focus was to simplify
              enterprise Java
   Now simplification efforts t...
Spring simplifies


     Spring’s initial focus was to simplify
                enterprise Java
    Now simplification effo...
Spring simplifies


     Spring’s initial focus was to simplify
                enterprise Java
    Now simplification effo...
Spring simplifies




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

Don’t forget the evals!
Upcoming SlideShare
Loading in...5
×

What's new in Spring 3?

11,602

Published on

Craig Walls' presentation on what's to come in Spring 3 as given at Dallas Tech Fest 2009 in Frisco, TX, June 19, 2009.

Published in: Technology, Business
1 Comment
16 Likes
Statistics
Notes
No Downloads
Views
Total Views
11,602
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
483
Comments
1
Likes
16
Embeds 0
No embeds

No notes for slide

Transcript of "What's new in Spring 3?"

  1. 1. What’s New in Spring 3
  2. 2. Who Am I? E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  3. 3. Who Am I? Java, Spring, and OSGi fanatic E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  4. 4. Who Am I? Java, Spring, and OSGi fanatic Principal Consultant with Improving E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  5. 5. 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
  6. 6. 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
  7. 7. Where we’ve been Spring: This is your life!
  8. 8. Evolution of Spring E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  9. 9. Evolution of Spring Spring 1.x <bean class="..."> </bean> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  10. 10. Evolution of Spring Spring 1.x <bean class="..."> </bean> Spring 2.0 <tx:/> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  11. 11. Evolution of Spring Spring 1.x <bean class="..."> </bean> Spring 2.0 <tx:/> Spring 2.5 @Component @Autowired E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  12. 12. Evolution of Spring Spring 1.x <bean class="..."> </bean> Spring 2.0 <tx:/> Spring 2.5 @Component @Autowired Spring 3.0 ? E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  13. 13. Evolution of Spring Spring 1.x <bean class="..."> </bean> Spring 2.0 <tx:/> Spring 2.5 @Component @Autowired Spring 3.0 ? E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  14. 14. Spring 1.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  15. 15. Spring 1.0 Dependency injection E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  16. 16. Spring 1.0 Dependency injection POJO-oriented development E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  17. 17. Spring 1.0 Dependency injection POJO-oriented development Declarative AOP and transactions E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  18. 18. Spring 1.0 Dependency injection POJO-oriented development Declarative AOP and transactions MVC framework E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  19. 19. Spring 2.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  20. 20. Spring 2.0 Problem-specific XML E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  21. 21. Spring 2.0 Problem-specific XML Extensible configuration E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  22. 22. Spring 2.0 Problem-specific XML Extensible configuration Bean scoping E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  23. 23. Spring 2.0 Problem-specific XML Extensible configuration Bean scoping Groovy, JRuby, and BeanShell E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  24. 24. Spring 2.0 Problem-specific XML Extensible configuration Bean scoping Groovy, JRuby, and BeanShell JSP tag library E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  25. 25. Spring 2.0 Problem-specific XML Extensible configuration Bean scoping Groovy, JRuby, and BeanShell JSP tag library Java 5 autoboxing and generics E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  26. 26. Spring 2.5 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  27. 27. Spring 2.5 Annotation-driven wiring E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  28. 28. Spring 2.5 Annotation-driven wiring Automatic bean configuration E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  29. 29. Spring 2.5 Annotation-driven wiring Automatic bean configuration New annotation-driven MVC framework E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  30. 30. Spring 2.5 Annotation-driven wiring Automatic bean configuration New annotation-driven MVC framework JUnit 4-based integration testing E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  31. 31. Spring 1.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  32. 32. Spring 1.0 <bean id="linus" class="com.springinaction.peanuts.Linus"> <property name="blanket"> <ref bean="blanket" /> </property> </bean> <bean id="blanket" class="com.springinaction.peanuts.Blanket"> <property name="color"> <value>blue</value> </property> </bean> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  33. 33. Spring 1.1 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  34. 34. Spring 1.1 <bean id="linus" class="com.springinaction.peanuts.Linus"> <property name="blanket" ref="blanket" /> </bean> <bean id="blanket" class="com.springinaction.peanuts.Blanket"> <property name="color" value="blue" /> </bean> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  35. 35. Spring 2.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  36. 36. Spring 2.0 <bean id="linus" class="com.springinaction.peanuts.Linus" p:blanket-ref="blanket" /> <bean id="blanket" class="com.springinaction.peanuts.Blanket" p:color="blue" /> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  37. 37. Spring 2.5 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  38. 38. Spring 2.5 <context:component-scan base-package="com.springinaction.peanuts" /> <bean id="blanket" class="com.springinaction.peanuts.Blanket" p:color="blue" /> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  39. 39. Annotation-Driven Wiring E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  40. 40. Annotation-Driven Wiring Java: E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  41. 41. Annotation-Driven Wiring @Component public class Linus { Java: @Autowired private Blanket blanket; public Blanket getBlanket() { return blanket; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  42. 42. Annotation-Driven Wiring @Component public class Linus { Java: @Autowired private Blanket blanket; public Blanket getBlanket() { return blanket; } } Spring : Context E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  43. 43. Annotation-Driven Wiring @Component public class Linus { Java: @Autowired private Blanket blanket; public Blanket getBlanket() { return blanket; } } <context:component-scan Spring base-package="com.springinaction.peanuts" /> : Context E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  44. 44. What’s new in Spring 3?
  45. 45. Spring Expression Language E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  46. 46. Spring Expression Language Wires values evaluated from expressions Works in XML and annotations E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  47. 47. Spring Expression Language Wires values evaluated from expressions Works in XML and annotations <bean class="com.springinaction.peanuts.Blanket"> <property name="color" value="#{someOtherBean.color}" /> </bean> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  48. 48. Spring Expression Language Wires values evaluated from expressions Works in XML and annotations @Component public class Blanket { @Value("#{someOtherBean.color}") private String color; public Blanket() { } // ... } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  49. 49. Expression variables E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  50. 50. Expression variables Any bean ID E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  51. 51. Expression variables Any bean ID systemProperties E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  52. 52. Expression variables Any bean ID systemProperties Scope/Context-specific... contextProperties contextAttributes request session E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  53. 53. SpEL examples E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  54. 54. SpEL examples Referencing bean properties E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  55. 55. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  56. 56. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  57. 57. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  58. 58. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  59. 59. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth "#{systemProperties.favoriteColor == 'red'}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  60. 60. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth "#{systemProperties.favoriteColor == 'red'}" Using static methods E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  61. 61. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth "#{systemProperties.favoriteColor == 'red'}" Using static methods "#{T(java.lang.Math).random()}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  62. 62. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth "#{systemProperties.favoriteColor == 'red'}" Using static methods "#{T(java.lang.Math).random()}" Templated Strings E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  63. 63. SpEL examples Referencing bean properties "#{settingBean.databaseUrl}" Referencing system properties "#{systemProperties.favoriteColor}" Evaluating truth "#{systemProperties.favoriteColor == 'red'}" Using static methods "#{T(java.lang.Math).random()}" Templated Strings "The time is #{T(java.lang.System).currentTimeMillis()}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  64. 64. One more SpEL example E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  65. 65. One more SpEL example Collection projection E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  66. 66. One more SpEL example Collection projection "#{snoopyPersonas.![name]}" E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  67. 67. @PathVariable E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  68. 68. @PathVariable Spring 2.5: @Controller public class SpittleListController { @RequestMapping("/spittleList.htm") public String displaySpittleList(@RequestParam("username") String userName) { // ... return "spittleList"; } } http://localhost:8080/spitter/spittleList.htm?username=habuma E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  69. 69. @PathVariable Spring 3.0: @Controller public class SpittleListController { @RequestMapping("/{username}/list") public String displaySpittleList(@PathVariable("username") String userName) { // ... return "spittleList"; } } http://localhost:8080/spitter/habuma/list E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  70. 70. @RequestHeader E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  71. 71. @RequestHeader Spring 2.5: @Controller public class HomeController { @RequestMapping("/home") public String displayHomePage(HttpServletRequest request) { String userAgent = request.getHeader("User-Agent"); // ... return "home"; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  72. 72. @RequestHeader Spring 3.0: @Controller public class HomeController { @RequestMapping("/home") public String displayHomePage(@RequestHeader("User-Agent") String userAgent) { // ... return "home"; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  73. 73. @CookieValue E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  74. 74. @CookieValue Spring 2.5: @Controller public class HomeController { @RequestMapping("/home") public String displayHomePage(HttpServletRequest request) { String lastVisit = "never"; Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if("LastVisit".equals(cookie.getName())) { lastVisit = cookie.getValue(); } } // ... return "home"; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  75. 75. @CookieValue Spring 3.0: @Controller public class HomeController { @RequestMapping("/home") public String displayHomePage(@CookieValue("LastVisit") String lastVisit) { // ... return "home"; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  76. 76. default values E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  77. 77. default values New for @RequestParam @RequestParam(value="productId", defaultValue="1234") String productId E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  78. 78. default values New for @RequestParam @RequestParam(value="productId", defaultValue="1234") String productId Standard issue for @RequestHeader and @CookieValue E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  79. 79. default values New for @RequestParam @RequestParam(value="productId", defaultValue="1234") String productId Standard issue for @RequestHeader and @CookieValue @RequestHeader(value="User-Agent", defaultValue="1234") String userAgent E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  80. 80. default values New for @RequestParam @RequestParam(value="productId", defaultValue="1234") String productId Standard issue for @RequestHeader and @CookieValue @RequestHeader(value="User-Agent", defaultValue="1234") String userAgent @CookieValue(value="LastVisit", defaultValue="1234") String lastVisit E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  81. 81. <spring:url> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  82. 82. <spring:url> New JSP tag Generates context-senstive URL E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  83. 83. <spring:url> New JSP tag Generates context-senstive URL <spring:url value="/spittle/{id}/edit" var="editUrl" escapeXml="true"> <spring:param name="id" value="${spittle.id}" /> </spring:url> <a href="${editUrl}">Do something</a> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  84. 84. Declarative Validation E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  85. 85. Declarative Validation Based on JSR-303 validators E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  86. 86. Declarative Validation Based on JSR-303 validators Hibernate Validator as default implementation E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  87. 87. Declarative Validation Based on JSR-303 validators Hibernate Validator as default implementation Primarily used to validate inputs to Spring MVC controllers E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  88. 88. Declarative Validation Based on JSR-303 validators Hibernate Validator as default implementation Primarily used to validate inputs to Spring MVC controllers Configured automatically with <mvc:annotation-driven/> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  89. 89. More on validation @Column(name="spittleText") @NotNull In entity @Size(min=1, max=140) class public String getText() { return this.text; } @RequestMapping(method=POST) public String addSpittle( @Valid Spittle spittle, BindingResult result) { if(result.hasErrors()) { return "spittle/form"; In Spring MVC } controller spitterService.addSpittle(spittle); return "redirect:/home"; } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  90. 90. ETag Support E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  91. 91. ETag Support ShallowEtagHeaderFilter E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  92. 92. ETag Support ShallowEtagHeaderFilter <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
  93. 93. ETag Support ShallowEtagHeaderFilter <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> Returns HTTP 304 if content is unmodified if-none-match (MD5 Hash comparison) Saves bandwidth E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  94. 94. HTTP Method Conversion E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  95. 95. HTTP Method Conversion HTTP defines four methods: GET, POST, DELETE, and PUT E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  96. 96. HTTP Method Conversion HTTP defines four methods: GET, POST, DELETE, and PUT HTML only supports 2: GET and POST E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  97. 97. HTTP Method Conversion HTTP defines four methods: GET, POST, DELETE, and PUT HTML only supports 2: GET and POST Spring 3’s HiddenHttpMethodFilter fixes that E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  98. 98. HTTP Method Conversion HTTP defines four methods: GET, POST, DELETE, and PUT HTML only supports 2: GET and POST Spring 3’s HiddenHttpMethodFilter fixes that <filter> <filter-name>hiddenMethodFilter</filter-name> <filter-class> org.springframework.web.filter.HiddenHttpMethodFilter </filter-class> </filter> <filter-mapping> <filter-name>hiddenMethodFilter</filter-name> <servlet-name>spitter</servlet-name> </filter-mapping> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  99. 99. HTTP Methods in Spring MVC E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  100. 100. HTTP Methods in Spring MVC Spring MVC form tags support hidden HTTP methods E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  101. 101. HTTP Methods in Spring MVC Spring MVC form tags support hidden HTTP methods <form:form method="delete"> <p class="submit"><input type="submit" value="Delete Spittle"/></p> </form:form> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  102. 102. HTTP Methods in Spring MVC Spring MVC form tags support hidden HTTP methods <form:form method="delete"> <p class="submit"><input type="submit" value="Delete Spittle"/></p> </form:form> Controllers can handle all HTTP methods E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  103. 103. HTTP Methods in Spring MVC Spring MVC form tags support hidden HTTP methods <form:form method="delete"> <p class="submit"><input type="submit" value="Delete Spittle"/></p> </form:form> Controllers can handle all HTTP methods @RequestMapping(method = RequestMethod.DELETE) public String deleteSpittle(@PathVariable long spittleId) { spittleService.deleteSpittle(spittleId); return "redirect:/home"; } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  104. 104. Content negotiation E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  105. 105. Content negotiation ContentNegotiatingViewResolver Chooses a view based on HTTP Accepts header, JAF content type, format parameter, or request path extension E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  106. 106. Content negotiation ContentNegotiatingViewResolver Chooses a view based on HTTP Accepts header, JAF content type, format parameter, or request path extension New view resolvers AbstractAtomFeedView AbstractRssFeedView MarshallingView MappingJacksonJsonView E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  107. 107. REST consumption E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  108. 108. REST consumption New RestTemplate E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  109. 109. REST consumption New RestTemplate Read RestTemplate template = new RestTemplate(); template.getForObject("http://localhost:8080/spitter/users/${id}", String.class, userId); E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  110. 110. REST consumption New RestTemplate Read RestTemplate template = new RestTemplate(); template.getForObject("http://localhost:8080/spitter/users/${id}", String.class, userId); Create RestTemplate template = new RestTemplate(); SpitterUser user = new SpitterUser(userName, password); template.postForLocation("http://localhost:8080/spitter/users/${id}", user, userId); E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  111. 111. REST consumption New RestTemplate Read RestTemplate template = new RestTemplate(); template.getForObject("http://localhost:8080/spitter/users/${id}", String.class, userId); Create RestTemplate template = new RestTemplate(); SpitterUser user = new SpitterUser(userName, password); template.postForLocation("http://localhost:8080/spitter/users/${id}", user, userId); Delete RestTemplate template = new RestTemplate(); template.delete("http://localhost:8080/spitter/users/${id}", userId); E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  112. 112. JavaConfig E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  113. 113. JavaConfig @Configuration public class PeanutsConfiguration { @Bean public Linus linus() { Linus linus = new Linus(); linus.setBlanket(blanket()); return linus; } @Bean private Blanket blanket() { Blanket blanket = new Blanket(); blanket.setColor("blue"); return blanket; } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  114. 114. JavaConfig in Components E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  115. 115. JavaConfig in Components @Component public class KiteEatingTree implements DeciduousTree { public void shedLeaves() { // ... } @Bean public Kite kite() { return new Kite(); } } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  116. 116. Asynchronous Methods E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  117. 117. Asynchronous Methods Annotate a bean method @Async public void backgroundJob() { ... } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  118. 118. Asynchronous Methods Annotate a bean method @Async public void backgroundJob() { ... } In Spring configuration: <task:annotation-driven/> E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  119. 119. Scheduling E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  120. 120. Scheduling @Scheduled(fixedDelay=3000L) public void ping() { ... } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  121. 121. Scheduling @Scheduled(fixedDelay=3000L) public void ping() { ... } @Scheduled(fixedRate=3000L) public void ping() { ... } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  122. 122. Scheduling @Scheduled(fixedDelay=3000L) public void ping() { ... } @Scheduled(fixedRate=3000L) public void ping() { ... } @Scheduled(cron="0 0 0 * * SAT) public void ping() { ... } E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  123. 123. Miscellaneous E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  124. 124. Miscellaneous Object-to-XML mapping from Spring-WS E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  125. 125. Miscellaneous Object-to-XML mapping from Spring-WS Embracing Java 5 (generics, autoboxing, annotations, etc). E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  126. 126. What’s going away
  127. 127. Bye bye E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  128. 128. Bye bye Spring MVC controller hierarchy (deprecated) E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  129. 129. Bye bye Spring MVC controller hierarchy (deprecated) JUnit 3 testing E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  130. 130. Bye bye Spring MVC controller hierarchy (deprecated) JUnit 3 testing Commons Attributes E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  131. 131. Bye bye Spring MVC controller hierarchy (deprecated) JUnit 3 testing Commons Attributes Native TopLink support E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  132. 132. Bye bye Spring MVC controller hierarchy (deprecated) JUnit 3 testing Commons Attributes Native TopLink support WebLogic 8.1 and WebSphere 5.1 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  133. 133. Bye bye Spring MVC controller hierarchy (deprecated) JUnit 3 testing Commons Attributes Native TopLink support WebLogic 8.1 and WebSphere 5.1 spring.jar E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  134. 134. Bye bye E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  135. 135. What else?
  136. 136. Keep your eye on... E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  137. 137. Keep your eye on... Spring Web Flow 2.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  138. 138. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  139. 139. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  140. 140. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  141. 141. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) SpringSource dm Server E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  142. 142. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) SpringSource dm Server SpringSource tc Server E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  143. 143. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) SpringSource dm Server SpringSource tc Server Roo E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  144. 144. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) SpringSource dm Server SpringSource tc Server Roo Groovy/Grails E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  145. 145. Keep your eye on... Spring Web Flow 2.0 Spring BlazeDS Spring Security 3.0 Spring Dynamic Modules (Spring-DM) SpringSource dm Server SpringSource tc Server Roo Groovy/Grails SpringSource Tool Suite E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  146. 146. In summary...
  147. 147. Spring simplifies E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  148. 148. Spring simplifies Spring’s initial focus was to simplify enterprise Java E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  149. 149. Spring simplifies Spring’s initial focus was to simplify enterprise Java Now simplification efforts turn inward E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  150. 150. Spring simplifies Spring’s initial focus was to simplify enterprise Java Now simplification efforts turn inward Trending away from XML toward annotations E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  151. 151. Spring simplifies Spring’s initial focus was to simplify enterprise Java Now simplification efforts turn inward Trending away from XML toward annotations All the while, offering more power E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  152. 152. Spring simplifies E-mail: craig@habuma.com Blog: http://www.springinaction.com Twitter: habuma
  153. 153. Thank You Don’t forget the evals!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×