0

I've made a project in java, using Eclipse.

Here is the project structure:

enter image description here

When I'm running the project in Eclipse as a java application, it runs perfectly fine.

Now, I need to export it as a jar. So, I created the jar using the method described in 3rd answer on this link (answered by Fever):

Failing to run jar file from command line: “no main manifest attribute”

Here is the output of jar tf EventLogger.jar:

META-INF/MANIFEST.MF
com/
com/project/
com/project/eventLogger/
com/project/eventLogger/KafkaConsumerGroup.class
com/project/eventLogger/KafkaProducer.class
com/project/eventLogger/ConsumeConfig.class
com/project/eventLogger/ConsumerThread.class
com/project/eventLogger/Formatter.class
com/project/eventLogger/Execute.class
com/project/eventLogger/Config.class
com/project/eventLogger/package-info.class
com/project/eventLogger/ProdConfig.class
com/project/eventLogger/FormatConfig.class
resources/
resources/Config.properties
resources/ConsumerConfig.properties
resources/FormatterConfig.properties
resources/ProducerConfig.properties
resources/log4j.properties

Here is the manifest file:

Manifest-Version: 1.0
Built-By: vishrant
Class-Path: lib/json-simple-1.1.1.jar lib/junit-4.10.jar lib/hamcrest-
 core-1.1.jar lib/kafka_2.9.2-0.8.2.2.jar lib/jopt-simple-3.2.jar lib/
 kafka-clients-0.8.2.2.jar lib/log4j-1.2.16.jar lib/lz4-1.2.0.jar lib/
 metrics-core-2.2.0.jar lib/slf4j-api-1.7.6.jar lib/snappy-java-1.1.1.
 7.jar lib/slf4j-log4j12-1.6.1.jar lib/zkclient-0.3.jar lib/zookeeper-
 3.4.6.jar lib/jline-0.9.94.jar lib/netty-3.7.0.Final.jar lib/scala-li
 brary-2.9.2-RC3.jar
Build-Jdk: 1.8.0_74
Created-By: Maven Integration for Eclipse
Main-Class: com.project.eventLogger.Execute

and, here is the exception:

