How to set a Tomcat webapp classpath - java

Hello I have a webapp in Tomcat server on linux
I need to be able to tell it in what order to load the jars located in WEB-INF/bin.
I tried to set it up in the META-INF/MANIFEST.MF under Class-Path but it didn't work, and I've searched the web for a solution and did not find any.
(My project is not inside a war file)
(The solution to chane the jar filename to "aaaaaaaRealName.jar" is unacceptable)
(I'm using Tomcat 7 (I think its v7.0.27))
Ido

The tomcat loads jars in the following order (extract from here: http://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html):
bootstrap (JRE/lib/ext folder)
system (can't used to add yours)
webapp libraries (first WEB-INF/classes, then WEB-INF/lib)
common libraries (check the common.loader property , then tomcat instance/lib, then common tomcat folder/lib)
So if you want to specify the order, just put the jars in the right place.

Related

How do I configure embedded jetty to used war file in executable jar as resource

I have an executable jar with a war file in it. Running the jar extracts the war file and creates a WebAppContext from it using webAppContext.setWar(warFile). Although that works, it seems that webAppContext.setWarResource(warResource) should work. I've tried it creating a resource using new PathResource("file.war") which shows a path like "jar:file:/Users/.../jetty-1.0.0-jar-with-dependencies.jar!/file.war". Sounds promising and conventional, but when I try it I get "java.lang.IllegalArgumentException: not file: scheme". Do I really have to extract the war file or is there a trick?
That would be a nested jar content reference and no Java program can do that.
Option 1: use a live-war (aka an executable-war) instead.
This would be a war file that can be deployed traditionally if you want to, but can also be used standalone from the java command line (and will start it's own server if it needs to).
An example project is maintained by the Eclipse Jetty project at ...
https://github.com/jetty-project/embedded-jetty-live-war
Note: the live-war concept was inspired by work done by the Jenkins project and their live-war.
Option 2: eliminate the WAR file layer entirely in your JAR
Don't package the WAR contents in your JAR as a filename.war, consider using it as an exploded WAR (or war directory) instead.
Just unpack the WAR into your JAR file somewhere safe (like /META-INF/webapps/<app-id>/) and then reference that directory location in your JAR file instead.
Option 3: eliminate the need for the WAR concepts entirely
This is the number one most popular choice.
You deconstruct your WAR file into a ServletContextHandler with configured Servlets and Filters, this also eliminates the need for things like annotation scanning / bytecode scanning (which is quite complicated), you'll also not have to wrangle the nested / isolate classloader (your uber JAR file contains all of the classes and downstream dependencies needed to run your webapp), and this approach will definitely speed up your startup time.

How to configure log4j2 with Tomcat 8.5.15

I have log4j2 jars under $CATALINA_HOME/lib:
log4j-api-2.10.0.jar
log4j-core-2.10.0.jar
log4j-jul-2.10.0.jar
export JAVA_OPTS="${JAVA_OPTS} -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager"
In catalina.properties I've got common classloader and I tried to add log4j-jul-2.10.0.jar again even if it is already under the CATALINA_HOME/lib, but no success.
common.loader="${catalina.base}/lib","${catalina.base}/lib/.jar","${catalina.home}/lib","${catalina.home}/lib/.jar","/opt/tomcat/apache-tomcat-8.5.15/lib/log4j-jul-2.10.0.jar"
I have deleted logging.properties under Tomcat and add a new log4j2.xml to path
ERRORMESSAGE:
Could not load Logmanager "org.apache.logging.log4j.jul.LogManager"
java.lang.ClassNotFoundException: org.apache.logging.log4j.jul.LogManager
Any idea why LogManager is still missing or should I use some other jars instead. In another messages they are speaking juli.jar and extras, but in their case they have older Tomcat version, 6 or 7.
You just need to add the log4j2-api, log4j2-core and log4j2-appserver libraries into the Tomcat classpath, provide the log4j2 configuration file and remove the $CATALINA_BASE/conf/logging.properties from your installation.
This is most easily done by:
Creating a set of directories in catalina home named log4j2/lib and
log4j2/conf.
Placing log4j2-api-2.x.x.jar, log4j2-core-2.x.x.jar, and
log4j2-appserver-2.x.x.jar in the log4j2/lib directory.
Creating a file named log4j2-tomcat.xml, log4j2-tomcat.json,
log4j2-tomcat.yaml, log4j2-tomcat.yml, or log4j2-tomcat.properties
in the log4j2/conf directory.
Create or modify setenv.sh in the tomcat bin directory to include
CLASSPATH=$CATALINA_HOME/log4j2/lib/*:$CATALINA_HOME/log4j2/conf
You can force the applications that use the JUL framework to use log4j2 format changing the environment variable LOGGING_MANAGER. You can do this by adding in the setenv.sh file: LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager"
Remember that org.apache.logging.log4j.jul.LogManager is included in the log4j-jul-2.x.x.jar bridge which must be added to your classpath.
refs:
https://db-blog.web.cern.ch/blog/luis-rodriguez-fernandez/2019-03-keeping-your-logs-clean-apache-tomcat-9-log4j2-and-spring-boot
https://logging.apache.org/log4j/2.x/log4j-appserver/index.html
I know that this is a little late to answer this question, but I'm sure it could help someone struggling like me trying to configure tomcat so that it uses lo4j.
I've been working on something similar for the past 3 days, and I found out that the extras folder provided by tomcat's website are not what I need. But, you can still grab them using maven. I was able to configure tomcat so that it uses the mentioned jar files ( tomcat-extras-juli.jar and tomcat-extras-juli-adapters.jar ). Just remember to include the VM argument -Dlog4j.debug to make your life easier and catch errors quicker.
Maven repo: https://mvnrepository.com/artifact/org.apache.tomcat.extras/tomcat-extras-juli-adapters
I came upon the same problem after I included the mentioned jars provided by tomcat's repository. After a quick analysis I found that the interface org.apache.juli.WebAppProperties was not included in the jar file tomcat-extras-juli.jar which is utilized by the file org.apache.catalina.loader.WebappClassLoaderBase. After researching a bit more, I realized that the tomcat jar files are included in the Maven Repo. I downloaded the mentioned jar files under the same version of tomcat ( currently 8.5 ), plugged those jars in my tomcat installation and everything worked as expected. Now my version of tomcat uses log4j instead of juli.
log4j2 jars must be loaded along with bootstrap.jar (tomcat startup) and tomcat-juli.jar (logging)
These jars are present in CATALINA_HOME/bin directory and are responsible for
initialization of tomcat including logging.
In CATALINA_HOME/cataline.bat in case of windows, you will find below code -
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
Here, you should add log4j2 jars at the classpath so that when tomcat starts, these jars are there.
Create in tomcat\bin\ file setenv.bat and add to file:
set "CLASSPATH=%CLASSPATH%%CATALINA_BASE%\bin;%CATALINA_BASE%\bin\log4j-core-2.10.0.jar;%CATALINA_BASE%\bin\log4j-api-2.10.0.jar;%CATALINA_BASE%\bin\log4j-jul-2.10.0.jar"
copy jars files
log4j-api-2.10.0.jar
log4j-core-2.10.0.jar
log4j-jul-2.10.0.jar
to folder tomcat\bin\
create file log4j2.xml in tomcat\bin folder

Eclipse:Dynamic Web Project Is it Mandatory to include OJDBC.jar file in WEB-INF?

Recently While I was doing a Dynamic web project,I forgot to include OJDBC.jar in the WEB-INF folder.But the code ran file without showing any Class Not Found Exception.But when my friend did the same,Class not found exception was shown.Then when he included the OJDBC.jar in the WEB-INF folder,the code ran fine.I am not able to understand why this is the case.Is it not mandatory to include OJDBC file in WEB-INF folder?And we both used Apache Tomcat Server.
As you can see from the above screenshot,I experimented by not including OJDBC.jar in the WEB-INF folder.The code ran fine.Please tell me why this is the case?
Well, Eclipse builds the context's classpath joining libraries from several locations:
Of corse, the <tomcat_home>\lib\*.jar files.
The <project>\WEB-INF\lib\*.jar files.
... and also the deployment assembly entries (within the project's properties).
Check out every one of these and compare with your partner ones.

Setting embedded Jetty war from classpath

How I can set a war in an embedded jetty in a way that it can load from a classpath. Following is my current code snippet
webAppContext.setWar("hello.war");
Context :-
I want to secure my code other than obfuscation.so, I used Jetty to create a runnable jar and subsequently i used winrun4j to create an exe wrapper. The exe works fine when war file is found at same level but not otherwise even though i've embedded the war in winrun4j exe.
Problem:-
Is there any way that i can set the war in a way that it can pick it up from classpath rather than some pre-defined path.
Hope i communicated the problem statement in a lucid way.
Thankyou.
I came around the same and I always extract the war to a temporary location and then use the absolute path;
webAppContext.setWar("/path/to/temp/tmp262622522.war");
In any case Jetty will extract the war to a temporary location too, when starting the web app.

Tomcat - won't load my META-INF\services\javax.servlet.ServletContainerInitializer file?

I have a web project that has a \META-INF\services\javax.servlet.ServletContainerInitializer file with its content pointing to the fully qualified name of a class that implements the ServletContainerInitializer interface. I basically followed the example given here: http://nullhaus.com/2011/03/using-servlets-3-0-servletcontainerinitializer/
I put debug lines in my class that implements the ServletContainerInitializer interface and it never makes it there. Not even the default constructor...
My application folder structure is as follows:
\MyApp
\META-INF\services\javax.servlet.ServletContainerInitializer
\WEB-INF\classes\
... [list of classes and packages go here]
Any ideas what I need to check for??
Note 1: My Tomcat publishes from an exploded external folder that contains my application
Note 2: I started my Tomcat from Eclipse - if that makes a difference!
Well, I think that you'll need to wrap your initializer class (and it's services-related META-INF directory) into a separate *.jar and put it in the WEB-INF/lib.
This is a JAR service, so I guess it could have something to do with problems with discovering services in a *.war file. Moreover, it doesn't even help if you put your META-INF directory inside WEB-INF/classes and set unpackWAR=false in your Tomcat's server.xml.
HTH.
The first thing to check is that you are actually using Servlet 3.0 and not an earlier version. For Tomcat, this means that you must be using Tomcat 7.0.22
Second, make sure that the \META-INF\services\javax.servlet.ServletContainerInitializer file actually exists in the exploded war file.
Third, when in doubt, configure and start Tomcat directly (not from Eclipse) - I've seen developers have endless problems with configuration of Tomcat using the Eclipse plugin.
For tomcat to load the META-INF directory , it has to be in classes folder . If you are using maven project , just put the META-INF directory inside src/main/resources directory .. on mvn package the same will be copied to classes directory .. No need of separerate jar .. if jar is prefered you can use
HandlesTypes annotation ..
I would like to quote some good explanation from Mark Thomas <markt#apache.org> given on the user mailing list of Tomcat:
Service files are loaded by class loaders from the META-INF/services
directory.
*.jar!/META-INF/services
and
*.war/WEB-INF/classes/META-INF/services
are visible to class loaders
*.war!/META-INF/services
is not.
The servlet expert group recently discussed WAR vs JAR in the context of
Java 9 and mutli-version JARs. The conclusion was (I'm paraphrasing)
that WARs are not a specialised form of JAR and while they share a
common format a feature that is available to a JAR is NOT automatically
available to a WAR unless the Servlet spec (of Java EE spec) explicitly
states otherwise.
Containers are free to add container specific extensions if they wish
but they come with the usual (lack of) interoperability warnings.
http://mail-archives.apache.org/mod_mbox/tomcat-users/201808.mbox/

Categories