30

So I am new to Spring - so I thought I would try Spring Boot

I am using a Maven to build - I set up a view requests, when I run it as "App" looks like it starts tomcat up itself and i have a service at default 8080 port, so when I call localhost:8080/service it's all good.

However when i try to package it up as a WAR to deploy to a server it doesn't work

So i thought i would go back to basics and deploy it onto my tomcat server locally and see what happens

So first off nothing happened - 404 - did a bit of googling at found out i need to include a web entry point like this - here's my main class

@ComponentScan
@EnableAutoConfiguration
public class App extends SpringBootServletInitializer
{

    public static void main( String[] args )    {
        SpringApplication.run(App.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(appClass);
    }

    private static Class<App> appClass = App.class;
}

so it looked like it worked, in the console i could see the red catalina startup text, then i saw the Spring boot start up (which i wasn't seeing before)

however when i try and call the service localhost:8080/service i still get a 404

when i run it as "App" it works a treat

is there something obvious i need to be doing ? to create the war i just

  1. changed the pom xml package type to war
  2. included the override in the code snippet above
  3. exported as a war

i have unzipped the WAR and it looked fine - there is a WEB-INF and a set of dependencies, etc.

any help would be good - as anyone had similar problems when deploying spring boot apps as a WAR?

***UPDATE****

Now i can get my war to deploy correctly on my local Tomcat 7 server - but when i try and deploy to an externally hosted Tomcat container i get

at       org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 15 more
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/cookpot
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cookpot]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:898)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/examples
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/host-manager
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/CookPot
Jul 14, 2014 1:49:02 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/CookPot/WEB-INF/lib/tomcat-embed-core-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jul 14, 2014 1:49:02 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/CookPot/WEB-INF/lib/tomcat-embed-el-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
Jul 14, 2014 1:49:06 PM org.apache.catalina.core.ContainerBase addChildInternal
SEVERE: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/CookPot]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.security.AccessControlException: access denied (java.util.PropertyPermission java.awt.headless write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.System.setProperty(System.java:727)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:263)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:130)
at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:89)
at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:51)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 15 more
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/CookPot
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/CookPot]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:898)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/ROOT
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/manager
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/docs
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/Cookpot
Jul 14, 2014 1:49:06 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/Cookpot/WEB-INF/lib/tomcat-embed-core-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jul 14, 2014 1:49:06 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/Cookpot/WEB-INF/lib/tomcat-embed-el-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
Jul 14, 2014 1:49:09 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-6350"]
Jul 14, 2014 1:49:09 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-4350"]
Jul 14, 2014 1:49:09 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 17529 ms
Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
philthomas26
  • 315
  • 1
  • 3
  • 8
  • Have you run "mvn package" to create the .war? Also, in your `pom.xml` have you marked `spring-boot-starter-tomcat` as `provided`? See [here](http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#build-tool-plugins-maven-packaging) about this. – Andrei Stefan Jul 14 '14 at 17:07
  • 1
    Generally speaking, Tomcat is going to prefix your app's URLs with `appname/`. What is the Tomcat name of the application? – chrylis -cautiouslyoptimistic- Jul 14 '14 at 17:17
  • Have you followed the guide on Spring.io which describes how to package your application as a WAR and deploy to Tomcat? http://spring.io/guides/gs/convert-jar-to-war/ – Steve Jul 15 '14 at 08:26
  • @philthomas26 Can you please explain exactely how you have solved the Problem? Because I have the same. thank you in advance – Samuel L Mar 01 '15 at 09:57
  • I've run into this before and can confirm the accepted solution works. I've also not run into it using Gradle, so an alternative may also be to use Gradle in lieu of Maven. – Cuga Mar 12 '15 at 17:03
  • Check this link will help https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file – anandchaugule Feb 08 '19 at 19:16

3 Answers3

36

The chapter Packaging executable jar and war files in the Spring Boot reference documentation states:

To build a war file that is both executable and deployable into an external container you need to mark the embedded container dependencies as “provided”, e.g:

<?xml version="1.0" encoding="UTF-8"?>
    <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">
    <!-- ... -->
    <packaging>war</packaging>
    <!-- ... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- ... -->
    </dependencies>
</project>
James
  • 11,654
  • 6
  • 52
  • 81
  • I believe I had to `mvn clean` before `mvn package` finally produced a `.war` deployable to tomcat, while applying this solution (it finally worked). – P Marecki Jan 14 '16 at 12:11
  • 1
    Summary of steps to ".war-ize" spring-boot app: (1) `war`, and the above dependency with "provided" in `pom.xml`, (2) modifying `Application.java` by `extends SpringBootServletInitializer` with the `@Override` as in the question. Produces `.war` runnable via `java -jar` and deployable to tomcat 7.0.59 and jetty 9.3.6 using spring-boot 1.3.1. – P Marecki Jan 14 '16 at 12:20
  • It's important to remark that `spring-boot-maven-plugin` build plugin should call goal `repackage` [See doc](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-include-maven-plugin). – albfan Feb 09 '16 at 22:29
5

Below code worked fine for tomcat8 deployment without tomcat dependency.

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
public class ManufacturingRegionApplication extends SpringBootServletInitializer {

public static void main(String[] args) {
    new SpringApplicationBuilder(ManufacturingRegionApplication.class).application().run(args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
    return applicationBuilder.sources(application);
}

private static Class<ManufacturingRegionApplication> application = ManufacturingRegionApplication.class;

}

Below dependency is not required.

   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

 @RestController
 @RequestMapping(value = "/manufacturing-region-service")
 public class ManufacturingRegionService {

@Resource
private ManufacturingRegionDao manufacturingRegionDao;

@ResponseBody
@Transactional(readOnly = true)
@RequestMapping(value = "/region-codes/{abbr}", method = GET, produces = "application/json")

http://localhost:8080/manufacturing-region-api/manufacturing-region-service/region-codes/ABBRVALUE

Sandeep M
  • 248
  • 3
  • 6
0

When we choose Spring Boot, we don't want to produce a WAR. From the root page:

Spring Boot makes it easy to create stand-alone [...] 
Applications that can you can "just run".
Embed Tomcat or Jetty directly (no need to deploy WAR files)

EDITED: So, if the purpose is "to try Spring Boot", I suggest to not generate a WAR file.

If you really need to produce a WAR file (keep your code built against SpringBoot and produce a file that you can run in any standard servlet container...) then you should read the documentation Converting a Spring Boot JAR Application to a WAR.

Did you include spring-boot-maven-plugin in the build process? You didn't describe this step...

mcoolive
  • 3,805
  • 1
  • 27
  • 32
  • It would help if you would post a relevant example on how to do this properly – Engineer2021 Jul 14 '14 at 19:20
  • @staticx that can be found right on Spring's site: [convert Spring Boot JAR to WAR](https://spring.io/guides/gs/convert-jar-to-war/). But mcoolive actually does answer this question better than James' in my opinion, consider no one has addressed that the question is strange. The whole point of Spring Boot is to run a simple jar file. You only produce a war file if you are using a java servlet container like tomcat for instance. For better info on that check this out: [spring.io inside and out](https://www.youtube.com/v/pA1oGmd1R5w?start=1565&end=1612&autoplay=1) – aaiezza Apr 17 '15 at 19:09
  • 2
    This comment doesn't answer to the question. – Stefano Bragaglia Jun 23 '15 at 19:14
  • 3
    Do comments normally answer questions? – cbmeeks Aug 28 '15 at 19:04
  • 1
    This "answer" only provides author's opinion on wheather he finds the aims of the OP reasonable or not. – P Marecki Jan 14 '16 at 11:56