unable to deploy spring boot app on tomcat [duplicate] - java

This question already has answers here:
Servlet 5.0 JAR throws compile error on javax.servlet.* but Servlet 4.0 JAR does not
(3 answers)
Deploying Spring 5.x on Tomcat 10.x
(1 answer)
Closed 1 year ago.
I was trying to deploy spring boot micro-service on the tomcat server but was unable to get any response. The url was showing 404 error then I decided to go from very basic so I created a simple spring boot project with Spring Boot Initializer. There I choose
war as packaging.
java version 16 (as I only have this on my machine).
Added Spring Web dependency.
With this setting spring initializer automatically added necessary stuff like war packaging, tomcat dependency, spring web dependency and also created ServletInitializer class for me.
After that I opened the downloading project in netbeans 12 and made just a few changes i.e.
Added main class in the pom.xml file with <start-class> tag and annotated main class with #RestController and exposed 1 endpoint which return simple string.
Then from the project's main folder I ran the command mvn package also tried mvn clean install as deployment with the 1st command was unsuccessful.
Here are my configuration
Environment Variables:
System Variables
CATALINA_HOME: D:\Inzimam Tariq\apache-tomcat-10.0.10.
JAVA_HOME: C:\Program Files\Java\jdk-16.0.2
Relevent values in Path Variable: C:\Program Files\Common Files\Oracle\Java\javapath, D:\Inzimam Tariq\apache-maven-3.8.2\bin, and C:\Program Files\Java\jdk-16.0.2\bin.
User Variable
MAVEN_HOME: D:\Inzimam Tariq\apache-maven-3.8.2\bin.
I'm using windows 10 64-bit. Tomcat manager shows the app as deployed but when I click on that it shows 404. My JDK folder does not show JRE folder so I searched over internet and found that Java does not include JRE now. I also tried to rename my war file to the project name as some articles suggested that i.e. abc.war from abc-0.0.1-SNAPSHOT but still error is the same.
Please can someone point me to the right direction? Regards

After Deploying your project war file in Tomcat, try to make the following changes in your POM.xml file. Then restart your tomcat. Probably it will work.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

Related

SLF4J Logback LoggerContext Conflicts

I am working on deploying a spring boot executable jar for my application. Im using SLF4J logging, and when I build and run inside of IntelliJ I have no issues.
However, when I try to run the .jar, from the command line I get a LoggerFactory is not a Logback LoggerContext but Logback is on the classpath exception.
It complains about the slf4j-log4j12-1.7.12.jar in two places /opt/mapr/lib/ and /opt/mapr/hadoop/hadoop-2.7.0/share/hadoop/common/lib/.
If i remove the jar from both places and run my app:
java -cp $(mapr classpath):MapRProducerApp-0.0.1-SNAPSHOT.jar org.springframework.boot.loader.PropertiesLauncher
it will then fail startup due to SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
I dont understand why it would fail saying faild to load the slf4j class when my apps .jar is built with that dependency through
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
In IntelliJ, I am bringing in all external dependencies that exist inside the /opt/mapr/lib folder, which includes the slf4j-log4j12-1.7.10.jar, but IntelliJ does not give the Logback LoggerContext error.
To recap here:
Building and running the jar on its own works, but will fail because it needs dependencies that exist inside the mapr classpath.
Running the jar with the mapr classpath fails because of the slf4j jar inside /opt/mapr/lib.
Removing that jar leads to another failure about a slf4j jar in /opt/mapr/hadoop/hadoop-2.7.0/share/hadoop/common/lib/.
Removing that jar then fails the app because it now cannot find any slf4j binding.
Is there something im missing? Do I need to package my app a certain way so it does not include the SLF4J dependency?
I'm not clear about your <dependencies> hierarchy, but by adding <exclusion> you can simply resolve the conflict.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
If you are using Spring-boot actuator, only exclusion of spring-logging might not help.
You will have to provide logging for it. Spring Boot support log4j for logging configuration.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Refrence: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.logging

Google App Engine Standard env - not found controller method - Spring Boot app

