Is there a way to load files stored inside JARs using getResourceAsStream from Tomcat applications?
I have a library that puts all the files it needs inside its jar, along with the compiled classes. This code works when the library is used in standalone applications but not when the library is used inside Tomcat (using the PHP java-bridge).
final InputStream stream = Object.class.getResourceAsStream("/styles/foo.xsl");
I tried without success to use the solution outlined in question getResourceAsStream not loading resource in webapp and changed the code to
final ClassLoader resourceLoader = Thread.currentThread().getContextClassLoader();
final InputStream stream = resourceLoader.getResourceAsStream("/styles/foo.xsl");
The latter code does not work neither when the library is used standalone or when the library is used in Tomcat. In both cases stream == null.
The file I am trying to load is correctly stored on the JAR in /styles/foo.xsl. The JAR with all the classes and these other files is tomcat/webapps/iJavaBridge/WEB-INF/lib/.
Can someone suggest a piece of code that works both in Tomcat and non-Tomcat applications?
You need to remove the leading slash from the path. That would only work with classloaders which do not operate on the classpath root.
final ClassLoader resourceLoader = Thread.currentThread().getContextClassLoader();
final InputStream stream = resourceLoader.getResourceAsStream("styles/foo.xsl");
if you got a class file in the jar with the xsl try the following:
final ClassLoader resourceLoader = com.mypackage.MyClassInJar.class.getClassloader();
final InputStream stream = resourceLoader.getResourceAsStream("/styles/foo.xsl");
if there is no class, just create a dummy class.
i think that should work because you will always get the classloader responsible for the jar.
Related
I have a project with a folder "src/main/resources" where inside there is the hibernate configuration file, I load it using this line of code
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
From inside the IDE it is working well, but when I create the jar it doesn't file the file.
How can I load it properly in the jar file too?
Thanks
Could you please try this:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileName").getFile());
I cannot say for ceratin that this is the issue without knowing how exactly you use the path extracted by:
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
but I can tell you this:
Run from an IDE the above line of code will return:
/path/to/project/src/main/resources/hibernate.cgf.xml
which is a valid filesystem path. You can then use this path to, for example, create an instance of File class and then use that instance to read the file contents.
However the same line of code run from inside a jar file will return:
file:/path/to/jar/jar_name.jar!/hibernate.cgf.xml
which is not a valid filesystem path. If you create an instance of File class using this path and then try to read the contents of the file you'll get an exception: java.io.FileNotFoundExeption
To read the contents of the file from inside of a jar you should use method Class.getResourceAsStream(String), which will return an instance of class sun.net.www.protocol.jar.JarURLConnection.JarURLInputStream (or equivalent in non-Oracle or non-OpenJDK Java). You can then use this object to read the contents of the file. For example:
InputStream inputStream = HibernateUtil.class.getResourceAsStream("/hibernate.cgf.xml");
Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
String fileContents = scanner.hasNext() ? sscanner.next() : "";
Most likely, the file is absent from the jar you create. There's too little information in your question, but I will try a guess:
Your hibernate.cgf.xml resides in the same directory as the Java sourcefles, and you are using a build tool (be it IDE, maven, gradle or an ant script) that expects resources to be stored in a separate directory.
It's easy to check: try to unzip your jar and see if the file is there (use any tool, you can just change the extension from .jar to .zip). I think you will see the file is absent.
Then come back with a question: "how to pack my non-java resources into a jar, using XXX", where XXX will be the name of the techology you are using for building the jar.
Most probably the slash in "/hibernate.cgf.xml" is not needed, if the hibernate.cgf.xml is in the same package as you class HibernateUtil.
You can access the file actually also via the classloader using the full path. Yet you never add to it the first slash.
Here is some code demonstrating how you can access the file using different methods:
public static void main(String[] args) {
// Accessing via class
System.out.println(SimpleTests.class.getResource("hibernate.cgf.xml").getPath());
// Accessing via classloader from the current thread
String path = Thread.currentThread().getContextClassLoader()
.getResource("simple/hibernate.cgf.xml").getPath();
System.out.println(path);
// Accessing via classloader used by the current class
System.out.println(SimpleTests.class.getClassLoader().getResource("simple/hibernate.cgf.xml").getPath());
}
In the example above the package 'simple' should be replaced by the package where your hibernate.cgf.xml is. But you should never have the slash at the beginning of the package declaration.
I'm trying to get the jar to read from target/classes outside of the jar so I can configure the data easier than going in the jar. The below is what I'm using to read the file, but it's reading from within the jar. After reading the XML I'm using DocumentBuilder to parse the XML.
ClassLoader classLoader = getClass().getClassLoader();
InputStream configFile = classLoader.getResourceAsStream(file);
The below is what I'm using to read the file, but it's reading from
within the jar.
To read a resource outside the jar that you execute, don't use classloader to find the resource that will looks for in the running jar but use File or better Path that allows to locate/manipulate resources in a filesystem.
You could just do it :
InputStream configFile = Files.newInputStream(Paths.get(file));
Whatever, I am not sure that you use case be valid as reading a file from target/classes makes not really sense as resources located at this place are not designed to be persistent but to be packaged in the built artifact (here a JAR).
I want to load a html file located in:
to use in standalone spring boot jar application.
This approach leads to FileSystemNotFoundException
new InputStreamReader(
getClass().getResourceAsStream("/email-templates/html-email.html")
)
Using
#Autowired
private ResourceLoader resourceLoader;
...
resourceLoader.getResource("classpath:email-templates/html-email.html");
leads to NullPointerException.
Could you please specify how to properly load a file in spring boot jar.
Try below code. Using spring classpathresource you should be able to load them. As long as you try load this file inside spring context, Spring container is aware of its classpath .So it should load corresponding file.Otherwise , it tries to find in file system.
Resource resource = new ClassPathResource("email-templates/html-email.html");
I assume you have these resouces in your jar, Check inside the jar file if those resources are present.
jar tf springboot.jar
Load resource in a jar file Java Spring
Try through below code.
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("email-templates/html-email.html");
/email-templates/html-email.html
If the above doesn't work visit this help full link
Java ClassLoaderUtil
I tried everything to access to CSV file when a run my jar. I put the CSV in resources package in Eclipse, and it's fine when I run the code from there, but it doesn't work when I run the jar from an executable.
ClassLoader c = MyClass.class.getClassLoader();
URL url = c.getResource("com/mysoft/resources/");
String path = URLDecoder.decode(url.getPath(), "utf-8");
File f = new File(path+ "VAL.csv");
if(f.exists())
...
I don't want to put this file out of the jar. I just want read the file. How can I do it?
EDIT: I closed my login of my first post - Access to csv file in jar - and I don't know how to remove it, and I can't respond to comments. So I posted it again here.
Is it possible not to use InputStream ?
Your use of getResource() here is very dubious. I would not rely on getResource() finding a packet/directory at all (after all, one can argue that it should return resources, not namespaces).
Also, never ever interpret the URL returned by getResource() - its inviting trouble times two. The ClassLoader can return you anything, the URL returned may have nothing in common with what you asked for. Constructing something from the URL's String representation has an abhorrent opportunity of failure when the ClassLoader isn't your standard classpath JRE classloader (think of Application Server, WebStart etc.).
Ask directly for the Resource you want:
getResource("com/mysoft/resources/VAL.csv")
And don't create a File, use InputStream. Resources aren't files, you can not access them with File API.
I'm reading someone elses code; they have a line like so:
InputStream is = getClass().getResourceAsStream("../../../../../../file.txt");
Why would you do this instead of using File? Isn't the point of using the classloader to locate resources on the said classloaders classpath?
getResourceAsStream() allows you get access to files inside the JAR-container.