How to avoid resource leaks using FileSystemResource in Drools 7.73.0? - java

I'm currently working with Drools 7.73.0, and seem to be running into a file lock issue when adding a KieModule to KieServices repository, using just a file path to a kjar file that exists on a local file system. It appears that the file path resource needs to be closed after adding it to the repository, however there does not appear to be a close method available.
The code I am currently using to load the kieModule from the kjar file into the repository is as follows:
String pathKjar = "pathToKjarFile.kjar";
...
KieServices ks = KieServices.Factory.get();
Resource resource = ks.getResources().newFileSystemResource(pathKjar);
ks.getRepository().addKieModule(resource); //<-- pathKjar is locked at this line
KieContainer kc = ks.newKieContainer(releaseId);
...
File testFile = new File(pathKjar);
testFile.delete(); //<-- pathKjar is still locked, delete always returns false
As noted above, the line of code ks.getRepository().addKieModule(resource); puts a lock on the resource, while it is in use, however I have not been able to find a way to close the resource afterwards, leaving the resource open.
What is the proper way to close the Resource?
Note, I was able to use an inputstream to accomplish the same thing, and the resource does close successfully using that method, and all seems to work as expected. This question is solely on how to properly use newFileSystemResource with a String path to the file location, and ensure there are no resource leaks.

I've tried to reproduce the problem that you're reporting but in all honesty I couldn't. In particular I quickly modified this example by putting the jar file returned by the getFile() method into a variable before passing it to the newFileSystemResource() one. Then trying to delete that file at the end of the test works as expected for me and returns true.
In case this problem persists I suggest you to open a ticket in the Drools tracking system and attach a complete reproducer.

Related

Getting Error while Reading Excel Using Spring-batch-excel

I am using Spring-batch-excel for reading a excel file in my new application. It is configured as a batch job and triggered using JobManager. Now i getting this error.
InputStream MUST either support mark/reset, or be wrapped as a PushbackInputStream
Caused by: java.lang.IllegalStateException: InputStream MUST either support mark/reset, or be wrapped as a PushbackInputStream
at org.springframework.batch.item.excel.poi.PoiItemReader.openExcelFile(PoiItemReader.java:82) ~[spring-batch-excel-0.5.0-SNAPSHOT.jar:?]
at org.springframework.batch.item.excel.AbstractExcelItemReader.doOpen(AbstractExcelItemReader.java:111) ~[spring-batch-excel-0.5.0-SNAPSHOT.jar:?]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE].
Any please help me.
Old question and I'm sure you figured it out, but I find the current answer to be unhelpful,sooo...
The Resource you're using could be an issue. Most spring-batch-excel examples utilize ClassPathResource. When you try to productionalize your code, you'll likely need to reach for files outside of your classpath. The obvious choice is FileSystemResource, but that will result in this Exception. Instead, look at UrlResource.
As #Thrax mentioned, spring-batch-excel expect to find a PushbackInputStream within the Resource. Here my solution to this problem when working with file on the filesystem:
I create my reader using input file from command line --input.file
#Bean
public PoiItemReader excelReader(#Value("${input.file}") String inputFile) throws FileNotFoundException {
PoiItemReader reader = new PoiItemReader();
PushbackInputStream input = new PushbackInputStream(new FileInputStream(inputFile));
InputStreamResource resource = new InputStreamResource(input);
reader.setResource(resource);
reader.setRowMapper(rowMapper());
return reader;
}
I hope it may helps you.
From looking at spring-batch-excel sources :
#Override
protected void openExcelFile(final Resource resource) throws Exception {
workbookStream = resource.getInputStream();
if (!workbookStream.markSupported() && !(workbookStream instanceof PushbackInputStream)) {
throw new IllegalStateException("InputStream MUST either support mark/reset, or be wrapped as a PushbackInputStream");
}
[...]
}
This exception is thrown if the InputStream does not support back reading. The InputStream depends of your Resource, so my conclusion would be that your resource is not a valid XLS/XLSX file.
I know this is an old issue , but i faced this issue, yet for those who have the same issue like me, i commented out this code of block and it worked
if (!workbookStream.markSupported() && !(workbookStream instanceof PushbackInputStream)) {
throw new IllegalStateException("InputStream MUST either support mark/reset, or be wrapped as a PushbackInputStream");
}
to understand why please refer to this code :
https://github.com/spring-projects/spring-batch-extensions/issues/34
I faced this issue today. The solution was to load the file from disk and not from the classpath. The interesting part is that on our local Windows environments loading from classpath worked fine, but not on a Unix environment. I suspect there might be some corruption going on in the excel file when packaged ina JAR. At any rate, we specify in a URL query parameter the location of the excel file to load, prefixed with classpath: to load it from the Java CLASSPATH, or file: to load it from disk. So all we had to do was put the file in some path on the same server as the running app, then update the URL query parameter to its location like this:
http://some.host.com?location=file:/absolute/path/to/excel/file
and voila. Internally we use Spring's ResourceLoader, which is nothing more than the Spring ApplicationContext. The ResourceLoader understands classpath: and file: prefixes and interprets each accordingly (read the documentation on the ResourceLoader.getResource() method for more details). We got a reference to the Spring's ResourceLoader simply by having our #Service component implement Spring's ResourceLoaderAware.

