Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resource is not loading in executable Spring boot jar - How executable jar loads resources?

I am trying to run executable boot spring jar based on documentation provided here. I am expecting the resources will be copied to the executable jar on running

mvn clean package

Here is how I am running the .jar under my project folder

./my-application.jar

In my project I have a batch process that is running on startup where I am trying to load a resource defined under

src/main/resources/batch/request_customers.csv

Here is how I am loading the resource application.properties

data.customers.input=classpath:batch/request_customers.csv

class

import org.springframework.util.ResourceUtils;
@Component
public class DataManager {

    @Value("${data.customers.input}")
    private String usersExistingData;

    public File jsonCustomerData() throws FileNotFoundException {
        return  ResourceUtils.getFile(usersExistingData);
    }


}

error log

s]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.groupon.batch.CustomerItemReader]: Factory method 'reader' threw exception; nested exception is java.io.FileNotFoundException: class path resource [batch/request_customers.csv] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/Users/xxx/projects/myproject/target/myproject-0.0.2-SNAPSHOT.jar!/BOOT-INF/classes!/batch/request_customers.csv; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'job' defined in class path resource [com/mycompany/batch/BatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'job' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1' defined in class path resource [com/mycompany/batch/BatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Step]: Factory method 'step1' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reader' defined in class path resource 

I also tried following path

data.customers.input=src/resources/batch/request_customers.csv
data.customers.input=batch/request_customers.csv

When I run application using my IDE and spring plugin to resources are loaded without any issues.But fails when I run executable jar using ./my-application.jar

  • The question is how to make sure all resources are copies to jar when I package it ?
  • Do I need to do some other configuration to tell maven to copy resources as they are structured ?
  • How I can check if resources are packages into jar ? I can not extract jar for some reasons ?

It would be great to know how exactly I can build a executable jar that basically works like an executable.

UPDATE the file exists in the jar that should be loaded. I am not loading from an external file path.

BOOT-INF/classes/batch/request_customers.csv

Here is the solution

When you build a jar file and deploy to a path then you need to treat resources as on file system - relative paths will not magically load resources, which is what I was expecting. You have to open as stream and read them. Here is one way to do that

StringBuffer buffer = new StringBuffer();

BufferedReader inputStream =
        new BufferedReader(new InputStreamReader(resourceloader.getResource(file).getInputStream()));

String line = null;

while ((line = inputStream.readLine()) != null){
    buffer.append(line);
}
like image 529
amjad Avatar asked Sep 21 '16 10:09

amjad


People also ask

Does JAR file contain resources?

jar ) contain your executable classes and resource files. A jar can also contain other jar files, which is useful when your program needs some library which is packaged in a jar.

What is executable jar?

Jar files (Java ARchive files) can contain Java class files that will run when the jar is executed. A jar is an archiving format that not only stores directories and source files, but can be run as an executable as well.


2 Answers

You cannot get a file reference because the file is within a jar (not the filesystem).

The best you can do is read it as a stream using:

ResourceUtils.getURL(usersExistingData).openStream()
like image 62
linead Avatar answered Nov 14 '22 23:11

linead


Instead of ResourceUtil, consider using ResourceLoader as stated on ResourceUtil doc

Consider using Spring's Resource abstraction in the core package for handling all kinds of file resources in a uniform manner. org.springframework.core.io.ResourceLoader's getResource() method can resolve any location to a org.springframework.core.io.Resource object, which in turn allows one to obtain a java.io.File in the file system through its getFile() method. 

So your class should be something like this:

import org.springframework.core.io.ResourceLoader;
@Component
public class DataManager {

    @Autowired
    ResourceLoader resourceloader;

    @Value("${data.customers.input}")
    private String usersExistingData;

    public File jsonCustomerData() throws IOException{
        return  resourceloader.getResource(usersExistingData).getFile();
    }


}
like image 22
Gokhan Oner Avatar answered Nov 15 '22 01:11

Gokhan Oner