Deploy a war of Spring Boot application to the local Tomcat server: 404 response [duplicate] - spring-boot

This question already has answers here:
Tomcat 10.0.4 doesn't load servlets (#WebServlet classes) with 404 error [duplicate]
(2 answers)
Closed 1 year ago.
I generated a simple Greeting web application using Spring Initializr and choose war as the packaging type. Starting it from the terminal with mvn spring-boot:run and pointing my browser to http://localhost:8080/greeting returns the expected response.
I followed this article for the deployment steps and modified pom.xml so that to avoid including version numbers in the generated war:
<build>
<finalName>${artifactId}</finalName>
<plugins>
...
</build>
I build the war as usual with mvn clean installand got the expected demo-spring-web.war which I copied/pasted inside the apache-tomcat-10.0.4/webapp folder.
Then I started the Tomcat bu running catalina.sh run from the Tomcat bin folder.
Tomcat started and displayed the demo-spring-web.war to be successfully deployed:
11-Apr-2021 18:24:36.414 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR
Deployment of web application archive [/Users/serguei/soft/apache-tomcat-10.0.4/webapps/demo-spring-web.war] has finished in [1,286] ms
But when I tried to access the deployed application at localhost:8080/demo-spring-web/greeting, it returned 404 status.
What's wrong with that?

You must declare a run class that extends SpringBootServletInitializer, for deploy in war mode.Like this :
#SpringBootApplication public class AppTomcat extends SpringBootServletInitializer {
}

The default prepared/initialized application from spring initializer contains main() method initializing the application so that it can run in a stand alone mode and can be tested quickly.
In case you want to deploy it to another container you should make a servlet initializing the application.
So you should be extending the class having main method with SpringBootServletInitializer and remove main method.
The "mvn clean package" will fail if you have plugin "org.springframework.boot" in the .
I think following above two steps will make the built war deployable in external tomcat.
I had read an article some times back, may be that can also help: https://www.baeldung.com/spring-boot-war-tomcat-deploy

Related

Deploying a spring boot war on jetty9.4.6 with no URI in the war available

I follow the spring boot reference document to make an executable and deployable war in 2 steps:
in pom file, make a war package and make spring-boot-starter-tomcat scope
provided
make the Application class extends
SpringBootServletInitializer and override configure method.
then copy the war file to {jetty_home}/webapps.
I tried restart the jetty server and it seems the war was loaded with below info
2017-07-24 11:16:35.740:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#6e1ec318{/abc-0.1,file:///tmp/jetty-0.0.0.0-8080-abc-0.1.war-_abc-0.1-any-4452702112804908874.dir/webapp/,AVAILABLE}{/abc-0.1.war}
Visitin {jetty_server_ip}:8080/abc-0.1 shows "Directory: /abc-0.1/" while visit any URL in the war returns a 404 error.
What am I doing wrong? Please guide.
The WebApp's "context path" is set to /abc-0.1 in your deployed instance.
You will only be able to access that webapp on {host}/abc-0.1/.
Assuming that you have no other contexts (webapps) deployed, then you have nothing answering at {host}/abc/ and will always get 404 for {host}/abc/ prefixed URLs.

Use of spring-boot-maven-plugin

While creating a spring boot project I define property in pom.xml as <packaging>war</packaging> with which I can create a war and thereafter deploy the war into server maybe tomcat or WAS.
But I came across a plugin named spring-boot-maven-plugin whose documentation states that it's use is to package executable jar or war archives and run an application in-place.
My query is why do we need this at all ?
If my packaging can tell me what to create and then can deploy it to run, what is the used of this plugin.
I am trying to understand a new project so wanted to be sure that every line makes sense
The maven plugin will create an "executable" archive. In the case of the war packaging, you would be able to execute your app with java -jar my-app.war. If you intend to deploy your Spring Boot application in an existing Servlet container, then this plugin is, indeed, not necessary.
The maven plugin does more things like running your app from the shell or creating build information.
Check the documentation
The Spring Boot Maven Plugin provides Spring Boot support in Apache Maven, letting you package executable jar or war archives and run an application “in-place”.
Refer this - https://www.javaguides.net/2019/02/use-of-spring-boot-maven-plugin-with.html

