How to get src/main/resources path from Java - java

I have some stuff under src/main/resources path.
Specifically I have a folder with report templates called reports.
I understand that when the application is deployed/run all files and folders under src/main/resources go to the classpath, namely my project's WEB-INF/classes.
This means that a folder WEB-INF/classes/reports will be created in my server.
Now I want to access my reports as paths, not as inputstream, because my reporting code in java supports a filepath and not an inputstream. So I have to be able to get the WEB-INF/classes/reports absolute path (or relative, I don't care as long as it is right).
Reading some answers regarding similar questions, I have already tried the following things:
getClass().getResource(".").getPath(); --> this returns the exact path of the class I am currently at in my classpath, namely: C:\Tools\JBoss Application Server 7.1.1\standalone\deployments\myProject.war\WEB-INF\classes\aaa\bbb\ccc\ddd
getClass().getClassLoader().getResource(".").getPath(); --> this returns: C:\Tools\JBoss Application Server 7.1.1\modules\sun\jdk\main\service-loader-resources, which is completely irrelevant.
I want something to return C:\Tools\JBoss Application Server 7.1.1\standalone\deployments\myProject.war\WEB-INF\classes
If it is not possible, I will get the first path and go as many folders back as needed to reach classes folder.
Thank you.

You need ServletContext.getRealPath(String) method.
getServletContext().getRealPath("/WEB-INF")

Related

Why ClassLoader returns a path with extraneous second exclamation point

I'm trying to grab a resource in ClassLoader. A simplified version of the code looks something like this:
String ePath = "rewrite/common/RenameFunctor.groovy"
String fPath = ThClType.class.getClassLoader().getResource(ePath);
the response I get back as fPath is jar:file:/Users/myName/warPath/warName.war!/WEB-INF/classes!/rewrite/common/RenameFunctor.groovy. The actual path to the resource we want it exactly that, except without the second exclamation point. (Unlike warName.war, classes is just a normal directory.)
Does anyone know what might have caused the extra exclamation point and/or what might be done to fix it? This is as part of a process of updating some pretty old code that I didn't write, so if esoteric customization of ClassLoader behavior is possible, it's possible it's been done in this case. if it is possible, then I don't know how to check, and would appreciate any insight.
Warning: this answer is part supposition and guess-work on the mechanics, it may not be 100% correct, but I think it comes close enough. As far as I know actual WAR class loading will vary per servlet container or application server, so this answer may not hold for all of them.
If you look at
jar:file:/Users/myName/warPath/warName.war!/WEB-INF/classes!/rewrite/common/RenameFunctor.groovy
you can split it up in the following parts:
file:/Users/myName/warPath/warName.war
/WEB-INF/classes
/rewrite/common/RenameFunctor.groovy
The actual resource that is on the class path is the last one, /rewrite/common/RenameFunctor.groovy, the other parts are the coordinates used by the war class loader to find the part of the class path that contains that resource: first the location of the war file itself, file:/Users/myName/warPath/warName.war, and then the path within the war, /WEB-INF/classes.
This theory build on the documentation of the JarURLConnection which states:
A URL Connection to a Java ARchive (JAR) file or an entry in a JAR
file.
The syntax of a JAR URL is:
jar:<url>!/{entry}
for example:
jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class
Jar URLs should be used to refer to a JAR file or entries in a JAR
file. The example above is a JAR URL which refers to a JAR entry. If
the entry name is omitted, the URL refers to the whole JAR file:
jar:http://www.foo.com/bar/baz.jar!/
So for a plain jar, the first part of the URL identifies the jar file itself, and the second part identifies the resource within the jar.
Technically war files are jar files, but contrary to jar files, the war file itself is not part of the class path. Instead it contains elements that are added to the class path., for example jar files in WEB-INF/lib and the classes and other files in WEB-INF/classes.
The ! separated parts then define the steps taken by the war class loader to locate a specific resource, in this case /rewrite/common/RenameFunctor.groovy.

Resources folder in a Java EE application

I'm developing a simple mail sender as Java EE application.
The project structure is shown as follows:
To properly setup email contents, I need to read the *.vm files placed inside the resource folder, that I supposed to have as path classpath:/templates/mail/*.vm (as with Spring)... But my supposition is wrong!
Which is the right path to use?
Should I have to use the META-INF folder? Is this solution more
java-ee-compliant? In that case, where have I to put the META-INF folder inside my project structure?
Update:
I packaged the project as .war, then I putted the files in:
/src/main/webapp/WEB-INF/classes/templates/mail/
Then:
org.apache.velocity.Template t = myVelocityEngine.getTemplate("classpath:/templates/mail/account_to_confirm.vm",
"UTF-8");
Nonetheless, the app returns an error at runtime:
Unable to find resource 'classpath:/templates/mail/account_to_confirm.vm'
What am I doing wrong?
Just to better understand:
Supposing that I'd like to deploy this app as jar (removing the servlet class, of course): in that case, should I have to edit the folder layout in order to still use the same path into the source code?
I think the problem is due to the prefix classpath:: where did you find that you have to use it?
You might find useful understanding how to initialize VelocityEngine reading Loading velocity template inside a jar file and how Configuring Resource Loaders in Velocity.
If you can, use Classloader.getResourceAsStream("templates/mail/*.vm"); or similar getResourceAsURL method.
If not, take a look at where files from resources are placed inside WAR. In your case, the file should be in /WEB-INF/classes/templates/mail .

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]

Java (maven web app), getting full file path for file in resources folder?

I'm working with a project that is setup using the standard Maven directory structure so I have a folder called "resources" and within this I have made a folder called "fonts" and then put a file in it. I need to pass in the full String file path (of a file that is located, within my project structure, at resources/fonts/somefont.ttf) to an object I am using, from a 3rd party library, as below, I have searched on this for a while but have become a bit confused as to the proper way to do this. I have tried as below but it isn't able to find it. I looked at using ResourceBundle but that seemed to involve making an actual File object when I just need the path to pass into a method like the one below (don't have the actual method call in front of me so just giving an example from my memory):
FontFactory.somemethod("resources/fonts/somefont.ttf");
I had thought there was a way, with a project with standard Maven directory structure to get a file from the resource folder without having to use the full relative path from the class / package. Any advice on this is greatly appreciated.
I don't want to use a hard-coded path since different developers who work on the project have different setups and I want to include this as part of the project so that they get it directly when they checkout the project source.
This is for a web application (Struts 1.3 app) and when I look into the exploded WAR file (which I am running the project off of through Tomcat), the file is at:
<Exploded war dir>/resources/fonts/somefont.ttf
Code:
import java.io.File;
import org.springframework.core.io.*;
public String getFontFilePath(String classpathRelativePath) {
Resource rsrc = new ClassPathResource(classpathRelativePath);
return rsrc.getFile().getAbsolutePath();
}
In your case, classpathRelativePath would be something like "/resources/fonts/somefont.ttf".
You can use the below mentioned to get the path of the file:
String fileName = "/filename.extension"; //use forward slash to recognize your file
String path = this.getClass().getResource(fileName).toString();
use/pass the path to your methods.
If your resources directory is in the root of your war, that means resources/fonts/somefont.ttf would be a "virtual path" where that file is available. You can get the "real path"--the absolute file system path--from the ServletContext. Note (in the docs) that this only works if the WAR is exploded. If your container runs the app from the war file without expanding it, this method won't work.
You can look up the answer to the question on similar lines which I had
Loading XML Files during Maven Test run
The answer given by BobG should work. Though you need to keep in mind that path for the resource file is relative to path of the current class. Both resources and java source files are in classpath

Find conf file regardless how application started

I'm newbie to java.
I have some directory structure
product/
conf/
classes/com/../..
conf/ contains some configuration file, while under classes/ I have my application.
How can I ensure from inside java code that I'm able to find file in conf/ despite way I'm executing it (e.g. from eclipse, from different directories, from crontab etc.).
P.S.
Files in conf/ are not resources, since required to be edited by user.
Is there're way to know where my .class, so I canuse relative path form that directory to reach my directory (e.g. MY_CLASS_DIR/../../../../conf)
I would put the conf directory into the class path. That way you can always find them by:
YourClass.class.getClassLoader().getResource("conf/....");
You can use the absolute path, including the way to product.
Or you may use a configuration setting, by starting your program like
java -DXY_HOME=/some/path/product ...
From the javacode, you use it:
String xyHome = System.getProperty ("XY_HOME")
Or you use a kind of inifile in your home directory, where you specify where to look for the conf-directory.
Rereading your question multiple times, it is unclear to me what your goal is. To find the conf dir independently from where you are (eclipse, crontab, ...)? But the headline asks for the CWD, which is the opposite - the directory, depending on where you are.
Both is possible, but you have to decide what you want.
Its safe to use relative paths than absolute paths. Even if you JAR your classes tomorrow it will work as is,
Put you configuration files in classpath during deployment.(Please note that
project directory structure can be different from that of deployment directory structure)
product/
classes/com/../..
classes/conf/some_conf.properties
Then you can use Apache common configuration to get the URL of file
URL urlOfFile = org.apache.commons.configuration.
ConfigurationUtils.locate("conf/some_conf.properties");
The other alternative you can try is,
URL urlOfFile = <SomeClassFromClassesFolder>.class.
getClassLoader().getResource(resourceFile);
Once you get the URL of your configuration file getting stream out of it very simple,
InputStream stream = urlOfFile.openStream();
Good luck.
For you understanding you can refer the following as well,
http://bethecoder.com/applications/tutorials/showTutorials.action?tutorialId=Java_IO_CurrentWorkingDirectory
http://bethecoder.com/applications/tutorials/showTutorials.action?tutorialId=Java_Reflection_WheretheClassloadedfrom
Good luck.
you can find out what is the absolute path of the working dir by:
String str = new File("").getAbsolutePath()

Categories