Logback include configuration not working with relative path - java

I am trying to place logback configuration outside war file and for this i hhave placed the logback file in the webapps folder to tomcat 7.
Project name : AnalyticsAPI
Path of logback.xml(the file inside the war) : /webserv/apache-tomcat-7.0.55_1/webapps/AnalyticsAPI/WEB-INF/classes/logback.xml
Path of external logback with actual configuration : /webserv/apache-tomcat-7.0.55_1/webapps/logback/logback-new.xml
The logback.xml in war is :
<configuration scan="true" scanPeriod="30 seconds">
<include file="../logback/logback-new.xml" />
</configuration>
I have given above path since i read the article that path should be relative to current working directory and current working directory in this case should be the context root of project(if i am right)
The error i am getting in the logs is :
12:41:09,834 |-INFO in
ch.qos.logback.core.joran.util.ConfigurationWatchListUtil#65b17009 - Adding
[file:/home/users/roshnig/../logback/logback-new.xml] to configuration watch list.
12:41:09,835 |-WARN in ch.qos.logback.core.joran.action.IncludeAction -
Failed to open [file:/home/users/roshnig/../logback/logback-
new.xml]

Related

Context.xml not recognized and not executed by Tomcat

after setting $CATALINA_HOME in this path /usr/local/cellar/tomcat/9.0.68/libexec, i put the file Context.xml with the same name as my war "warName.xml" in this path : /usr/local/Cellar/tomcat/9.0.68/libexec/work/Catalina/localhost.
here is the content of my file :
<Context>
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="/Users/user.name/Desktop/workspace/projectName/dev-resources/config" webAppMount="/WEB-INF/classes/"/>
</Resources>
</Context>
and when i deploy and launch the server i have not my dev-resources/config folder inside /WEB-INF/classes/ in my unzipped project.
the unzipped project has the following permissions :
drwxr-x---
i'am wondering if the process can not inject the configuration because of permissions problems
thanks

How to separate application config from AP in container on Kuberetes?

