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

2

6

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.

Fluttery answered 15/10, 2014 at 10:46 Comment(2)
What does "application crashes" exactly mean? Is there a stack trace? If yes, please add it to your question. Have you unzipped the jar files and checked what's in it? Are all files therein as expected and at the right place? Is the MANIFEST.MF OK?Margarito
Thank you @GeroldBroser for your comment; I completely rewritten the question with a minimal reproducible example. I hope this is clear enough. Best Regards,Fluttery
F
6

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.

Fluttery answered 17/10, 2014 at 14:47 Comment(1)
This helped me out greatly. Thanks. On minor note: You should mention that the maven-assembly-plugin is building a somewhat "shaded jar" and that the <classpathPrefix>lib/</classpathPrefix> property is unnecessary because the jar will have all the dependencies embedded within it. You only need this if you are using a "non-shaded" (light-weight) jar because the jar will reference the lib/ directory which exists beside the (light-weight) jar sans dependencies.Digestive
M
1

[As answer since too long for comment]

Maybe helpful for java.lang.NoClassDefFoundError:

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.

Margarito answered 16/10, 2014 at 19:35 Comment(1)
Thank you again @GeroldBroser, I found your links useful to understand more my problem, and you were right about the reason why code worked in Netbeans and not in the created jars. for the /main/testlog4j-1.0.jar!/log4j.xml, it is indeed there as the One-Jar plugin bundles the first jar into another. Anyway I switched to maven-assembly-plugin. You can see my answer.Fluttery

© 2022 - 2024 — McMap. All rights reserved.