Newsletter |
How to Deploy Spring Boot Applications on External Tomcat Server
So far, in previous examples we used to deploy and run the applications using embedded tomcat server provided by the spring boot. Generally in the real-time projects we wont use inbuilt servers provided by the frameworks because of many reasons like security, maintenance and control. So in this article I will show you how can we deploy the spring boot applications on external servers (in this tutorial I am going to consider the external server as Tomcat).
Just do these changes to your spring boot application which you want to deploy it on to external tomcat server.
- pom.xml, add dependency and packaging to war
- Extend your main class with SpringBootServletInitializer and override its configure method
- Generate WAR and deploy into the external server
If want you can change the context path also in the application.properties. (Optional)
pom.xml
<!-- to export as WAR --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- packaging to WAR --> <packaging>war</packaging>
Final pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.java4s</groupId> <artifactId>SpringBootAppInExternalTomcat</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- packaging to WAR --> <packaging>war</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Instruct spring boot not to use the inbuilt Tomcat server --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> </project>
Extend main Class with SpringBootServletInitializer
package com.java4s.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class SpringBootApp extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootApp.class); } public static void main(String[] args) { SpringApplication.run(SpringBootApp.class, args); } }
application.properties
server.contextPath=/springbootapp
SpringJava4sController.java
package com.java4s.app.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SpringJava4sController { @RequestMapping("/java4s-spring-boot-ex-tomcat") public String customerInformation() { return "Hey, I am from external tomcat"; } }
Generate a WAR file
Right click on pom.xml -> Run as -> Maven install, this will generate a WAR file in your target folder. Just copy that WAR file into your tomcat’s webapps folder and start the server ( or ) you can deploy and test from your IDE (eclipse/sts) by importing that WAR into your work space and run that in the external tomcat [I tried importing into eclipse].
Output
Note:
If you observe the context path in the URL, its showing SpringBootAppInExternalTomcat-0.0.1-SNAPSHOT. Its not taking the context path we have given in the application.properties, rather its considering the context path as Artifact Id + Version from pom.xml. So if you want required context path, the only possibility is change pom.xml accordingly (if you know other ways please comment).
You can download the application and generate the WAR file with the above step and verify.
You Might Also Like
::. About the Author .:: | ||
My students are referring to this tutorials. Good article dude. 🙂
Hi If I use WebLogic what can be my url, can you pls do the needful.
Only JNDI name in application.properties
Nice explanation bro.
I am not clear with why it is not taking context path from application.properties . It will not read context path only or not read any given property from application.properties file at all.
Hi Siva, Has anyone used Spring Boot app with native Tomcat in production scenarios?
Hi Sir,
I have used weblogic as external server and the war got deployed successfully with few changes, can you share me that how is the URL got framed, what is the URL to hit like http://host:port/artifact-version/controller name
Context path can be set in following file : src/main/webapp/META-INF/context.xml
<Context path="/mybootapp/" />
Hi Sivateja, As you asked for contextPath , can try below : –
server.context-path=/springbootapp
I am getting the error from the Tomcat log.
01-Oct-2018 14:29:57.442 INFO [http-nio-8080-exec-43] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
01-Oct-2018 14:30:11.851 SEVERE [http-nio-8080-exec-43] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file
01-Oct-2018 14:30:11.852 SEVERE [http-nio-8080-exec-43] org.apache.catalina.core.StandardContext.startInternal Context [/test] startup failed due to previous errors
01-Oct-2018 14:30:11.889 WARNING [http-nio-8080-exec-43] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [test] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
01-Oct-2018 14:30:11.889 WARNING [http-nio-8080-exec-43] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [test] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.base@10.0.2/java.lang.Object.wait(Native Method)
java.base@10.0.2/java.lang.ref.ReferenceQueue.remove(Unknown Source)
com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64)
java.base@10.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.base@10.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.base@10.0.2/java.lang.Thread.run(Unknown Source)
01-Oct-2018 14:30:12.932 INFO [Abandoned connection cleanup thread] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1329)
at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1006)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.checkContextClassLoaders(AbandonedConnectionCleanupThread.java:90)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:63)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Thanks, nice post
On delopying the war file in tomcat getting the below error :
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringBootAppInExternalTomcat]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:985)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: More than one fragment with the name [spring_web] was found. This is not legal with relative ordering. See section 8.2.2 2c of the Servlet specification for details. Consider using absolute ordering.
at org.apache.tomcat.util.descriptor.web.WebXml.orderWebFragments(WebXml.java:2200)
at org.apache.tomcat.util.descriptor.web.WebXml.orderWebFragments(WebXml.java:2159)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1124)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:769)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:299)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5181)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
… 10 more
Mar 19, 2019 10:07:20 AM org.apache.catalina.startup.HostConfig deployWAR
SEVERE: Error deploying web application archive [C:\Software\apache-tomcat-8.5.38-windows-x64\apache-tomcat-8.5.38\webapps\SpringBootAppInExternalTomcat.war]
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringBootAppInExternalTomcat]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:758)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:985)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
application.properties file is not loading while start the tomcat server. throwing error unsatisfieddependencyexception error creating bean with name "datasource". actually i have specified my DB credentials in application.properties file.
Hi Sivateja,
No need of application.properties.
Use <finalName>springbootapp</finalName> in <build> tag in your pom.xml.
It will resolve your issue.
Regards,
Dinesh