java.io.FileNotFoundException: ConsumerConfig.properties (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at com.project.eventLogger.ConsumeConfig.loadPropertiesFile(ConsumeConfig.java:34)
    at com.project.eventLogger.ConsumeConfig.<clinit>(ConsumeConfig.java:42)
    at com.project.eventLogger.Execute.main(Execute.java:18)
Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.project.eventLogger.Execute.main(Execute.java:18)
Caused by: java.lang.NullPointerException
    at com.project.eventLogger.ConsumeConfig.<clinit>(ConsumeConfig.java:47)
    ... 1 more

Seeing the exception, it is clear that it is not able to load ConsumerConfig.properties which is being done in ConsumeConfig.java.

Here is ConsumeConfig.java:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Properties;

/**
 * @author vishrant
 *
 */
public class ConsumeConfig {

    public static String zookeeper;
    public static String balance;
    public static String bootstrap_servers;
    public static String zk_session_to;
    public static String zk_sync;
    public static String auto_commit;
    public static String[] topics;
    private static String kafka_bin;
    private static final String PROPERTIES_FILE_PATH = "src/main/resources/ConsumerConfig.properties";

    private static Properties loadPropertiesFile() throws IOException {
        Properties properties = new Properties();
        InputStream in = new FileInputStream(PROPERTIES_FILE_PATH);
        properties.load(in);
        return properties;
    }

    static {
        Properties property = null;
        try {
            property = loadPropertiesFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        zookeeper = property.getProperty("ZOOKEEPER");
        balance = property.getProperty("BALANCE");
        bootstrap_servers = property.getProperty("BOOTSTRAP_SERVERS");
        zk_session_to = property.getProperty("ZK_SESSION_TO");
        zk_sync = property.getProperty("ZK_SYNC_TIME");
        auto_commit = property.getProperty("AUTO_COMMIT_INTERVAL");
        topics = property.getProperty("CONSUMER_TOPICS").split(",");
        kafka_bin = property.getProperty("KAFKA_BIN_PATH");
    }
}

Can someone tell me what is the problem and how to resolve this?

This runs perfectly well when run in Eclipse itself.

EDIT1:

Now, the exception is:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.project.eventLogger.Execute.main(Execute.java:18)
Caused by: java.lang.NullPointerException
    at java.util.Properties$LineReader.readLine(Properties.java:434)
    at java.util.Properties.load0(Properties.java:353)
    at java.util.Properties.load(Properties.java:341)
    at com.project.eventLogger.ConsumeConfig.loadPropertiesFile(ConsumeConfig.java:35)
    at com.project.eventLogger.ConsumeConfig.<clinit>       (ConsumeConfig.java:42)
    ... 1 more

line no 35:

props.load(resourceStream);

This is the code now:

private static final String PROPERTIES_FILE_PATH = "ConsumerConfig.properties";

private static Properties loadPropertiesFile() throws IOException {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Properties props = new Properties();
    InputStream resourceStream = loader.getResourceAsStream(PROPERTIES_FILE_PATH);
    props.load(resourceStream);
    return props;
}
Community
  • 1
  • 1
vish4071
  • 5,135
  • 4
  • 35
  • 65
  • 1
    Objects in a jar are **not** files and you can't use File based APIs (such as `FileInputStream`) to access them. Look at `Class.getResourceAsStream`. – greg-449 Mar 14 '16 at 08:54
  • Now You may copy paste the Method this should work. Otherwise there must be any configuration problem or `Resources` Folder is not available at his place. – Vikrant Kashyap Mar 14 '16 at 09:41
  • Yeas... @VikrantKashyap, that was indeed the problem. I changed the path to `resources/ConsumerConfig.properties` and it worked. – vish4071 Mar 14 '16 at 09:45
  • Can you tell, why this problem is there. How should I make the jar so that structure is good. – vish4071 Mar 14 '16 at 09:45

2 Answers2

1

I see the following problems to be the cause:

  • The jar file is not created correctly for a maven project because the directory resources will normally be not copied to the target directory as is, i.e., instead of

resources/Config.properties

it should look like without the resources directory:

Config.properties

directly under the root directory of the jar file.

  • The second point is you are using the following in your code

private static final String PROPERTIES_FILE_PATH = "src/main/resources/ConsumerConfig.properties";

This path will not be seen outside of your IDE (in this case Eclipse) because src/main/resources should not exist in the jar file as you could see in the list of your jar file.

  • The last point is, you should use getResourceAsStream() of the class loader as Vikrant Kashyap already pointed.
ujulu
  • 3,289
  • 2
  • 11
  • 14
  • Thanks for pointing out the problem in structure of my jar. I changed the path in the code from `ConsumerConfig.properties` to `resources/ConsumerConfig.properties` and it works just fine. – vish4071 Mar 14 '16 at 09:43
  • Can you tell, why this problem is there. How should I make the jar so that structure is good. – vish4071 Mar 14 '16 at 09:44
  • 1
    You should just use **mvn package** and the jar file will be created under the target directoy. – ujulu Mar 14 '16 at 10:05
  • Still one point: you can create the jar file also from within Eclipse: right click on the pom.xml file and click on **Run As > Maven install**, and the correct jar file will be created in the **target* directory. – ujulu Mar 14 '16 at 10:21
  • Thanks. The 1st one worked great. (Didn't try second) – vish4071 Mar 14 '16 at 14:48
0

try this

// Change Your File Path First.
private static final String PROPERTIES_FILE_PATH = "ConsumerConfig.properties";

private static Properties loadPropertiesFile() throws IOException {
    Properties properties = new Properties();

    // First way to load ResourceAsStream.
    // ClassLoader loader = Thread.currentThread().getContextClassLoader();
    // InputStream resourceStream = loader.getResourceAsStream(PROPERTIES_FILE_PATH);
    // Second way to load ResourceAsStream.
    InputStream resourceStream = ConsumeConfig.class.getResourceAsStream(PROPERTIES_FILE_PATH);
    properties.load(resourceStream);
    return properties;
}
toku-sa-n
  • 798
  • 1
  • 8
  • 27
Vikrant Kashyap
  • 6,398
  • 3
  • 32
  • 52
  • resourceName should be path or just the name? – vish4071 Mar 14 '16 at 09:04
  • It should only a File Name not the absolute path because in Maven Resource Folder is just a dummy Folder . It will not present in War File if we deployed as a `war` – Vikrant Kashyap Mar 14 '16 at 09:08
  • Replace Your Method with this .. you will not getting error probably – Vikrant Kashyap Mar 14 '16 at 09:16
  • Yeah...I did all that. I tried this is a separate project earlier which was not maven...maybe that is why it was not working. – vish4071 Mar 14 '16 at 09:21
  • Now, in this project, I've edited all and it works a charm when run form Eclipse. But again, when I create the jar, it gives a new (NullPointer) Exception, on the same line. – vish4071 Mar 14 '16 at 09:22
  • now FileNotFound is Gone.then problem with some other code. Your File is not Present. I think there is problem with Property keys which will not be found in File this might a reason for your `NULL Pointer Exception` – Vikrant Kashyap Mar 14 '16 at 09:24
  • Please see the Edited post. File is there and it works good in Eclipse, but not when I create jar. – vish4071 Mar 14 '16 at 09:30
  • I have added a new line in my answer. Now replace your function and try once again.. add this line `ClassLoader loader = Thread.currentThread().getContextClassLoader();` – Vikrant Kashyap Mar 14 '16 at 09:33
  • Thanks. I've got the error. Please revert your latest edit. Previous one works fine. – vish4071 Mar 14 '16 at 09:41
  • This code will also works fine. There are two ways to do that I have mentioning the second one too @vish4071 – Vikrant Kashyap Mar 14 '16 at 09:43
  • Yeah...I know. I said that because previous one was generic. No problem anyway. Thanks. – vish4071 Mar 14 '16 at 09:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106216/discussion-between-vikrant-kashyap-and-vish4071). – Vikrant Kashyap Mar 14 '16 at 09:47