BLOGs
Web Development
Published June 02nd, 2017 by

Customized Deployment for Spring Boot Applications

Technology: Spring Boot is most popular framework used for developed applications. Spring Boot will provide Tomcat server by default. If we add spring-starter-web as dependency then Tomcat server will be added to classpath.Spring-boot-starter-tomcat will be added if we add spring-starter-web as dependency in pom.xml file.

Configuring Server Properties:

Spring-boot-autoconfigure jar file provides ServerProperties class using which we can provides properties to server like port, context-path of an application, SSL configuration etc…

ConfigurationPropertiesBindingPostProcessor will load all properties and assign properties to Java Properties and create the required beans.

Java development
Creating sample Rest application:

@SpringBootApplication

public class SpringBootCustomDeploymentApplication {

                public static void main(String[] args) {

                                SpringApplication.run(SpringBootCustomDeploymentApplication.class, args);

                }             

                @RestController

                public class SampleController{

                                @GetMapping("/greeting")

                                public Map<String,String> getGreetings(){

                                                Map<String,String> map = new HashMap<String, String>();

                                                map.put("Hello", "Greeting");

                                                return map;

                                }

                }

}

If we run the application then tomcat server will run on port 8080 and run the application on root contextpath.

Running/deploying application on Jetty:

We can run/deploy the application on jetty server using spring-boot-starter-jetty dependency.

So we can remove the tomcat dependency and we can add spring-boot-starter-jetty dependency.

<dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-starter-tomcat</artifactId>

                <scope>provided</scope>

</dependency>

<dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-starter-jetty</artifactId>

</dependency>

Using scope we can we can exclude adding dependency at runtime, in above scenario we are removing tomcat dependency and adding jetty as embedded server.

Similarly we can remove jetty dependency and we can add spring-boot-starter-undertow dependency if we want to deploy and run the application in undertow server.

Adding Servlet, Filter and Listeners to an application:

There are many ways to add servlet, Filter and Listeners to an applications.

  1. We can implement we can extend HTTPServlet, Filter and Listener interface and mark them Spring Beans, and the package will be available to Spring Component Scan.
  2. For servlets and filters we can use ServletRegistrationBean and FilterRegistrationBean Spring classes to register the servlets and filters. We can also provide init-param to servlet and filter. If we don’t specify the dispatching modes then by default it will be FORWARD, INCLUDE, REQUEST. We can also enable and disabled using setEnabled method by passing either true or false.
  3. @WebServlet, @WebFilter, and @WebListener annotated classes can be automatically registered with an embedded servlet container by annotating a @Configuration class with @ServletComponentScan and specifying the package(s) containing the components that you want to register. By default, @ServletComponentScan will scan from the package of the annotated class.

Assign Random Port to Embedded Server:

We can also assign port number based on availability of ports on Host Machine. If we set server.port=0 in application.properties then port number will be allocated during the run time.

org.springframework.util.SocketUtils.findAvailableTcpPort() is the method to assign the port number to embedded server during runtime.

Obtaining the Server Port:

After assigning the port number to server Spring Boot will raise EmbeddedServletContainerInitializedEvent event. We need to implement ApplicationListener of the type EmbeddedServletContainerInitializedEventto receive the event. ApplicationListener need to implement getSource() which will return EmbeddedServletContainer  of the type, has method getPort() which will return the port number on which Embedded server is running.

Configuring SSL:SSL can be configured declaratively by setting the various server.ssl.* properties, typically in application.properties or application.yml file.

server.port=8443

server.ssl.key-store=classpath:keystore.jks

server.ssl.key-store-password=secret

server.ssl.key-password=another-secret

Spring Boot application either it will support HTTP or HTTPS, it does not support both connectors at the same time using application.properties file, but we can do the same using programmatically.

Configure Logging:

For Tomcat embedded server we can use prefix server.tomcat.* to configure Tomcat Server properties like max-connections, threads, log file etc… Some of mostly used properties are mentioned below:

server.tomcat.accesslog.enabled=true

server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)

server.tomcat.accesslog.file-date-format=.yyyy-MM-dd

