Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring Boot in the Web Tier

Dave Syer
September 09, 2014

Spring Boot in the Web Tier

This presentation shows you how to understand and harness those features for maximum benefit. We will cover the basics of opinionated application configuration, showing what Spring Boot has to offer the web developer out of the box: content negotiation, internationalization, view templates, security, messaging with websockets, etc. We will look at the embedded servlet container abstractions in Spring Boot, showing how to customize the containers, and how to extract the most from the containers at runtime. We will also show how Spring Boot can embed some other interesting and popular web technologies, like Jersey and Ratpack, giving developers instant access to a wide range of useful features, and zero-effort integration with the Spring for middleware integration.

Dave Syer

September 09, 2014
Tweet

More Decks by Dave Syer

Other Decks in Technology

Transcript

  1. Spring Boot for the Web Tier
    Phillip Webb
    twiiter: @phillip_webb
    email: [email protected]
    Dave Syer
    twitter: @david_syer
    email: [email protected]
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    1 of 43 10/09/14 08:15

    View Slide

  2. Presentation Overview
    Part 1 - Static Content
    Part 2 - Dynamic Content
    Part 3 - Embedded Server
    Part 4 - Other Stacks
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    2 of 43 10/09/14 08:15

    View Slide

  3. Static Content - Serving Files
    Can't use /src/main/webapp for jar deployments
    Put static files from src/main/resources/static
    or .../public or .../resources or .../META-
    INF/resources
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    3 of 43 10/09/14 08:15

    View Slide

  4. Static Content - Conventions
    src/main/resources/static/index.html is mapped to
    /index.html & /
    Add a src/main/resources/favicon.ico to replace the Spring
    Leaf
    Imported "webjars" are automatically mapped
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    4 of 43 10/09/14 08:15

    View Slide

  5. Demo - Static Content
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    5 of 43 10/09/14 08:15

    View Slide

  6. Static Content: Grunt
    Toolchain
    For serious front end developers the best choice is a Javascript toolchain.
    Good community, lots of tools
    Package static assets into a jar
    And/or build them as part of a very thin back end
    Spring Boot CLI makes a great lightweight back end in production or
    for Java devs
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    6 of 43 10/09/14 08:15

    View Slide

  7. Static Content - wro4j
    Great for Java developers
    Often good enough
    JsHint
    CssLint
    JsMin
    Google Closure compressor
    UglifyJs
    Less
    Sass
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    7 of 43 10/09/14 08:15

    View Slide

  8. Static Content - Wro4j with
    Maven
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    8 of 43 10/09/14 08:15

    View Slide


  9. ro.isdc.wro4j
    wro4j-maven-plugin
    ${wro4j.version}

    generate-resources
    run


    ro.isdc.wro.maven.plugin.manager.factory.Configu
    rableWroManagerFactory
    ${basedir}/target/generated-resources
    /static/
    ${basedir}/src/main/wro/wro.xml
    ${basedir}/src/main/wro
    /wro.properties


    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    9 of 43 10/09/14 08:15

    View Slide

  10. Static Content - Wro4j with
    Maven
    src/main/wro/wro.xml


    file:./src/main/wro/main.less


    src/main/wro/wro.properties
    postProcessors=less4j
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    10 of 43 10/09/14 08:15

    View Slide

  11. Dynamic Content - Templating
    Support
    Thymeleaf
    Groovy Template Language
    Freemarker
    Velocity
    JSP (not recommended)
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    11 of 43 10/09/14 08:15

    View Slide

  12. Dynamic Content - Template
    Conventions
    Templates live in src/main/resources/templates
    and are accessed via classpath:/templates/
    Default Extensions are:
    *.html - Thymeleaf
    *.tpl - Groovy
    *.ftl - Freemarker
    *.vm - Velocity
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    12 of 43 10/09/14 08:15

    View Slide

  13. Dynamic Content - Template
    Customization
    User spring.xxx.prefix and spring.xxx.suffix
    eg. spring.freemarker.suffix=fm
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    13 of 43 10/09/14 08:15

    View Slide

  14. Demo - Templatinghttp://localhost:4000/decks/spring-boot-for-the-web-tier.html
    14 of 43 10/09/14 08:15

    View Slide

  15. Dynamic Content - Custom
    Support
    Add a ViewResolver
    Optionally add a TemplateAvailabilityProvider
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    15 of 43 10/09/14 08:15

    View Slide

  16. public class GroovyTemplateAvailabilityProvider implements
    TemplateAvailabilityProvider {
    @Override
    public boolean isTemplateAvailable(String view, Environment
    environment,
    ClassLoader classLoader, ResourceLoader resourceLoader) {
    if (ClassUtils.isPresent("groovy.text.TemplateEngine",
    classLoader)) {
    String prefix =
    environment.getProperty("spring.groovy.template.prefix",
    GroovyTemplateProperties.DEFAULT_PREFIX);
    String suffix =
    environment.getProperty("spring.groovy.template.suffix",
    GroovyTemplateProperties.DEFAULT_SUFFIX);
    return resourceLoader.getResource(prefix + view +
    suffix).exists();
    }
    return false;
    }
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    16 of 43 10/09/14 08:15

    View Slide

  17. Dynamic Content -
    Internationalization
    A MessageSource bean is added when src/main/resources
    /messages.properties exists
    Use messages_LOCALE.properties to add additional locales
    e.g. messages_FR.properties
    Choose a specific locale using the spring.mvc.locale property
    Choose a specific date format using the spring.mvc.date-
    format property
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    17 of 43 10/09/14 08:15

    View Slide

  18. Dynamic Content -
    HttpMessageConverter
    Add HttpMessageConverter beans and Spring Boot will try to do
    the right thing
    It tries to be intelligent about the order
    Add a HttpMessageConverters bean if you need more control
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    18 of 43 10/09/14 08:15

    View Slide

  19. Dynamic Content - Rest
    Use the @RestContoller annotation
    Use ResponseEntity builder methods with Spring Framework 4.1
    ResponseEntity.
    accepted().
    contentLength(3).
    contentType(MediaType.TEXT_PLAIN).
    body("Yo!");
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    19 of 43 10/09/14 08:15

    View Slide

  20. Demo - HttpMessageConverter
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    20 of 43 10/09/14 08:15

    View Slide

  21. Dynamic Content - Hidden
    Gems
    You can get the RequestContext from RequestContextHolder
    anywhere
    The request has some useful things in it (from Spring), e.g.
    HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE
    All Converter, Formatter, GenericConverter beans are
    automatically added
    Use spring.mvc.message-codes-resolver-format to add a
    MessageCodesResolver
    prefix_error_code or postfix_error_code
    # prefix_error_code
    empty.customer.name=Customer name is required
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    21 of 43 10/09/14 08:15

    View Slide

  22. # postfix_error_code
    customer.name.empty=Customer name is required
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    22 of 43 10/09/14 08:15

    View Slide

  23. Embedded Server
    When using WARs a ServletContainerInitializer creates
    the Spring ApplicationContext
    When running embedded the ApplicationContext creates the
    Server
    Expects a single EmbeddedServletContainerFactory bean
    Odd dance for
    WebApplicationContext.getServletContext() and
    ServletConfigAware
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    23 of 43 10/09/14 08:15

    View Slide

  24. Embedded Server -
    Initialization
    The following beans are used to configure the server:
    Servlet
    Filter
    ServletRequestListener
    ServletRequestAttributeListener
    HttpSessionAttributeListener
    HttpSessionListener
    ServletContextListener
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    24 of 43 10/09/14 08:15

    View Slide

  25. Embedded Server -
    Initialization
    For more control use
    ServletRegistrationBean
    FilterRegistrationBean
    ServletListenerRegistrationBean
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    25 of 43 10/09/14 08:15

    View Slide

  26. @Bean
    public ServletRegistrationBean myServlet() {
    ServletRegistrationBean bean =
    new ServletRegistrationBean(new MyServlet(), "/mine");
    bean.setAsyncSupported(false);
    bean.setInitParameters(Collections.singletonMap("debug",
    "true"));
    return bean;
    }
    @Bean
    public FilterRegistrationBean myFilter() {
    return new FilterRegistrationBean(new MyFilter(), myServlet());
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    26 of 43 10/09/14 08:15

    View Slide

  27. Embedded Server -
    Initialization
    By design the following are not called with embedded servers:
    javax.servlet.ServletContainerInitializer
    org.springframework.web.WebApplicationInitializer
    Use
    o.s.boot.context.embedded.ServletContextInitializer
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    27 of 43 10/09/14 08:15

    View Slide

  28. /**
    * Configure the given {@link ServletContext} with any servlets,
    filters, listeners
    * context-params and attributes necessary for initialization.
    * @param servletContext the {@code ServletContext} to initialize
    * @throws ServletException if any call against the given {@code
    ServletContext}
    * throws a {@code ServletException}
    */
    void onStartup(ServletContext servletContext) throws
    ServletException;
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    28 of 43 10/09/14 08:15

    View Slide

  29. Embedded Server -
    Customization
    Use ServerProperties (e.g. server.port=8080)
    EmbeddedServletContainerCustomizer
    Customize common things (e.g. the port, error-pages,
    context-path)
    Tomcat Specific
    TomcatConnectorCustomizer
    TomcatContextCustomizer
    Jetty Specific
    JettyServerCustomizer
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    29 of 43 10/09/14 08:15

    View Slide

  30. Embedded Server -
    Customization
    If all else fails subclass EmbeddedServletContainerFactory
    Lots of protected methods to override
    TomcatEmbeddedServletContainerFactory
    JettyEmbeddedServletContainerFactory
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    30 of 43 10/09/14 08:15

    View Slide

  31. @Bean
    public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    return new TomcatEmbeddedServletContainerFactory(7070) {
    @Override
    protected void customizeConnector(Connector connector) {
    // Something with the connector
    }
    @Override
    protected void configureSsl(AbstractHttp11JsseProtocol>
    protocol, Ssl ssl) {
    // Something with ssl
    }
    };
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    31 of 43 10/09/14 08:15

    View Slide

  32. Embedded Server - Tomcat
    Behind HTTPD
    Running behind Apache HTTPD is a common option
    Especially useful with SSL termination
    Real IP and SSL information is passed in headers
    server.tomcat.protocol-header=x-forwarded-proto
    server.tomcat.remote-ip-header=x-forwarded-for
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    32 of 43 10/09/14 08:15

    View Slide

  33. Embedded Server - Tomcat
    Behind HTTPD

    ServerName example.spring.io
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    ProxyPass / http://${TOMCAT_IP}:8080/
    ProxyPassReverse / http://${TOMCAT_IP}:8080/


    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/apache.crt
    SSLCertificateKeyFile /etc/apache2/ssl/apache.key
    ProxyPass / http://${TOMCAT_IP}:8080/
    ProxyPassReverse / http://${TOMCAT_IP}:8080/
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"

    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    33 of 43 10/09/14 08:15

    View Slide

  34. Demo - Running Behind
    HTTPS
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    34 of 43 10/09/14 08:15

    View Slide

  35. Other Stacks
    JAX-RS: Jersey 1.x, Jersey 2.x dsyer/spring-boot-jersey, CXF
    (allegedly works)
    Netty and NIO: Ratpack dsyer/spring-boot-ratpack
    Servlet 2.5 scratches/spring-boot-legacy
    Vaadin peholmst/vaadin4spring
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    35 of 43 10/09/14 08:15

    View Slide

  36. Jersey 1.x
    Easy to integrate with Spring Boot using Filter (or Servlet), e.g.
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    36 of 43 10/09/14 08:15

    View Slide

  37. @Configuration
    @EnableAutoConfiguration
    @Path("/")
    public class Application {
    @GET
    @Produces("text/plain")
    public String hello() {
    return "Hello World";
    }
    @Bean
    public FilterRegistrationBean jersey() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new ServletContainer());
    bean.addInitParameter("com.sun.jersey.config.property.packages",
    "com.mycompany.myapp");
    return bean;
    }
    }
    (N.B. with fat jar you need to explicitly list the nested jars that have
    JAX-RS resources in them.)
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    37 of 43 10/09/14 08:15

    View Slide

  38. Jersey 2.x
    Spring integration is provided out of the box, but a little bit tricky to use
    with Spring Boot, so some autoconfiguration is useful. Example app:
    @Configuration
    @Path("/")
    public class Application extends ResourceConfig {
    @GET
    public String message() {
    return "Hello";
    }
    public Application() {
    register(Application.class);
    }
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    38 of 43 10/09/14 08:15

    View Slide

  39. Ratpack
    Originally inspired by Sinatra, but now pretty much diverged. Provides a
    nice programming model on top of Netty (potentially taking advantage of
    non-blocking IO).
    2 approaches:
    Ratpack embeds Spring (and uses it as a Registry), supported
    natively in Ratpack 0.9.9
    Spring embeds Ratpack (and uses it as an HTTP listener) = spring-
    boot-ratpack
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    39 of 43 10/09/14 08:15

    View Slide

  40. Spring Boot embedding
    Ratpack
    Trivial example (single Handler):
    @Bean
    public Handler handler() {
    return (context) -> {
    context.render("Hello World");
    };
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    40 of 43 10/09/14 08:15

    View Slide

  41. Spring Boot embedding
    Ratpack
    More interesting example (Action registers Handlers):
    @Bean
    public Handler hello() {
    return (context) -> {
    context.render("Hello World");
    };
    }
    @Bean
    public Action handlers() {
    return (chain) -> {
    chain.get(hello());
    };
    }
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    41 of 43 10/09/14 08:15

    View Slide

  42. Spring Boot Ratpack DSL
    A valid Ratpack Groovy application:
    ratpack {
    handlers {
    get {
    render "Hello World"
    }
    }
    }
    launched with Spring Boot:
    $ spring run app.groovy
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    42 of 43 10/09/14 08:15

    View Slide

  43. Questions?
    http://projects.spring.io/spring-boot/
    https://github.com/SpringOne2GX-2014/spring-boot-for-the-web-tier
    http://localhost:4000/decks/spring-boot-for-the-web-tier.html
    43 of 43 10/09/14 08:15

    View Slide