FileTransfer "Saved file:" followed by FileNotFoundException

My app downloads a zip file from a remote webserver, then extracts it.
The javascript successfully calls FileTransfer, which logs:
FileTransfer Saved file: file:///data/data/com.yadda.yadda/update.zip
As part of the success function, javascript calls my custom update plugin which immediately tests for the file:
Context ctx = this.cordova.getActivity().getBaseContext();
File update = new File(ctx.getFilesDir(),"update.zip");
if(!update.exists()) Log.w("File not found",update.getAbsolutePath());
The log for that last line is:
File Not Found /data/data/com.yadda.yadda/update.zip
Later in a try/catch block I have an InputStream variable created and one of the catch blocks is a FileNotFoundException which is firing every time.
Begin edit - more info
The FileNotFoundException has an interesting bit. The file path is wrong - even though I'm sending the same "update" variable to create the FileInputStream
InputStream fileis = new FileInputStream(update);
And the interesting bit of the exception:
Caused by: java.io.FileNotFoundException: /data/data/com.yadda.yadda/files/update.zip
End edit
What is going wrong here? Cordova logs that the file transfer completed and the file was saved, but then the file doesn't exist when I test for it! When I create the FileInputStream, why is the path different, causing the exception?
What am I missing? Everything works fine in the IOS version of the app.
Edit 2: per request, I browsed the device filesystem and found that update.zip does indeed exist in /data/user/0/com.yadda.yadda
OK, somewhere there is a bug. I'm inclined to believe it's a bug in getAbsolutePath() because I'm seeing consistent operation elsewhere.
When I create the "File update" variable, then immediately test and log the update.getAbsolutePath() - it shows the correct path. But when I attempt to create the FileInputStream, the path is different (+ /files/)
So, a little searching and I found that in order to access the application data directory (without /files) I must send a different directory with the new File command. Here's what it looks like:
File update = new File(ctx.getApplicationInfo().dataDir,"update.zip");
Obtaining the dir with getFilesDir()
ctx.getFilesDir() = /data/data/com.yadda.yadda/files
Obtaining the correct dir
ctx.getApplicationInfo().dataDir = /data/data/com.yadda.yadda

Loading an image from the Resource Folder

