I have a Spring Batch process that writes a .txt file. It works great, except for one thing. When it runs on a scheduler (zena), the output file gets written out to the wrong location because I have the path set up to be relative. Here's how I specify the location of the output file in the FlatFileItemWriter:
FlatFileItemWriter<Something> writer = new FlatFileItemWriter<Something>();
writer.setResource(new FileSystemResource(new File("..csv/output.txt")));
When I run without the scheduler, the file is written out to the correct directory:
/BatchJob/csv/output.txt
But when I run on the scheduler, the file gets written out to:
/Scheduler/Location/csv/output.txt
I tried using classPathResource:
writer.setResource(new ClassPathResource("output.txt", getClass()));
But then it tries to write the file to a directory location based on the name of the class package. Instead, I want to write the file to a specific directory path location, not based on the package name.
Read the Directory parameter from a property file and inject into your resource.
Related
I am currently working on a project using jmeter-maven plugin. I need to use a CSV data config file from which some variables are to be read during execution. Although the created JMX file works in the JMeter GUI, the same isn't working in non-gui mode.
From the logs, I was able to gather that the data file isn't being opened (stored) during execution in the non-gui mode, which on the other hand, it happens in the GUI mode leading to successful execution in GUI mode.
I have checked the path of the file (the absolute path of the file - with forward slashes), permissions of the file and all the parameters set in the CSV data config element in the jmx file created (it has proper path to the csv file) and I couldn't possibly get the reason on why the CSV file is not being used during execution in non-gui mode.
I have tried having the CSV file in the bin folder (giving the complete path of to the bin folder and just the file name - both methods), having the csv in the same path as the jmx file.
Any ideas on what I might be missing?
CSV Config Data CSV configuration Image
I developed a small program that takes as input some configuration parameters from a .cfg file and produces an output .txt file based on the values taken from the .cfg file.
While the program runs perfectly in eclipse, I receive a NullPointerException error when I create a JAR file of this program and try to run it. From my understanding I have to make the JAR access its internal files or try to receive the needed information (in this case the .cfg file) externally, e.g. create a resource folder next to the JAR file.
I have searched many related questions asked here but I got even more confused whether there is an optimal way to produce a JAR file that can access input files and produces output files. Should I modify my code to achieve this or there is another way?
For the record, I use FileReader and FileWriter to access and produce the files.
If your .cfg file is outside of the JAR file, it should work just as in Eclipse.
If you want to access it from inside of the JAR archive, then you should use a class loader to load it, instead of FileReader...
I have a Scala project that I want to export as a jar file so I can run it on another machine(I know how to export as a jar file). My main function reads in an existing input.json file and writes to a output.json file. The path where the the input.json is hard coded in my main and the path where the output.json will be written is hard coded as well. My goal is to export a jar file and pass in multiple input.json files to this jar file and my desire is the output.json file to be written to some directory. Basically, I want to have a large pipeline that feeds many different input.json files to this jar file and outputs all the output.json to some directory. I'm not too sure if this can be done, and if so how exactly?
Try to use the path from the configuration and from the environment variables and if the environment variable is not present it will pick up the path from the Configuration.
Change the environmental variable according to your needs and there you go.!
But in the case you want a whole directory to be taken as input containing multiple json files. Then in that case you have to implement a hack !
Read the directory path from the configuration file or environmental variable, and read it as directory, extract the list of names and perform operations on them inside a map !
I hope I answered your query!
I am loading my properties file using the class loader as follows.
Properties prop = new Properties();
prop.load(MyClass.class.getResourseAsStream("/Property.properties"));
Now, using this method I am able to read the properties file. I want to write some data to the property file. I don't know the path of the property file. How do I store the data to the property file then ?
Update
I tried the following, but it doesn't give me the correct path:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
I don't think you can in a generic way that would always work, because your properties file could be bundled inside a jar, etc. You can get the URL via getResource(String) and then do something with that URL, for example if it's a file URL, you could get the file name there.
URL u=MyClass.class.getResource("/Property.properties");
if ("file".equals(u.getProtocol()){
File f=new File(u.toURI());
}
But that wouldn't work in all cases.
I would write the modified value to a file in a well known location, and use the bundled Properties as the default value, that are overriden by the values in the file.
There are two parts to your question.
First, the reading part. You said: "I am loading my properties file ..." using the code you provided. This code treats the file as a "resource" and loads it using the class loader. The class loader mechanism in the Java Runtime comes into picture here. Roughly speaking, this mechanism searches for it in your application's current classpath and makes the input stream associated with first matching resource available to your code. It may be fine in your case, however, you should realize that if there are multiple properties files by the same name in different parts of your classpath (e.g. different JAR files having the same config file), then you may not know which file is being read. The only way to ensure that you are reading the right file from the classpath is to ensure that you have that config file in a unique place in your application's classpath.
This seems to work for you. Reading from a file is easier, than, say writing to a file.
In the second part, you want to write to a file. It's important to note that you should know the exact whereabouts of the file you are writing to. If you rather unknowingly convert it to an output stream, then you might end up trying to write to a stream that you are not allowed to write to. So, here, you should try to find the location (path) of the actual, physical file, for example, on a computer's hard drive. That path is something you should know before you write and run this program. Remember that a file always exists in a folder or a directory.
Your attempt:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
to find the location or path of the file you want to write to fails because when you do new File("Property.properties");, Java tries to refer to a file (does not do anything yet with the operating system) that resides in the Java Runtime's current working directory. This refers to the location given by System.getProperty("user.dir"). So, your propFile refers to a (hypothetical) file in that folder and the call to getAbsolutePath() prints its path. This is not the file that you want because you are trying to write to a file whose path you don't know. So, you should find the path of the file and then use a BufferedWriter backed by a FileWriter or BufferedOutputStream backed by a FileOutputStream to write to this file. Make sure that the file you want to write to exists and you have permission to write to it.
Essentially get the resource as an OutputStream, then pass it to the store() method of your Properties object.
Details here:
http://www.drdobbs.com/jvm/readwrite-properties-files-in-java/231000005
I work on a Java console application. There is a property in my application.properties file, which contains another file name as a value of a property, like
my.file.location=file:myDir/myFileName
In the code I try to get the file like this:
#Value("${my.file.location}")
private File myfileLocation;
If I start the application from the directory, which contains jar file, the file is resolved, but when I run my application from a different location, the file location is not valid.
I can't have this file on classpath, it must be external to the jar file.
How can I make the file path to be relative to my jar file and not to the current working directory?
I believe this has nothing to do with Spring right? You just want to load configuration file, that is inside your application, unpacked, so the user can modify it, ok?
First, you may try to always setup the working directory, which I believe is more "standard" solution. In windows you can make a link, that specifies the Start in section and contains the path to your jar file (or bat or cmd, whatever).
If you insist on using the jar path, you could use How to get the path of a running JAR file solution. Note, that the jar must be loaded from filesystem:
URI path = MySpringBean.class.getProtectionDomain().getCodeSource().getLocation().toURI();
File myfileLocation = new File(new File(path).getParent(), "/myDir/jdbc.properties");