Java Spring Boot - Read a file from the Resources folder inside a .jar

3

I am writing a class that will read an ETL Pentaho Kettle (transformation). I put the file that the class will read in the Resources / KTR folder.

But when I try to run the code as a java (java -jar) application, I get an error saying that the file does not exist.

However, it is trying to read the file from the local disk and not from within my .jar.

How do I read the file from within .jar?

I'm using Spring Boot 2.1.0.BUILD-SNAPSHOT and Java 1.8.

public class run_tranform {

 public static void main( String[] args ) throws IOException
{
 String file="src/main/resources/KTR/transformation.ktr";

    try {
        KettleEnvironment.init();
        //TransMeta metaData = new TransMeta(file.getPath());
        TransMeta metaData = new TransMeta(file);
        Trans trans = new Trans( metaData );
        trans.execute( null );
        trans.waitUntilFinished();
        if ( trans.getErrors() > 0 ) {
            System.out.print( "Error Executing transformation" );
        }
    } catch( KettleException e ) {
        e.printStackTrace();
    }
   }

 }
    
asked by anonymous 28.08.2018 / 14:12

1 answer

1

First, I suggest you, follow the language conventions and instead of naming your class as run_transform , name it as RunTransform .

You can get a InputStream for the resource within the JAR by using method getResourceAsStream with try-with syntax -resources like this:

String resource = "/KTR/transformation.ktr";
try (InputStream is = RunTransform.class.getResourceAsStream(resource)) {
    // ...
}

However, the class TransMeta does not have a constructor that only receives a InputStream or only a Reader instead of a File . There is only one constructor with the parameters TransMeta(InputStream, Repository, boolean, VariableSpace, OverwritePrompter) :

    public TransMeta(InputStream xmlStream, Repository rep, boolean setInternalVariables, VariableSpace parentVariableSpace, OverwritePrompter prompter ) throws KettleXMLException
    {
        loadXML( XMLHandler.loadXMLFile(xmlStream, null, false, false), rep, setInternalVariables, parentVariableSpace, prompter);
    }

So, come on, let's have a look at constructor that you are using, which gets File :

   public TransMeta(String fname) throws KettleXMLException
    {
        this(fname, true);
    }

This calls a another builder :

    public TransMeta(String fname, boolean setInternalVariables) throws KettleXMLException
    {
        this(fname, null, setInternalVariables);
    }

Calling plus another :

    public TransMeta(String fname, Repository rep, boolean setInternalVariables ) throws KettleXMLException
    {
        this(fname, rep, setInternalVariables, null);
    }

Calling yet another :

    public TransMeta(String fname, Repository rep, boolean setInternalVariables, VariableSpace parentVariableSpace ) throws KettleXMLException
    {
        this(fname, rep, setInternalVariables, parentVariableSpace, null);
    }

One more :

   public TransMeta(String fname, Repository rep, boolean setInternalVariables, VariableSpace parentVariableSpace, OverwritePrompter prompter ) throws KettleXMLException
    {
        // ... Um monte de coisas aqui
    }

In this last constructor, the signature is almost the same as the desired constructor, except that the first parameter is String instead of InputStream . In both the constructor you call and the desired one, there is a call to a loadXML method. In the desired construct, as the first parameter to this method, we have this:

XMLHandler.loadXMLFile(xmlStream, null, false, false)

This method returns a Document . The constructor with String loads the Document of the file and uses it to call the loadXML method.

It is concluded that you have to replace this:

TransMeta metaData = new TransMeta(file);

So:

TransMeta metaData = new TransMeta(stream, null, true, null, null);

Your resulting code gets this:

import java.io.IOException;
import java.io.InputStream;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;

public class RunTransform {
    public static void main(String[] args) throws IOException {
        String resource = "/KTR/transformation.ktr";
        try (InputStream is = RunTransform.class.getResourceAsStream(resource)) {
            KettleEnvironment.init();
            TransMeta metaData = new TransMeta(stream, null, true, null, null);
            Trans trans = new Trans(metaData);
            trans.execute(null);
            trans.waitUntilFinished();
            if (trans.getErrors() > 0) {
                System.out.print("Error Executing transformation");
            }
        } catch (KettleException e) {
            e.printStackTrace();
        }
    }
}
    
29.08.2018 / 06:58