Spring WebApplicationInitializer (ServletContainerInitializer, #HandlesTypes) with Embedded Tomcat

I fail to understand why in the following minimal project my implementation of Spring's WebApplicationInitializer interface is found when running tests within Eclipse and IntelliJ, but not when using Maven (mvn clean test).
With Eclipse and IntellIJ I see INFO: Spring WebApplicationInitializers detected on classpath: [com.example.pack.DummyInitializer#26d678a4]
With mvn clean test I see INFO: No Spring WebApplicationInitializer types detected on classpath.
In the test I start an Embedded Tomcat:
String pathToWebXML = new File("src/main/webapp/").getAbsolutePath();
tomcat = new Tomcat();
tomcat.setBaseDir("embedded_tomcat");
tomcat.setPort(0);
tomcat.addWebapp("", pathToWebXML);
tomcat.start();
The web.xml references a ServletContextListener implementation which creates a new (and empty) AnnotationConfigWebApplicationContext.
I uploaded the example project to GitHub: https://github.com/C-Otto/webapplicationinitializer
As indicated in the comments, the classpath used by Maven Surefire (and Maven Failsafe) in the default setting is not scanned by Tomcat. Most classes are referenced using a MANIFEST.MF file inside a JAR file.
One option is to disable the useSystemClassLoader setting of the Maven plugins. However, this changes the details of the classloader, which may cause other problems.
As another option one could disable useManifestOnlyJar, which may cause problems on Windows machine.
In our project we decided to remove the initializer classes, and instead register whatever they were supposed to do manually. In a concrete example, as our implementation of AbstractSecurityWebApplicationInitializer was not found, we now register the security filter manually inside the contextInitialized method:
String filterName = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
servletContext.addFilter(filterName, new DelegatingFilterProxy(filterName)).addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
You can tell Tomcat to include the jars that are referenced via the manifest file in the jar created by surefire. This can be done in context.xml setting the Jar Scanner attribute scanManifest to true. This is the default in newer versions of Tomcat as stated here: https://bz.apache.org/bugzilla/show_bug.cgi?id=59961.

Grails run-app causes error generating web.xml file and bootstrap.groovy not included in war file

I am working on an maven application. When I run it from IntelliJ, it successfully launches my application. But bootstrap.groovy file is not being read. I have created a new username to be added to DB in bootstrap and it should allow me to login to the application using that username for the first time. This is not getting invoked during the start of the program. What settings should I do to include bootstrap.groovy.
The same happens when I create a war file and deploy it in the test server. Bootstrap.grrovy is not read. To create the war file, I use mvn package in command line.
My other question with the same application is that when I do grails run-app, I get the following error: Error generating web.xml file.
What is that I am missing? Please let me know.
Well, I fixed the issue. The web.xml was created when I changed the grails dependent jar. I was using 2.3.4 in my application and my jar was incompatible as I had 2.4.3 version of the jar. Now my program is up and running! Hope this helps someone who is facing the same problem.

Maven Jetty Run from Jar

Here is want I want to do. I created a maven project and configured the jetty plugin for it in eclipse...
So from Eclipse if I do run and set the maven goal there to be jetty:run it runs my project in jetty on the port specified in web.xml. Now I want to build the jar file and when I do java -jar myapp.jar it will automatically call jetty:run.
How can I do this?
If you want to package your application so that you can hand it to someone and have them run it as a standalone application without having to go through deploying a war file into a web container, then that is a different concern from doing mvn jetty:run at development time, I will call that deployment time to avoid any confusion
At deployment time, we can't assume there will be maven on the machine, thus no mvn jetty:run, and even if there was, this would not work, unless we deliver the source code to run the build as in the development environment!
A standalone web application can be packaged by bundling the jetty jars in the application war along with a Main class to start jetty programmatically, and get it to run the application war. This relies on the fact that the file and directory structure of the WAR and JAR are different, and thus there is no significant overlap between the two, which is what makes this workaround possible, and it also leaves the option of deploying the war file in a web container possible
There is a maven plugin that embeds winstone which is another lightweight servlet container
For jetty, you may start by reading Embedded Jetty 7 webapp executable with Maven

Resources