I was trying to deploy Spring Boot application on Google App Engine (standard environment). At first I cloned example app from this nice tutorial https://springframework.guru/spring-boot-web-application-part-4-spring-mvc/
For example I called http://localhost:8080/products and template with data was displayed.
So everything ran without problems, I was able to call all controller methods locally. Then I decided as experiment to deploy it on GAE. I adjusted pom.xml according to instructions from here https://github.com/GoogleCloudPlatform/getting-started-java/tree/master/appengine-standard-java8/springboot-appengine-standard
It means I excluded Tomcat dependency, changed packaging from jar to war, created appengine-web.xml file etc. As next step, I created GAE project in GAE console and copied APP ID into appengine-web.xml. Then I ran mvn clean package and war was created in target folder. Finally I started with GAE deployment and it also went smoothly without errors.
My app is now deployed on this URL https://20180109t135551-dot-oe-gae-test.appspot.com/
If you try it, you will see Hello World in browser. But if I try to call /products controller method like this https://20180109t135551-dot-oe-gae-test.appspot.com/products I get "not found" error.
Can you give me advice on which URL should I call my controller methods? Did I forget to implement something like web.xml servlet mapping? Or is it some specific Spring Boot - Google App Engine problem?
I will be grateful for any hint.
Thank you all in advance
Following this steps translates into the following for the code:
In pom.xml, change <packaging>jar</packaging> to <packaging>war</packaging>
In the package guru.springframework add this class:
Code:
package guru.springframework;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootWebApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebApplication.class, args);
}
}
Remove Tomcat Starter:
Find this dependency in the POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
And add these lines:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Exclude Jetty dependencies and include the Servlet API dependency:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
Add the App Engine Standard plugin:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.1</version>
</plugin>
Add a file called appengine-web.xml in src/webapp/WEB-INF with these contents:
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<threadsafe>true</threadsafe>
<runtime>java8</runtime>
</system-properties>
</appengine-web-app>
Exclude JUL to SLF4J Bridge by locating this dependency in the pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
and modifying it this way:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Avoiding out of memory errors:
In src/main/resources add a logging.properties file with:
.level = INFO
and inside src/main/webapp/WEB-INF/appengine-web.xml paste this:
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/classes/logging.properties" />
</system-properties>
EDIT:
For steps 3 and 7 you can also go to the project explorer (in case you're using Eclipse) and navigate to Libraries -> Maven dependencies and select each library individually (jul-to-slf4j-1.7.25 and spring-boot-starter-tomcat-1.5.3.RELEASE in my case). Right click on each library and go to Maven -> Exclude Maven artifact... And click Ok. This will have the same effect on the POM as editing.

Running Java application on Tomcat

I downloaded from github http://websystique.com/spring-boot/spring-boot-angularjs-spring-data-jpa-crud-app-example/ and import as maven and I cannot add this app to tomcat.
If i changed packaging from jar to war, I can add, but get 404 on localhost:8080/SpringBootCRUDApp
How can i run this app?
You do not need to add it to tomcat. Spring Boot uses a public static void main entry-point that launches an embedded web server for you. So just run main method.
In Your Application, you already added Springboot-starter-web Dependency in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
And packaged your application as "jar" as below in pom.xml
<packaging>jar</packaging>
"spring -boot-starter-web" dependency has inbuilt embedded Tomcat container, so you don't need to add anything in Tomcat container
You can run your application with below command in cmd
java -jar SpringBootCRUDApplicationExample.jar
<!-- marked the embedded servlet container as provided -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
use this example for your reference.

Getting NoSuchMethodError:javax.servlet.ServletContext.getVirtualServerName()

I am facing an issue during deployment of a service in Tomcat 8. Getting following error :
Caused by: java.lang.NoSuchMethodError:
javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String;
at org.apache.tomcat.websocket.server.WsServerContainer.(WsServerContainer.java:149)
at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:131)
at org.apache.tomcat.websocket.server.WsSci.onStartup(WsSci.java:47)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5244)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 10 more
Method getVirtualServerName was introduced in Servlet 3.1 and after extracting MANIFEST.MF from my servlet-api jar I got following details :
Specification-Title: Java API for Servlets
Specification-Version: 3.1
Specification-Vendor: Sun Microsystems, Inc.
Implementation-Title: javax.servlet
Which says that its having 3.1. So is there any other reason for this error? Please help
Check all your Maven (or equivalent) dependencies and make sure that you - or most likely another dependency - are not pulling in a pre-3.1 version of the javax.servlet / servlet-api that may be taking precedence over what's in your Tomcat 8. If you've manually deployed, make sure you haven't manually copied any servlet-api JARs into Tomcat itself.
See: https://stackoverflow.com/a/26232535/954442
The method getVirtualServerName has been added in ServletContext in Servlet 3.1. See the java doc's method getVirtualServerName.
This problem has 3 primary causes:
Your servlet version is older than 3.1.
Some other jar has the servlet with a version older than 3.1.
Your tomcat version is older than 8
to solve it, you can try the below way.
I. Check your pom.xml for the code below.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
if your pom.xml has the above code, it would still has that problem. you can do the second way.
II. to check your other jar has refer to the javax.servlet-api jar. for example, the org.apache.santuario has refer to the javax.servlet-api jar. the pom.xml:
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>1.4.3</version>
</dependency>
but when you look at the maven dependencies, it refer to the javax.servlet-api jar whose version is 2.3 older than 3.1.
so you should exclude the 2.3 version. pom.xml:
<!-- exclude servlet-api 2.3 jar-->
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>1.4.3</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- servlet-api 3.1 version has getVirtualServerName() -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
III. spring boot run the default tomcat 7. so define your tomcat version 8 instead of tomcat 7. so add the code your pom.xml:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<tomcat.version>8.5.5</tomcat.version>
</properties>
I had this error on IntelliJ with maven after updating IntelliJ.
I could run the tests with maven but not from my IDE.
I solved the problem by removing the ./idea and project.iml files and reloading the project.
If you have used this dependency:
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.23.0</version>
</dependency>
Then please exclude as below:
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.23.0</version>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>org.mortbay.jetty</groupId>
</exclusion>
</exclusions>
</dependency>
Spring boot will run tomcat 7 per default, you have to override maven build tomcat.version in your pom.xml. See below to run tomcat 8.0.30
<properties>
<tomcat.version>8.0.30</tomcat.version>
</properties>
Should fix your problem.
Solved
On my mac with java 8 was facing issue with downloaded tomcat from site and unzip.
My issue got solved because there was a extra servlet-api.jar file which was getting picked up. It was coming from
/Library/Java/Extensions/servlet-api.jar
For finding it in your system you can use
sudo find / -name servlet-api.jar
Removed it by backing it up somewhere else.
I was following this for intallation
https://gist.github.com/ddanailov-nmdp/c97aba2ca926b9627f6b4f7174083a32
Assuming this problem appears when you ran the application in Eclipse.
Use Dependency Hierarchy view to search for servlet-api in pom.xm
After a huge pain & sifting through all these stackoverflow answers the only thing that ended up working for me was downgrading from tomcat8 to tomcat7. I know this isn't an ideal solution, and perhaps it was just a fresh install of tomcat that solved my problem. If all else fails give that a shot.
I attach gradle style dependencies code.
dependencies {
compileOnly("javax.servlet:javax.servlet-api:3.1.0")
This surely has something to do with the version of javax.servlet and version of Tomcat.
In my case, it went away when I declared javax.servlet dependency in gradle with no version. Like this -
compile('javax.servlet:servlet-api')

Configure external libraries as Glassfish modules

I have several OSGI bundles and WAR packages which use external libraries:
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>osgi-cdi-api</artifactId>
<version>3.1-b41</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
Instead of building the libraries into every OSGI bundle and WAR package is it possible to copy these libraries into /modules directory of the Glassfish server. I suppose that it's possible to use only one copy without any problem?
EDIT
I found that these libraries can be deployed as modules in Glassfish with the command:
[root#Testserver bin]# sh asadmin add-library /opt/primefaces.jar
But then for example in a simple WAR package what I need to modify in order to use Glassfish modules? The WAR package must be configured to use external libraries I suppose?
I don't think the problem is in your war file, but to be sure you can check the MANIFEST file. If the Import-Package headers are correct, there isn't anything you can do from the war file. If that's the case, there must be a way to convince Glassfish to make a module visible to a webapp (I'm no Glassfish expert, sorry).
Otherwise, fix the Import-Package headers (you can do that manually for now).
You can take a look at this section of glassfish documentation, called Module and Application Versions:
http://docs.oracle.com/cd/E26576_01/doc.312/e24929/overview.htm#gkhhv
"Application and module versioning allows multiple versions of the same application to exist in a GlassFish Server domain, which simplifies upgrade and rollback tasks. At most one version of an application or module can be enabled on a server any given time. Versioning provides extensions to tools for deploying, viewing, and managing multiple versions of modules and applications, including the Administration Console and deployment-related asadmin subcommands. Different versions of the same module or application can have the same context root or JNDI name. Use of versioning is optional."

Categories

Resources