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.
Related
I want to get a file from the resource file, and to use it in string.
I tried this :
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("/resources/fileC.p12").getFile());
String data = String.valueOf(file);
but doesnt work, thanks for helping
I tried this but i had a error, it returns a null value
new File In java, File means File. As in, an actual file on your actual harddisk. Resources aren't - they are entries in a jarfile and therefore not a file. Simply put, resources cannot be read this way.
Fortunately, File in general is barking up the wrong tree: The correct abstraction is InputStream or similar - that represents 'any stream of bytes'. A file can be an InputStream. So can a network socket, a blob from a network, or, indeed, a resource being streamed to you by the classloader, which could very well be getting it from a network or generating it whole cloth - classloaders can do that. It's an abstract mechanism.
You're also doing it wrong - you want Type.class.getResource. Your way is needlessly wordy and will fail in exotic scenarios (such as bootloaders and agents and the like, which have no classloader).
class Example {
public String getDataFromFileC() throws IOException {
try (var in = Example.class.getResourceAsStream("/resources/fileC.p12")) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}
}
This:
Uses getResourceAsStream which gives you an inputstream. As I mentioned, if you mention File, you lose. Hence, we don't.
Uses the proper form: MyType.class.get. This avoids issues when subclassing or in root classloader situations.
MyType.class.get needs a leading slash. the getResource on classloaders requires you not to have it (which explains why your snippet wouldn't work in any scenario - that leading slash).
Uses try-with-resources as you should.
Propagates exceptions as you should.
Configures charset which you should do anytime you go from bytes to strings or vice versa.
NB: Depending on your build system, it may package those resources in the jar as /fileC.p12 and not as /resources/fileC.p12 - in fact, that is likely. You may want to update this to "/fileC.p12".
NB2: String.valueOf(file); does not read files. It just calls toString() on the file object which gives you a path. Resources don't have to be a path so this cannot work. They do have a URL, which may or may not be useful. If you want that: return MyClass.class.getResource("/resources/fileC.p12").toString();.
String data = new String(getClass().getResourceAsStream("/fileC.p12").readAllBytes());
Your resource (which shouldn't be seen as a file as it could and probably should be packaged with your app) is at the root, so useful to start with '/' then it can be addressed from any package. Be cautious with Java >= 17 as that will be decoded by default as UTF-8, so if that's not the encoding, you will have to specify what is in the String ctor. It might be safer to do that anyway.
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
I am trying to retrieve a jrxml file in a relative path using the following java code:
String jasperFileName = "/web/WEB-INF/reports/MemberOrderListReport.jrxml";
File report = new File(jasperFileName);
FileInputStream fis = new FileInputStream(report);
However, most probably I didn't succeed in defining the relative path and get an java.io.FileNotFoundException: error during the execution.
Since I am not so experienced in Java I/O operations, I didn't solve my problem. Any helps or ideas are welcomed.
You're trying to treat the jrxml file as an object on the file-system, but that's not applicable inside a web application.
You don't know how or where your application will be deployed, so you can't point a File at it.
Instead you want to use getResourceAsStream from the ServletContext. Something like:
String resourceName = "/WEB-INF/reports/MemberOrderListReport.jrxml"
InputStream is = getServletContext().getResourceAsStream(resourceName);
is what you're after.
You should place 'MemberOrderListReport.jrxml' in classpath, such as it being included in a jar placed in web-inf\lib or as a file in web-inf\classes.
The you can read the file using the following code:
InputStream is=YourClass.class.getClassLoader().getResourceAsStream("MemberOrderListReport.jrxml");
String jasperFileName = "/web/WEB-INF/reports/MemberOrderListReport.jrxml";
Simple. You don't have a /web/WEB-INF/reports/MemoberOrderListReport.jrxml file on your computer.
You are clearly executing in a web-app environment and expecting the system to automatically resolve that in the context of the web-app container. It doesn't. That's what getRealPath() and friends are for.
check that your relative base path is that one you think is:
File f = new File("test.txt");
System.out.println(f.getAbsoluteFile());
I've seen this kind of problem many times, and the answer is always the same...
The problem is the file path isn't what you think it is. To figure it out, simply add this line after creating the File:
System.out.println(report.getAbsolutePath());
Look at the output and you immediately see what the problem is.
I have a resource (velocity template) which I'd like to be able to swap during development. However,
getClass().getClassLoader().getResourceAsStream()
seems to cache the template. Is there a way to disable this besides using a file loader instead of the class loader?
To avoid caching you can use:
getClass().getClassLoader().getResource().openStream()
It would be equal to using URLResourceLoader for Velocity instead of ClasspathResourceLoader I suppose. I would just go with a file loader.
See if something like this helps (exception handling omitted):
URL res = getClass().getClassLoader().getResource(resName);
if (res != null) {
URLConnection resConn = res.openConnection();
resConn.setUseCaches(false);
InputStream in = resConn.getInputStream();
}
Another thing to watch out for (besides the caching mentioned in the other answers) is that your IDE or build system might move your resources to your build directory and put that on the class path. So the file you are editing in your source directory is not the file that is being served.
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.