Ticket #350 (closed enhancement: fixed)
Custom Log4J appender to startup classpath
| Reported by: | gdb | Owned by: | bruno |
|---|---|---|---|
| Priority: | minor | Milestone: | 0.4 |
| Component: | core/kauri-runtime | Version: | trunk |
| Keywords: | startup classpath | Cc: | kauri-discuss@… |
Description
I have a custom log4j appender developed to use in the startup of my kauri application.
But I could not find a possibility to add my jar to the startup classpath.
I ended up with adding my own classes to the existing log4j.jar in the kauri/lib dir.
Is it possible to provide something for this?
Thanks.
Change History
comment:2 in reply to: ↑ 1 ; follow-up: ↓ 3 Changed 3 years ago by gdb
I have tried to set the environment variable KAURI_CLI_CLASSPATH to /myPath/myJar.jar, but at the startup I still get the exception ClassNotFound?
comment:3 in reply to: ↑ 2 ; follow-up: ↓ 4 Changed 3 years ago by jgou
Replying to gdb:
I have tried to set the environment variable KAURI_CLI_CLASSPATH to /myPath/myJar.jar, but at the startup I still get the exception ClassNotFound
The KAURI_CLI_CLASSPATH is probably only used to start the launcher, but the launcher itself doesn't use it to build its classpath.
comment:4 in reply to: ↑ 3 ; follow-up: ↓ 5 Changed 3 years ago by mpo
Replying to jgou:
The KAURI_CLI_CLASSPATH is probably only used to start the launcher, but the launcher itself doesn't use it to build its classpath.
Yes, and no.
There is a minimal classpath (ie one single launcher-jar) given at the RuntimeCliLauncher? which is extended with wathever you provide in KAURI_CLI_CLASSPATH
The launcher in its turn will find in its jar some classloader.xml file (generated at build-time based on the pom) that describes the classloader to create for the actual kauri-runtime being launched.
Anyway, IIRC that 2nd classloader has the launcher-classloader as a parent, so anything you add to it via the environment variable mentioned should be available as well.
Which brings us back to the continued NCFException in your report:
Based on my understanding I'm suspecting the error is not really about the class in the jar itself, but about a class it depends upon (like log4j base classes? which are only applied to a classloader on a lower level)
Could you check that and report back please?
And if my suspicion is correct, could you add the needed dependency-jars to the environment variable as well (use the path-separator for your environment (win=; linux=:) and let us know if that makes the NCF go away?
If still needed we can consider some -D system property to the launcher for specifying additional jars to be added to the launcher-classpath.
comment:5 in reply to: ↑ 4 Changed 3 years ago by gdb
I have extended my environment variable as follow (with the log4j.jar):
set KAURI_CLI_CLASSPATH=%M2_REPO%\log4j\log4j\1.2.14\log4j-1.2.14.jar;%M2_REPO%\be\schaubroeck\ebestuur\ebestuur-utils\0.4-SNAPSHOT\ebestuur-utils-0.4-SNAPSHOT.jar
I'm working in Windows, my M2_REPO=C:\Users\gdb\.m2\repository.
But i still get the ClassNotFoundException? below when I start my application with the kauri.bat:
log4j:ERROR Could not create an Appender. Reported error follows.
java.lang.ClassNotFoundException: be.schaubroeck.ebestuur.utils.EBDailyRollingFileAppender
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.apache.log4j.helpers.Loader.loadClass(Loader.java:178)
at org.apache.log4j.xml.DOMConfigurator.parseAppender(DOMConfigurator.java:174)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurator.java:150)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfigurator.java:163)
at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOMConfigurator.java:425)
at org.apache.log4j.xml.DOMConfigurator.parseRoot(DOMConfigurator.java:394)
at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:829)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:712)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:618)
at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:470)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:122)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:88)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:664)
at org.kauriproject.runtime.cli.KauriRuntimeCli.<init>(KauriRuntimeCli.java:57)
at org.kauriproject.runtime.cli.KauriRuntimeCli.main(KauriRuntimeCli.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.kauriproject.launcher.RuntimeCliLauncher.run(RuntimeCliLauncher.java:79)
at org.kauriproject.launcher.RuntimeCliLauncher.launch(RuntimeCliLauncher.java:58)
at org.kauriproject.launcher.RuntimeCliLauncher.main(RuntimeCliLauncher.java:54)
log4j:ERROR Could not parse url [file:/D:/sources/taakplanner/ebestuur-launcher/log4j.xml].
java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:394)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurator.java:151)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfigurator.java:163)
at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOMConfigurator.java:425)
at org.apache.log4j.xml.DOMConfigurator.parseRoot(DOMConfigurator.java:394)
at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:829)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:712)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:618)
at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:470)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:122)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:88)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:664)
at org.kauriproject.runtime.cli.KauriRuntimeCli.<init>(KauriRuntimeCli.java:57)
at org.kauriproject.runtime.cli.KauriRuntimeCli.main(KauriRuntimeCli.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.kauriproject.launcher.RuntimeCliLauncher.run(RuntimeCliLauncher.java:79)
at org.kauriproject.launcher.RuntimeCliLauncher.launch(RuntimeCliLauncher.java:58)
at org.kauriproject.launcher.RuntimeCliLauncher.main(RuntimeCliLauncher.java:54)
comment:6 follow-up: ↓ 7 Changed 3 years ago by mpo
Hm, this needs more in depth testing (can you share your jar, possibly via private mail).
Next steps I think about now:
- try adding jars for slf4j and commons-logging too
- check if we do/can set the context-classloader (looking at the lines before the one triggering the NCF at http://svn.apache.org/viewvc/logging/log4j/tags/v1_2_14/src/java/org/apache/log4j/helpers/Loader.java?view=markup#l178
comment:7 in reply to: ↑ 6 Changed 3 years ago by gdb
I have tried to set the jars of slf4j and commons-logging too but it has no effect.
(jar is coming up)
comment:8 Changed 3 years ago by mpo
Well, you got me convinced we needed to go for an additional -D to the launcher, but checking up on the code I see the inheritance of the classloaders is indeed as expected... so things _should_ just work.
and they do: here is my attempt with the jar you send me:
$ export KAURI_CLI_CLASSPATH=/tmp/ebestuur-utils-0.4-SNAPSHOT.jar:~/.m2/repository/log4j/log4j/1.2.14/log4j-1.2.14.jar $ export KAURI_JAVA_ARGS=-Dkauri.logdir=/tmp $ kauri.sh run -o /tmp/kauri-log4j.properties [main] INFO org.kauriproject.runtime.info - Starting the Kauri Runtime. ... ... more - no errors ... [main] INFO org.kauriproject.runtime.info - Kauri Runtime started [August 17, 2010 12:22:47 PM CEST]
And I see the various different logfiles in the /tmp being created
Could you double check you don't have any typo's in your attempt?
comment:9 Changed 3 years ago by jgou
Geert and I had a look at this again, and yes... it works !
Some remarks though:
The KAURI_CLI_CLASSPATH is only used in the kauri.sh/bat scripts in kauri-trunk. The scripts that are packaged in the releases (and nightly builds) do mention it in the comments, but don't use it to expand the classpath.
But as it turns out, most attempts to get the custom appender going were done on a server, using the Tanuki wrapper scripts. This means the plain scripts aren't even used, but instead the launcher classpath is configured in the service-wrapper-common.conf. When packaging your kauri application with the kauri-package-plugin, you get a service-wrapper.conf file which you can use to customise the configuration. You can add jars to the classpath in that file, by adding e.g.
wrapper.java.classpath.3=/some/path/ebestuur-log.jar wrapper.java.classpath.4=%KAURI_HOME%/lib/log4j/log4j/1.2.14/log4j-1.2.14.jar
Note you have to start the classpath additions at 3, because otherwise you overwrite the config in the service-wrapper-base.conf .
And as a final note, I would like to point out that adding jars to the launcher classpath is not recommended as you can easily get into all sorts of classloading issues later. Also in valid use cases (as is the case here), you still have to make sure that you keep the added jars as minimal as possible.
comment:10 Changed 3 years ago by jgou
- Milestone changed from 0.4.1 to 0.4
Only thing left to do, is adding KAURI_CLI_CLASSPATH to the classpath in the startup scripts bundled in the releases (similar to the scripts in kauri-trunk).
I juist checked, the CLI script allows to have classpath-entries injected via the environment variable KAURI_CLI_CLASSPATH
Just give that a spin, and let us know how it works out.