Tomcat: correct way to find a resource? [duplicate] - java

This question already has answers here:
How to find the working folder of a servlet based application in order to load resources
(3 answers)
Closed 7 years ago.
I've working on a big application deployed on a Tomcat server. There's only one .jsp page and all the UI is done using ext-js.
There are a lot of .java classes. In one of these class (which is performing validation), I'd like to add XML validation and to do this I need to access the .xsd file.
My problem is that I don't know how to cleanly find the path to my .xsd file.
I'll put the .xsd files in a repertory next to css/, images/, etc.
I know how to this in a crappy way: I call System.getProperty("user.home") and from there I find my webapp, the xsd/ folder, and the .xsd files.
But what is a "clean" way to do this?
Where am I supposed to find the path to my webapp (or to my webapp resources) and how am I supposed to pass this information down to the .java class that performs the validation?

For files in public web content the ServletContext#getRealPath() is indeed the way to go.
String relativeWebPath = "/path/to/file.xsd";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
// ...
However, I can't imagine that there is ever intent to serve the XSD file into the public and also the Java class which needs the XSD doesn't seem to be a servlet. So, I'd suggest to just put XSD file in the classpath and grab from there instead. Assuming that it's been placed in the package com.example.resources, you can load it from the classpath as follows:
String classpathLocation = "com/example/resources/file.xsd";
URL classpathResource = Thread.currentThread().getContextClassLoader().getResource(classpathLocation);
// Or:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(classpathLocation);

getServletContext().getRealPath("/") is what you need.
See here.

Related

Failed to read a file in a directory in java [duplicate]

This question already has answers here:
Reading a plain text file in Java
(31 answers)
Closed 2 years ago.
My project structure is like this:
Project
App
x.java
files
file.txt
main.java
I want to access file.txt via x.java.. My code:
File file = new File("file.txt");
Scanner sc = new Scanner(file);
while (sc.hasNextLine())
out += sc.nextLine();
if (out.isEmpty()) out = "NOTHING";
but gives me NullPointerException.
If this file is supposed to be part of your app the way class files are (so, effectively read-only, an asset that you pack in with the rest. Think texture maps for games, or icons for user interfaces), use getResourceAsStream, as the resource in question may not even be a file (java projects tend to ship as jars, and an entry in a jar is not a file!).
If not, well, then figure out a way to get the full path info into your code, because it's not going to magically figure out that you have a dir structure with "App" and "files", which is non-standard. (the standard route is src/main/java/pkgname/Type.java for java files, and src/main/resources/pkgname/open.png for assets that just need to be there (don't need compiling).
If you set up a project in your favourite IDE according to this structure and configured using e.g. maven or gradle, then getResourceAsStream works during dev time, and also at runtime, even if the resource is inside the jar.
Basically when you read the file "file.txt", you don't provide with an absolute path so the operating system will look for a file in the current directly. That is the one where your program started.
I get you didn't start the program in the folder "files" but in another folder like maybe the folder "Project". In that case the path to use would be "files/file.txt".
I solved it !
First, I used
File directory = new File("./");
System.out.println(directory.getAbsolutePath());
to detect the whole path.. Then I appended the directory.getAbsolutePath() with the filename so it becomes directory.getAbsolutePath()+"file.txt"
I used the normal way to read a file by using the scanner and scanner.readLine() to read the file !
This answer
Has helped me

Access to csv file in jar without InputStream

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.

Opening input file using java code in JSP

I am using JSP on NetBeans.
In the java code, I am trying to read data from a file. First I open the file by specifying its path.
Because my code runs on a server (GlassFish), I would like to have my file path independent of the machine where it runs. Therefore, I want to start the path with the folder name that contains the file which is saved on the root of the project directory. I tried so hard to achieve that but I couldn't.
I read online and I found this way, but it still doesn't work:
<%
//building the tree here.
GraphBuilder tree = new GraphBuilder("${pageContext.request.contextPath}\\src\\java\\Database\\OptimizedFullTermFile.pad");
%>
Can anyone help? Thank you.
Just read it from the classpath. Given that you're using the typical src folder representing the Java source code (the Java package/class structure), I assume that the file OptimizedFullTermFile.pad is placed in the Java package java.Database (eek, a capital in package name? lowercase it all). In that case, it's already in the classpath and thus you can just get it straight from there as follows:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("java/Database/OptimizedFullTermFile.pad");
// ...
As to your failed attempt: the EL ${pageContext.request.contextPath} isn't ever going to work in a scriptlet. Even if it did, it's not the right thing, it returns the context path in the webapp URL which is absolutely not part of the local disk file system path, let alone the classpath. Using scriptlets is strongly discouraged since a decade, by the way.
See also:
getResourceAsStream() vs FileInputStream
Where to place and how to read configuration resource files in servlet based application?
You can try the following code to get your directory file in project from the following code.
this.getServletContext().getRealPath("")+[your file path in project web directory]

