I have a really strange problem in a Java webstart application. I'm using slf4j and logback for my logging framework but when one of my users runs the webstart application he gets a log4j warning message! I'm not including log4j jars in the webstart application. Where can log4j possibly be coming from and how do I find out? I cannot import any log4j classes and call their methods because I cannot compile against a jar file I don't have.
Here are some details:
slf4j 1.7.12 logback classic and core 1.1.3
The main class looks something like this:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyMain {
static {
String classpath = System.getProperty("java.class.path");
System.out.println("CLASSPATH = " + classpath);
}
private final static Logger LOG = LoggerFactory.getLogger(MyMain.class);
public void static main( String args[] ) {
// do stuff...
}
}
The output of this program on my user's Mac OS X Yosemite 10.10.3 is (remember it is a webstart program and there is a JNLP file that is launched from a browser):
CLASSPATH = /Library/Internet Plugins/JavaAppletPlugin.plugin/Contents/Home/lib/deploy.jar
log4j:WARN No appenders could be found for logger (MyMain).
log4j:WARN Please initialize the log4j system properly.
Here is the JNLP file:
<jnlp spec="6.0" codebase="http://example.com/mymain">
<information>
<title>MyMain</title>
<vendor>My Business</vendor>
<homepage href="http://www.example.com"/>
<description>My Application</description>
<description kind="short">GUI Tool</description>
<icon href="resources/your.appicon.gif"/>
<icon kind="splash" href="resources/your.splashicon.gif"/>
<offline-allowed/>
</information>
<resources>
<j2se version="1.8+" max-heap-size="1024M"/>
<jar href="mymain.jar" main="true"/>
<jar href="tsallperspectives63dep.jar"/>
<jar href="activation-1.1.jar"/>
<jar href="antlr-runtime.jar"/>
<jar href="appframework-1.0.3.jar"/>
<jar href="asm-all-repackaged-2.1.88.jar"/>
<jar href="asm-all-repackaged-2.2.0-b21.jar"/>
<jar href="batik.jar"/>
<jar href="beansbinding-1.2.1.jar"/>
<jar href="cglib-2.1.88.jar"/>
<jar href="cglib-2.2.0-b21.jar"/>
<jar href="common.jar"/>
<jar href="commonj.sdo-2.1.1.jar"/>
<jar href="commons-beanutils-1.8.3.jar"/>
<jar href="commons-codec-1.6.jar"/>
<jar href="commons-lang3-3.4.jar"/>
<jar href="commons-logging-1.1.3.jar"/>
<jar href="derbyclient.jar"/>
<jar href="dom4j-1.6.1.jar"/>
<jar href="eclipselink-2.5.0.jar"/>
<jar href="guava-14.0.1.jar"/>
<jar href="hk2-api-2.1.88.jar"/>
<jar href="hk2-api-2.2.0-b21.jar"/>
<jar href="hk2-locator-2.1.88.jar"/>
<jar href="hk2-locator-2.2.0-b21.jar"/>
<jar href="hk2-utils-2.1.88.jar"/>
<jar href="hk2-utils-2.2.0-b21.jar"/>
<jar href="httpclient-4.3.5.jar"/>
<jar href="httpcore-4.3.2.jar"/>
<jar href="iText.jar"/>
<jar href="javaee-api-7.0.jar"/>
<jar href="javax.annotation-api-1.2.jar"/>
<jar href="javax.inject-1.jar"/>
<jar href="javax.inject-2.1.88.jar"/>
<jar href="javax.inject-2.2.0-b21.jar"/>
<jar href="javax.mail-1.5.0.jar"/>
<jar href="javax.persistence-2.1.0.jar"/>
<jar href="javax.ws.rs-api-2.0.jar"/>
<jar href="jcommon-1.0.17.jar"/>
<jar href="jersey-client-2.0.jar"/>
<jar href="jersey-client-2.4.1.jar"/>
<jar href="jersey-common-2.0.jar"/>
<jar href="jersey-common-2.4.1.jar"/>
<jar href="jfreechart-1.0.14.jar"/>
<jar href="jfreesvg-2.1.jar"/>
<jar href="jsse.jar"/>
<jar href="jul-to-slf4j-1.7.12.jar"/>
<jar href="junit-3.8.1.jar"/>
<jar href="logback-classic-1.1.3.jar"/>
<jar href="logback-core-1.1.3.jar"/>
<jar href="ojdbc6.jar"/>
<jar href="ojpse.jar"/>
<jar href="oraclepki.jar"/>
<jar href="oraclepki103.jar"/>
<jar href="osdt_cert.jar"/>
<jar href="osdt_core.jar"/>
<jar href="osgi-resource-locator-1.0.1.jar"/>
<jar href="poi.jar"/>
<jar href="serializer.jar"/>
<jar href="slf4j-api-1.7.12.jar"/>
<jar href="sso.jar"/>
<jar href="swing-layout-1.0.4.jar"/>
<jar href="swing-worker-1.1.jar"/>
<jar href="xalan.jar"/>
<jar href="xmlbeans-2.3.0.jar"/>
</resources>
<application-desc main-class="MyMain">
<argument>-h</argument>
<argument>example.com</argument>
<argument>-u</argument>
<argument>user</argument>
<argument>-p</argument>
<argument>pass</argument>
</application-desc>
<security>
<all-permissions/>
</security>
</jnlp>
Note, there is a commons-logging jar that is a transitive dependency of some other jar (I'm not sure which). I don't think this is related.
Now, I also have Mac OS X Yosemite 10.10.3 and I do not get any warning from log4j... I get what I expect for output:
CLASSPATH = /Library/Internet Plug-ins/JavaAppletPlugin.plugin/Contents/Home/lib/deploy.jar
20:51:43,748 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
20:51:43,750 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
20:51:43,750 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:http://example.com/mymain/mymain.jar!/logback.xml]
I know of two other Mac OS X systems that properly run this webstart app and no others that fail like this one user's system.
All systems are running Java 1.8.0 update 45.
The only possible thing I can think of is that my user's system has some other java application that has installed log4j in a location that is loaded on the classpath or by Java webstart and this is loading before my webstart application. Possibly this jar is in /Library/Java/Extensions or ~/Library/Java/Extensions.
How do I find out where this log4j message is coming from? As in... which jar file and where is that jar file stored on the filesystem?
To find out what jar or classpath entry has the slf4j bridge/implementation use the following code in your MyMain
.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.ILoggerFactory;
public class MyMain {
static {
ILoggerFactory lf = binder.getLoggerFactory();
Class lfc = lf.getClass();
System.out.println(lfc.getResource(lfc.getSimpleName() + ".class"));
}
private final static Logger LOG = LoggerFactory.getLogger(MyMain.class);
public void static main( String args[] ) {
// do stuff...
}
}