server.tomcat.accesslog.rotate=true

server.tomcat.max-connections=10

server.tomcat.max-threads=10

server.tomcat.max-http-post-size=2048

Similarly we can properties for Jetty embedded server properties using server.jetty.* prefix.

Adding Multiple Connectors in Embedded Server:

EmbeddedServletContainerCustomizer is the interface to customize the embedded server, where we can add connectors, error pages, providing proxy details etc…

Adding custom connectors, custom settings for each server by using below code.

@Component

public class MyCustomizer implements EmbeddedServletContainerCustomizer{




        @Override

        public void customize(ConfigurableEmbeddedServletContainer container) {

                        if(TomcatEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass()))

                        {

                                        log.info("in tomcat");

                        }

                        if(JettyEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass()))

                        {

                                        log.info("in jetty");

                        }
        }
}

We can create a ServletContainerFactory for each embedded server, and add connectors to it.

@Component

public class MyCustomizer implements EmbeddedServletContainerCustomizer{




        @Override

        public void customize(ConfigurableEmbeddedServletContainer container) {

                        if(TomcatEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass()))

                        {

                                        log.info("in tomcat");

                                        TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory = TomcatEmbeddedServletContainerFactory.class.cast(container);

                                tomcatEmbeddedServletContainerFactory.addAdditionalTomcatConnectors(createTomcatSslConnector(),createTomcatAJPConnector());

                        }

                        if(JettyEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass()))

                        {

                                        log.info("in jetty");

                                        JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory = JettyEmbeddedServletContainerFactory.class.cast(container);

                        }

        }

        private Connector createTomcatSslConnector() {

                        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");

                        Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();

                        try {

                                        File keystore = new ClassPathResource("keystore").getFile();

                                        File truststore = new ClassPathResource("keystore").getFile();

                                        connector.setScheme("https");

                                        connector.setSecure(true);

                                        connector.setPort(8443);

                                        protocol.setSSLEnabled(true);

                                        protocol.setKeystoreFile(keystore.getAbsolutePath());

                                        protocol.setKeystorePass("keystorepass");

                                        protocol.setTruststoreFile(truststore.getAbsolutePath());

                                        protocol.setTruststorePass("keystorepass");

                                        protocol.setKeyAlias("keyalias");

                                        return connector;

                        }

                        catch (IOException ex) {

                                        throw new IllegalStateException("can't access keystore: [" + "keystore"

                                                                        + "] or truststore: [" + "keystore" + "]", ex);

                        }

        }

        private Connector createTomcatAJPConnector() {

                        Connector ajpConnector = new Connector("AJP/1.3");

                        ajpConnector.setPort(8081);

                        ajpConnector.setSecure(false);

                        ajpConnector.setAllowTrace(false);

                        ajpConnector.setScheme("http");

                        return ajpConnector;

        }

}

Enable HTTP response compression:

HTTP response Compression is supports by tomcat, jetty and undertow, it can be enabled using application.properties/application.yml file using server.compression.enabled=true property.

By default if the response size is greater than 2048 then only it will be enabled, but we can also customize the size using server.compression.min-response-size property, we can also limit the compression for MIME-Types using server.compression.mime-types property, by default text/html,text/xml,text/plain,text/css MIME-Types will be compressed.

Conclusion: Spring Boot by default comes with Tomcat as embedded server, but we can also customize on which we want to deploy our applications, can add multiple connectors, listeners based on embedded server, using application.properties file, we can customize the configuration without writing code.

In this article, you have learn about customized deployment for spring boot applications . If you have any question, ask to experts of Java web development company straightforward in comments. Do share your feedback for this post and tell other readers how your experience with this tutorial was.

Ethan Millar

Technical Writer at Aegis Softtech
Having more than 6+ years of experience to write technical articles especially for Hadoop, Big Data, Java, CRM and Asp.Net at Aegis Softtech.

Our rankings are completely independent, transparent, and community driven; they are based on user reviews and client sentiment. These web development companies had to earn their way up and didn't just pay their way up.

View Rankings of Best Web Development Companies