The code I am using to load the image is:
ImageIO.read(SpriteSheet.class.getResource(path));
The path being the path to the resource. But it would error with IllegalArgumentException. I wondered what might be causing and came to the conclusion that the resource should be added into the same path as the class.
Is it possible to load the image from another folder, like a res folder outside of the bin folder? (folder holding compiled classes)
EDIT:
So i messed around with a few things, and came to a solution. But now I have another problem. Here is my code
File sheet = new File(SpriteSheet.class.getProtectionDomain().getCodeSource().getLocation().getPath());
URI uri = sheet.toURI();
BufferedImage image = ImageIO.read(uri.toURL());
When I try to run it, it gives me an IIOException: Can't read Input File
This means that I can never actually get it work. I tried debugging by prining the URL to the console and this is the URL.
C:\Users\Amma\Abhijeet\Eclipse%20Workspace1\Test%20Game\bin
The %20 comes in the middle. Meaning that the file is and never can be acceesed. Is there anyway I can fix this?
Thanks.
Class.getResource will return null if the resource could not be found or the invoker doesn't have adequate privileges to get the resource.
All variants of ImageIO.read will throw an IllegalArgumentException if they receive a null input.
Take a look at the documentation of the getResource to understand how an absolute resource name is constructed from the given resource named and what are the rules for searching resources.
You can read images from any location as long as you have permissions to do so, the ImageIO.read method accepts a File, URL or InputStream so you have many option to do it.

Java fails in moving (renaming) a file when the resulting file is on another filesystem

A program we have erred when trying to move files from one directory to another. After much debugging I located the error by writing a small utility program that just moves a file from one directory to another (code below). It turns out that while moving files around on the local filesystem works fine, trying to move a file to another filesystem fails.
Why is this? The question might be platform specific - we are running Linux on ext3, if that matters.
And the second question; should I have been using something else than the renameTo() method of the File class? It seems as if this just works on local filesystems.
Tests (run as root):
touch /tmp/test/afile
java FileMover /tmp/test/afile /root/
The file move was successful
touch /tmp/test/afile
java FileMover /tmp/test/afile /some_other_disk/
The file move was erroneous
Code:
import java.io.File;
public class FileMover {
public static void main(String arguments[] ) throws Exception {
boolean success;
File file = new File(arguments[0]);
File destinationDir = new File(arguments[1]);
File destinationFile = new File(destinationDir,file.getName() );
success = file.renameTo(destinationFile);
System.out.println("The file move was " + (success?"successful":"erroneous"));
}
}
Java 7 and above
Use Files.move(Path source, Path target, CopyOption... opts).
Note that you must not provide the ATOMIC_MOVE option when moving files between file systems.
Java 6 and below
From the docs of File.renameTo:
[...] The rename operation might not be able to move a file from one filesystem to another [...]
The obvious workaround would be to copy the file "manually" by opening a new file, write the content to the file, and delete the old file.
You could also try the FileUtils.moveFile method from Apache Commons.
Javadoc to the rescue:
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
Note that the Files class defines the move method to move or rename a
file in a platform independent manner.
From the docs:
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
If you want to move file between different file system you can use Apache's moveFile
your ider is error
beause /some_other_disk/ is relative url but completely url ,can not find the url
i have example
java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt D:\Eclipse33_workspace_j2ee\test\src
The file move was successful
java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt \Eclipse33_workspace_j2ee\test\src
The file move was erronous
result is url is error

classloader.getSystemResourceAsStream returns null

I'm trying to load a properties file without using the actual path of the file. I've already done that on some other simple apps using:
InputStream inputStream = ClassLoader.getSystemResourceAsStream(PROPERTIES_FILE);
props.load(inputStream);
But this time it doesn't work. The inputStream is null for some reason. PROPERTIES_FILE is a constant defined as "app.properties". I tried to remove the .properties extension and got the same results.
Any ideas?
Thanks.
The PROPERTIES_FILE constant should include the package as well as the properties file (e.g. "com/some/library/file.properties".
final static String PROPS_FILE = "/com/some/library/file.props";
//The preceding "/" is dependendant on wheterh
//you are going to be giving a relative or absolute location
InputStream is = YourCurrentClass.class.getResourceAsStream(PROPS_FILE);
Got the same problem.
Reason: I renamed DAO package to dao. While exploding the artifact, directory DAO not get overwritten.
So I got dao in project internals and DAO in filesystem :facepalm:
When getSystemResourceAsStream returns null, it means the resource was not found. Make sure the requested resource really is on the classpath at the specified location.

Categories

Resources