Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven Java application crashes when running from command line but not from within the Netbeans IDE

Edit: Question Rewritten:

I created a new minimal example to illustrate my problem. First here is the source code of a simple class App.java:

package testlog4j.testlog4j;

import java.io.*;
import java.net.*;
import org.apache.log4j.*;
import org.apache.log4j.xml.*;

public class App 
{
    static Logger logger = Logger.getLogger(App.class);
    URL url = getClass().getClassLoader().getResource("log4j.xml");

    public static void main( String[] args )
    {
        App app = new App();
        DOMConfigurator.configure(app.url);
        System.out.println( "Hello World!" );
        System.out.println("Resource(.): " + App.class.getResource("."));
        System.out.println("Resource(): " + App.class.getResource(""));
        System.out.println("URL :" + app.url.toString());

        logger.info("INFO");
    }
}

Second, Here is the pom.xml file of the project

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>testlog4j</groupId>
<artifactId>testlog4j</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<name>testlog4j</name>
<url>http://maven.apache.org</url>

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>testlog4j.testlog4j.App</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

    <plugin>
        <groupId>org.dstovall</groupId>
        <artifactId>onejar-maven-plugin</artifactId>
        <version>1.4.4</version>
        <executions>
            <execution>
                <configuration>
                    <mainClass>testlog4j.testlog4j.App</mainClass>
                    <attachToBuild>true</attachToBuild>
                </configuration>
                <goals>
                    <goal>one-jar</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    </plugins>
</build>


<dependencies>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>3.8.1</version>
  <scope>test</scope>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>        
    <version>1.2.14</version>
</dependency>   
</dependencies>

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>
</project>

Third, I have my log4j.xml under src/main/resources folder:

<?xml version="1.0" encoding="iso-8859-1"?>
<!--<!DOCTYPE log4j:configuration PUBLIC-->
<!--"-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="true">

<appender name="default.console" class="org.apache.log4j.ConsoleAppender">
    <param name="target" value="System.out" />
    <param name="threshold" value="debug" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
    </layout>
</appender>
<appender name="main.file" class="org.apache.log4j.RollingFileAppender">
    <param name="file" value="log/main.log" />
    <param name="MaxFileSize" value="2MB" />
    <param name="append" value="true" />
    <param name="threshold" value="debug" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
    </layout>
</appender>

 <logger name="testlog4j.testlog4j.App" additivity="false">
    <level value="debug" />
    <appender-ref ref="main.file" />
    <appender-ref ref="default.console" />
</logger>


<root>
    <priority value="debug" />
    <appender-ref ref="default.console" />
    <appender-ref ref="main.file" />
</root>

OK, building the application and running in Netbeans works perfectly as expected logging out into both the console and a file under the log directory.

However, running from command line (both the normal jar and oneJar) doesn't work as you can see below:

java -jar testlog4j-1.0.jar

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at testlog4j.testlog4j.App.<clinit>(App.java:17)
    Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 1 more

java -jar testlog4j.1.0.one-jar.jar

log4j:ERROR Could not parse url [jar:file:/testlog4j-1.0.one-jar.jar!/main/testlog4j-1.0.jar!/log4j.xml]. 
java.io.FileNotFoundException: /testlog4j-1.0.one-jar.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method)
    at java.util.zip.ZipFile.<init>(ZipFile.java:215)
    at java.util.zip.ZipFile.<init>(ZipFile.java:145)
    at java.util.jar.JarFile.<init>(JarFile.java:154)
    at java.util.jar.JarFile.<init>(JarFile.java:91)
    at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:93)
    at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69)
    at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:84)
    at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122)
    at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:150)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:613)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:812)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
    at org.apache.log4j.xml.DOMConfigurator$2.parse(DOMConfigurator.java:612)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:711)
    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.apache.log4j.Logger.getLogger(Logger.java:117)
    at testlog4j.testlog4j.App.<clinit>(App.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.simontuffs.onejar.Boot.run(Boot.java:340)
    at com.simontuffs.onejar.Boot.main(Boot.java:166)
log4j:ERROR Could not parse url [jar:file:/testlog4j-1.0.one-jar.jar!/main/testlog4j-1.0.jar!/log4j.xml].
java.io.FileNotFoundException: /testlog4j-1.0.one-jar.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method)
    at java.util.zip.ZipFile.<init>(ZipFile.java:215)
    at java.util.zip.ZipFile.<init>(ZipFile.java:145)
    at java.util.jar.JarFile.<init>(JarFile.java:154)
    at java.util.jar.JarFile.<init>(JarFile.java:91)
    at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:93)
    at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69)
    at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:84)
    at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122)
    at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:150)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:613)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:812)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
    at org.apache.log4j.xml.DOMConfigurator$2.parse(DOMConfigurator.java:612)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:711)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:618)
    at org.apache.log4j.xml.DOMConfigurator.configure(DOMConfigurator.java:743)
    at testlog4j.testlog4j.App.main(App.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.simontuffs.onejar.Boot.run(Boot.java:340)
    at com.simontuffs.onejar.Boot.main(Boot.java:166)

Hello World!
Resource(.): null
Resource(): jar:file:/testlog4j-1.0.one-jar.jar!/main/testlog4j-1.0.jar!/testlog4j/testlog4j/
URL :jar:file:/testlog4j-1.0.one-jar.jar!/main/testlog4j-1.0.jar!/log4j.xml
log4j:WARN No appenders could be found for logger (testlog4j.testlog4j.App).
log4j:WARN Please initialize the log4j system properly.

Your help is highly appreciated.

like image 451
mtleis Avatar asked Oct 15 '14 10:10

mtleis


2 Answers

The first problem with NoClassDefFoundError was setting correct classpaths, I solved this by adding the maven-dependencies-plugin and included the class prefix attribute in the maven-jar-plugin.

For one-jar plugin; When building the one-jar file, DOMConfigurator.configure() method of log4j was not able to parse the log4j.xml file anymore (as can be seen in the question above). I was able to replace this by log4j.properties file and using the PropertyConfigurator.configure() method. Then the problem would be solved. However, OneJar is causing another problem for me. Since it builds the first executable jar into another jar; I will need to change my code to find the path of the parent executable jar to write log and properties files. For this reason, I changed into the maven-assembly-plugin using its non deprecated single goal. In this case I can also keep the nice log4j.xml file.

Below is the new pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>testlog4j</groupId>
  <artifactId>testlog4j</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <name>testlog4j</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>testlog4j.testlog4j.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.5.1</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/lib/</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4.1</version>

        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>testlog4j.testlog4j.App</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- bind to the packaging phase -->
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
    </dependency>
  </dependencies>

  <repositories>
  </repositories>
</project>

Moreover, I uploaded the testing project into github:

https://github.com/mtleis/simpleLog4jMaven

I Hope someone will find this useful.

like image 127
mtleis Avatar answered Nov 05 '22 13:11

mtleis


[As answer since too long for comment]

Maybe helpful for java.lang.NoClassDefFoundError:

  • 3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
  • java.lang.NoClassDefFoundError: How to resolve – Part 1.

I'm not too familiar with NetBeans but I can imagine that it works therein because NetBeans accesses your classes from target/classes and log4j from your local Maven repository, not from the created jars.

Have you unzipped the jar files and checked what's in it? Are all files therein as expected and at the right place? /main/testlog4j-1.0.jar!/log4j.xml seems not to be where it is expected.

like image 26
Gerold Broser Avatar answered Nov 05 '22 14:11

Gerold Broser