I want to deploy a application which use an extenal config on Kubernetes. I built a spring boot application to a war file and put it into websphere liberty. Then put application.properties in /config/config ( /config is shortcut of /opt/ibm/wlp/usr/servers/defaultServer) which I want my application to use.
I write a Dockerfile as below:
FROM websphere-liberty:19.0.0.6-javaee8
USER root
RUN mkdir -p /ibank-pv && chown -R 1001:0 /ibank-pv
RUN mkdir -p /config/config/ && chown -R 1001:0 /config/config
COPY --chown=1001:0 ibank.war /config/apps/
COPY --chown=1001:0 server.xml /config
COPY --chown=1001:0 application.properties /config/config/
USER 1001
CMD ["/opt/ibm/wlp/bin/server","run","defaultServer"]
Here is my server.xml. I set ${server.config.dir}/config as a config resource folder.
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<featureManager>
<feature>javaee-8.0</feature>
</featureManager>
<basicRegistry id="basic" realm="BasicRealm">
<!-- <user name="yourUserName" password="" /> -->
</basicRegistry>
<httpEndpoint id="defaultHttpEndpoint"
httpPort="9080"
httpsPort="9443" />
<applicationManager autoExpand="true"/>
<library id="configResources">
<folder dir="${server.config.dir}/config" />
</library>
<application location="ibank.war">
<classloader privateLibraryRef="configResources" />
</application>
</server>
And I add these code to read the application.properties in ${server.config.dir}/config.
public class IbankServlet extends HttpServlet {
private static final long serialVersionUID = 7526471155622776147L;
private final Properties config;
public IbankServlet() throws Exception {
InputStream is = getClass().getResourceAsStream("application.properties");
config = new Properties();
config.load(is);
}
}
However, when I start the server my application, it still read the application.properties which is in war file. What I have to do let my application use application.properties in ${server.config.dir}/config.
Is the issue that getClass().getResourceAsStream("relative-path") looks in the Java package of that specified class? That is, whatever subdirectory corresponds to the Java package of IbankServlet. In other words, is your application.properties within the WAR file buried down in a package subdirectory?
If so, you'll need to either change to getClass().getResourceAsStream("/application.properties") (with the leading slash), and move it to the classpath root in your WAR file, or have your Docker file copy it down into the correct subdirectory.
However, if your IbankServlet is actually not in a Java package at all, this probably isn't the issue.)
(But also, I admit, I'm not certain of the precedence if a file exists in both your WAR and in a "shared library".)

Specifying Log4j2 Configuration File When Using Executable JAR

I am having trouble specifying the Log4j2 config file location when using an executable JAR file. It works fine if I separate all the JARs, but when I try to combine them into one executable JAR file, for some reason the log4j2.xml file isn't picked up from the command line.
I've tried these two methods of specifying the location:
java -Djava.libary.path=..\bin -cp ..\config -jar MyApplication.jar
java -Djava.libary.path=..\bin -Dlog4j.configurationFile=..\config\log4j2.xml -jar MyApplication.jar
Neither of those are working. I've also tried adding the directory containing the config file to the classpath in the JAR's manifest file:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.2
Created-By: 1.7.0_21-b11 (Oracle Corporation)
Main-Class: com.abc.MyApplication
Class-Path: ../config/
I haven't had success with this method either. Any ideas what I might be doing wrong?
Thanks in advance for any help!
EDIT
Ah, I believe I mistook the problem. Originally, this was the error I was seeing in the command line output:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
But at some point while I was changing things, the error message changed without my realizing it to this:
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
So what I figured out was that even though the executable JAR I was building was including the log4j-core-2.1.jar and log4j-api-2.1.jar JARs inside of it and in the MANIFEST file's classpath, there was a problem. The way I wrote my ant file to combine the libraries into the single JAR I was creating was successfully copying over the directories and class files, but was not copying over the other types for some reason, which are also obviously necessary (e.g. Log4j-config.xsd, Log4j-events.dtd, etc.).
To fix this, I changed the way I was merging the JARs in my Ant build file to this:
<jar destfile="${dist}/${jarName}" basedir="${classes}"
excludes=".svn">
<!-- Merge this JAR with all the JARs in the lib directory, so that
we are only creating one distribution JAR that includes all the
libraries that you need. -->
<fileset dir="${classes}" includes="**/*.class" />
<zipgroupfileset dir="${lib}" includes="**/*.jar" />
<!-- Specify the manifest file of the JAR -->
<manifest>
<attribute name="Main-Class" value="com.abc.MyApplication"/>
<attribute name="Class-Path" value=". ${manifest.classpath}"/>
</manifest>
</jar>
And that fixed the issue and copied over all files from the JARs into my newly created JAR.
Once this issue was resolved, the second of the commands I posted above worked for specifying the location of the configuration file. (As noted by #rewolf below, the first command won't work because the classpath specified in the MANIFEST of the JAR overrides any classpath specified on the command line.
Thanks for your responses, they definitely helped me get on the right path toward figuring out my mistakes.
Something that isn't explained very well/obviously in the Java documentation is that if you're using an executable Jar, it will only use the Class-Path as specified in the Manifest file. It will not listen to the -cp or --classpath arguments.
-Dlog4j.configurationFile=directory/file.xml
should definitely work though. I'm assuming you're running on Windows given your slash direction. Are you sure you are running it from the correct relative directory?
Update
I just tried it in Windows with no problems. I used the following manifest:
Manifest-Version: 1.0
Built-By: andrew.flower
Build-Jdk: 1.7.0_67
Class-Path: lib/log4j-api-2.1.jar lib/log4j-core-2.1.jar
Created-By: Apache Maven 3.2.3
Main-Class: com.andrew_flower.test.Log4jTest
Archiver-Version: Plexus Archiver
The Log4j2 jars are located in a lib/ directory and the log4j2.xml is in the conf/ directory. I executed the following command, and it found the config successfully.
java -Dlog4j.configurationFile=conf\log4j2.xml -jar log4j2test1-1.0-SNAPSHOT.jar
For others who may have this issue...
Make sure your -Dlog4j.configurationFile options occur before your '-jar' not after. Might seem obvious, but saw that mistake once.
Try treating the file location as a url and see if that works. I.e. escape spaces with %20 etc. Also use 'file://path', replace backslashes with forwardslashes.
Windows paths can be written as file://c:/path/to/log4j2.xml
Hence if you have a log4j2.xml in your program folder for your exampleApp in C:\Program Files\ExampleApp then...
java.exe -Dlog4j.configurationFile=file://c:/program%20files/exampleapp/log4j2.xml -jar exampleApp.jar ...
...should work
I solved the problem of specifying the location of log4j2 configuration in a runnable Jar that I created from Eclipse by including this in my java code:
System.setProperty("log4j.configurationFile", "resources/log4j2.xml");
I have a package and so I needed to specify the path to my "resources" folder (in my "src" folder in Eclipse):
System.setProperty("log4j.configurationFile", "com/company/app/resources/log4j2.xml");
Notice I didn't include "src" in my path and I think it's the path in the "bin" folder that's required: ie in my case "com/company/app/resources/log4j2.xml"
My configuration file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level - %msg%n"/>
</Console>
<RollingFile
name="RollingFile"
fileName="${sys:logFilename}"
filePattern="${sys:logFilename}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</appenders>
<loggers>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
Also notice I dynamically assign the rolling log file path + name "${sys:logFilename}" by including this in my java code:
System.setProperty("logFilename", "logs/myApp.log");
In order to get these 2 dynamic System.setProperty assignments to work they need to execute before the "getLogger" statement and so my java code looks like:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MyTestLoggingClass {
public static Logger logger = null;
...................
setUpLogging();
...............
public static void setUpLogging() {
System.setProperty("log4j.configurationFile", "com/company/app/resources/log4j2.xml");
System.setProperty("logFilename", "logs/myApp.log");
logger = LogManager.getLogger(Logger.class.getName());
}
}
Having "logger" declared at the start of my class (but without invoking "getLogger" before my 2 System.setProperty statements) enables me to reference "logger" in other methods. I am obliged to initialise it though and so I chose "null" but then later update it with the "getLogger" statement - given this I can't make it "final" (can only assign it once) but can make it static - a constant class variable.
nb the 2 log4j2 jars I included in the build path are:
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
I had this issue with version 2.8 of Log4j2.
This was gone when the respective Log4j2 jars were replaced with version 2.6 of Log4j2.

Logback can't find logback.xml even though it exists (on the classpath)

I've an issue with logback. I set it up (using maven) and everything seems fine except that Logback reports it can't find the configuration file (but I'm able to log to the console using the default logger configuration).
[#|2013-07-03T07:55:30.843+0200|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=124;_ThreadName=Thread-2;|07:54:39,844 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
07:54:39,844 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
07:54:39,844 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
07:54:39,847 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
|#]
I put the configuration file (called logback.xml) into the src/main/resources folder of my Maven artifact (which is a WAR).
Interestingly, if I attempt to load the config from the classpath, I succeed:
Reader r = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("logback.xml"));
StringWriter sw = new StringWriter();
char[] buffer = new char[1024];
for (int n; (n = r.read(buffer)) != -1; )
sw.write(buffer, 0, n);
String str = sw.toString();
System.out.println(str);
Which prints my sample configuration file:
[#|2013-07-03T07:55:30.844+0200|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=124;_ThreadName=Thread-2;|<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root> </configuration>|#]
My pom.xml has the following entries:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
Which is packed as a WAR file (inside an EAR file). The location of the logback.xml inside the WAR file is as follows: WEB-INF/classes/logback.xml
Does anybody have an idea what's wrong with my setup?
Many thanks for your help
stupidSheep
The location within the WAR file is correct, WEB-INF/classes.
The logback configuration documentation talks about where the logback.xml file can be located within a war, but it doesn't mention anything about an EAR.
Could you please try the information at this link? I am wondering if it needs to be packed into the EAR in a specific way.
Glassfish 3 + ear + logback.xml
(edit: second link removed, didn't work)
Logback invokes very similar code to the code in your example, i.e.
getClassLoader().getResourceAsStream("logback.xml");
If logback cannot find logback.xml, then it must be that the resource is not visible to the class loader that loaded the logback class. This class loader is most probably different than the class loader that loaded your test code which can find logback.xml.
When you deliver the configuration file of the logging framework within an WAR works everything as expected and without any problems. But if you try this with an EAR something magically happens, the logging framework can’t find the configuration file. And it uses it’s default behavior.
I solved it doing the following:
Create a new folder directly under the EAR folder. For example, create
a new folder named "classes" --> MyEar/classes
Place your logback.xml file in this new folder:
MyEar/classes/logback.xml
In your WAR file's MANIFEST.MF file, add this new folder to the
classpath:
Manifest-Version: 1.0
Class-Path: classes
So I had similar problem where I had logback.xml in classpath but wasn't being included in the build process. I recently switched over to gradle. I was having issues initially with my resource files not included in the build even though I specifically added src/main/resources to sourceSet of build.gradle.
So my solution at the time was to put the types of files in the include:
includes = ["**/*.css", "**/*.wav", "**/*.mp3", "**/*.mp4", "**/*.png"]
Sometime passed and I noticed my logging config wasn't being applied. I spent a great deal of time tweaking the log and looking up the problem. I soon realized that the file wasn't being included.
String URL = "logback.xml";
System.out.println(ClassLoader.getSystemResource(URL));
I remembered I had to put the type of files in the include. I added the xml type and it worked.
sourceSets {
main {
resources {
srcDirs = ["src/main/java", "src/main/resources"]
includes = ["**/*.css", "**/*.wav", "**/*.mp3", "**/*.mp4", "**/*.png", "**/*.xml"]
}
}
}

Define Servlet Context in WAR-File

How can I tell e.g. Tomcat to use a specific context path when given my WAR-File?
Example:
I have a war file created by maven build and the resulting name of the file is rather long.
So I do not want the tomcat manager application to use the filename of the war as the context.
Supplying a context.xml in META-INF did not produce the desired results
I also found this in the documentation for the path attribute of Context:
The value of this field must not be set except when statically defining a Context in server.xml, as it will be inferred from the filenames used for either the .xml context file or the docBase.
So it does not seem to be the right way to tell the application-server what the path for my WAR should be.
Any more hints?
There are two important points in the the documentation of the Context Container:
In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml extension) will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar. The default web application may be defined by using a file called ROOT.xml.
Only if a context file does not exist for the application in the $CATALINA_BASE/conf/[enginename]/[hostname]/, in an individual file at /META-INF/context.xml inside the application files. If the web application is packaged as a WAR then /META-INF/context.xml will be copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to match the application's context path. Once this file exists, it will not be replaced if a new WAR with a newer /META-INF/context.xml is placed in the host's appBase.
So, when you bundle a META-INF/context.xml, the file gets renamed to the name of the WAR and this name becomes the context path, regardless of any path defined in the Context element.
I see thus two options here:
Either set the name of the generated war to a shorter name (I suggest using <finalName> over <warName> which is deprecated AFAIK):
<project>
...
<build>
<finalName>mycontext</finalName>
...
</build>
...
</project>
Or use the maven-tomcat-plugin for the deployment and set the context path in the plugin configuration:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<path>/mycontext</path>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
</project>
I found an easy solution to keep war file name and choose the context-path.
You just have to deploy your war outside of the Host's appBase and to create a link inside the appBase directory.
Ex. :
ln -sf ${CATALINA_HOME}/wars/myapp-0.0.8-SNAPSHOT.war ${CATALINA_HOME}/webapps/myapp.war
Ektor
You can set the path attribute of the <Context> element of your META-INF/context.xml.
Alternatively, you can configure maven to create the war artifact with a custom name:
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<warName>yourCustomWarName</warName>
</configuration>
</plugin>
........
</plugins>
</build>
In your project there is a folder META-INF, in that folder there is a context.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/myproject" />

Categories

Resources