A static resource file?

Android uses a static resource file R. This file (at least in eclipse) is automatically updated when ever you add new id's of any sort. How can I create/implement the same feature in a normal java application? Is it as simple as just writing an xml parser and just updating the resource file after the xml is modified?
In a way, yes. You need to create a custom build script/program which runs at the start of each build (before anything else), scans your resource folder files (and if they are XML files it needs to read in the XML files and parse out the string resources or whatever from those), then write it all to a Java file in some manner (e.g. R.string_name = "string value").
Make sure the XML files aren't actually packaged in your .jar, since all that information will be stored inside your Java resources file now.
For things which aren't XML files you could just store the filename as a string in the Java resources file.
You didn't specified the type or the use of the resources. I don't know android, but I'll try to help; If you just need to access some resource in your application you can use properties or resource, there are some differences see this other question Properties vs Resource Bundle

getResourceAsStream() is always returning null [duplicate]

This question already has answers here:
Where to place and how to read configuration resource files in servlet based application?
(6 answers)
Closed 6 years ago.
I have the following structure in a Java Web Application:
TheProject
-- [Web Pages]
-- -- [WEB-INF]
-- -- -- abc.txt
-- -- index.jsp
-- [Source Packages]
-- -- [wservices]
-- -- -- WS.java
In WS.java, I am using the following code in a Web Method:
InputStream fstream = this.getClass().getResourceAsStream("abc.txt");
But it is always returning a null. I need to read from that file, and I read that if you put the files in WEB-INF, you can access them with getResourceAsStream, yet the method is always returning a null.
Any ideas of what I may be doing wrong?
Btw, the strange thing is that this was working, but after I performed a Clean and Build on the Project, it suddenly stopped working :/
To my knowledge the file has to be right in the folder where the 'this' class resides, i.e. not in WEB-INF/classes but nested even deeper (unless you write in a default package):
net/domain/pkg1/MyClass.java
net/domain/pkg1/abc.txt
Putting the file in to your java sources should work, compiler copies that file together with class files.
A call to Class#getResourceAsStream(String) delegates to the class loader and the resource is searched in the class path. In other words, you current code won't work and you should put abc.txt in WEB-INF/classes, or in WEB-INF/lib if packaged in a jar file.
Or use ServletContext.getResourceAsStream(String) which allows servlet containers to make a resource available to a servlet from any location, without using a class loader. So use this from a Servlet:
this.getServletContext().getResourceAsStream("/WEB-INF/abc.txt") ;
But is there a way I can call getServletContext from my Web Service?
If you are using JAX-WS, then you can get a WebServiceContext injected:
#Resource
private WebServiceContext wsContext;
And then get the ServletContext from it:
ServletContext sContext= wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT));
Instead of
InputStream fstream = this.getClass().getResourceAsStream("abc.txt");
use
InputStream fstream = this.getClass().getClassLoader().getResourceAsStream("abc.txt");
In this way it will look from the root, not from the path of the current invoking class
I think this way you can get the file from "anywhere" (including server locations) and you do not need to care about where to put it.
It's usually a bad practice having to care about such things.
Thread.currentThread().getContextClassLoader().getResourceAsStream("abc.properties");
I don't know if this applies to JAX-WS, but for JAX-RS I was able to access a file by injecting a ServletContext and then calling getResourceAsStream() on it:
#Context ServletContext servletContext;
...
InputStream is = servletContext.getResourceAsStream("/WEB-INF/test_model.js");
Note that, at least in GlassFish 3.1, the path had to be absolute, i.e., start with slash. More here: How do I use a properties file with jax-rs?
I had the same problem when I changed from Websphere 8.5 to WebSphere Liberty.
I utilized FileInputStream instead of getResourceAsStream(), because for some reason WebSphere Liberty can't locate the file in the WEB-INF folder.
The script was :
FileInputStream fis = new FileInputStream(getServletContext().getRealPath("/")
+ "\WEBINF\properties\myProperties.properties")
Note:
I used this script only for development.
I had a similar problem and I searched for the solution for quite a while:
It appears that the string parameter is case sensitive. So if your filename is abc.TXT but you search for abc.txt, eclipse will find it - the executable JAR file won't.

Categories