Adding and accessing resource files to Play Framework application - java

I am running a PlayFramework 2 application. The application builds a client authenticated SSL session to a 2nd server. To accomplish this I am storing a Java Keystore file in a resource directory. Everything runs fine on my local box. Next I create a dist package for upload to Cloud Foundry which essentially builds a war file with a buch of Jars. Any idea how I can access the Keystore from my java code once its compiled into a Jar and uploaded to CloudFoundry? Any direction would be greatly appreciated. Here is current code snippet.
Best,
SR
//READS THE JAVA KEYSTORE FILE FROM A RELATIVE LOCATION
File clientKS = new File("resource/devportal.jks");
//SET CONNECTION PARAMS
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type","application/json");
con.setDoOutput(true);
con.setSSLSocketFactory(getFactory(clientKS, passphrase.toCharArray()));

Assuming there is no other way than to use a java.io.File, you may want to try getting ahold of it by putting it in the classpath of your app and do something like
AnyClassOfYourApp.class.getResource("devportal.jks").getFile()

Its been a while but try this:
//TESTING BY USING INCLUDED KEYSTORE IN JAR FILE
String ksPath = "/res/devportal.jks";
URL jksURL = PostNvp.class.getResource(ksPath);
File jksStore = new File(jksURL.toURI());
//TESTING
Where PostNvp is my java class PostNvp.java where this code snippet lives.

Related

Where to put file that a jar needs to load

I have a jar that will be connecting to a website for communication using websockets. The website is an SSL site and for that reason I have a .ts the program needs to load file. The following is the java code used to load that .ts file
System.setProperty("javax.net.ssl.trustStore",
"foo.ts");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
and the java program is in a package called foo.web so thus when packed into the jar is in a folder called foo which then has a subfolder called web.
My question is, do I put the foo.ts in the foo/web folder where my classes reside or should I put the foo.ts file at the root of the jar to be loaded with my current code in the program for loading the foo.ts file?
The work around System.setProperty... needing a 'regular' file path, is using mechanism to resolve class resources:
place ts file in your code folder under some package (normal web code not
a library jar code)
in a class from the same package, call:
a
//this will find the file in the package folder
URL cert = this.getClass().getResource("ts");
String path = cert.toString(); //this translate the url to file system location
if (path.startsWith("file:"))
path = path.substring("file:".length()+1,path.length()); //getting rid of file prefix as not needed
System.setProperty("javax.net.ssl.trustStore", path);
If you want to include ts in jar, similar trick, but instead of path (which will not work, read the content and save it to temporary location
in = this.getClass().getResourceAsStream(wsdl);
... save it to tmp location
System.setProperty("javax.net.ssl.trustStore", your tmp location);
I assume that you have unsigned, self generated certificate that you want to use for your ssl connection.
The part that servers the content over ssl, (your tomcat on 443 or apache) needs to know the certificate and its key (configured as in tomcat or apache document).
Your java code that is deployed on that server, does not need to knwo about the certificate or even that is behind ssl.
But the code that wants to connect to such server, lets say web service client will throw exception (and very obscured btw) as it will not recognize the certificate and refuse connecting (unlike the web browser which ofer the dialog that lets you add an exception).
So the client code needs the certificate added to its TrustedStore before oppening connection (the trick with System.property does the job). Thanks to it the client can trust the connection as your remote cert matches the one he already has.
If your client code happens to be running on the same tomcat, it still needs the cert added to the store, as the configuration options for connector at 443 only expose the cert to anyone who can read it, but do not add it to the tomcat's pool of know certificates. To do so you need the -Djava.net.ssl.trustStore=YOUR_TS -Djavax.net.trustStorePassword=PASS options for tomcat starts, or the System.setProperty inside your application code.
The value of the javax.net.ssl.trustStore property is a file path that points to the location of the trust store on disk. If you don't specify a folder, it will assume the current working directory for the program which is most likely where the JVM was invoked from. If you are unsure what your current working directory is, you can get it from the user.dir system property.
System.getProperty("user.dir"));

Why getClass().getProtectionDomain().getCodeSource().getLocation().getPath() doesn't work in final product after compiled?

Ok, Here is my Web project. I built it in eClipse with the following structure:
workspace3\MyProject\war\images\uploaded
workspace3\MyProject\war\WEB-INF\classes
Ok, I want to store the uploaded images into workspace3\MyProject\war\images\unloaded, so here is the code at service side & it works fine in Eclipse
String absolutePath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
absolutePath=absolutePath.replace("WEB-INF/classes/", "images/uploaded");
File file = File.createTempFile("upload-", "."+extName, new File(absolutePath));
Ok, now I compiled my project & put it into VPS with Tomcat server and it has the following structure
tomcat7\webapps\ROOT\images\uploaded
tomcat7\webapps\ROOT\WEB-INF\classes
However, somehow when run the website via internet, it couldn't find the images\uploaded location.
Did i do anything wrong here?
Why getClass().getProtectionDomain().getCodeSource().getLocation().getPath() doesn't work in final product after compiled?
You should rather use ServletContext#getRealPath(...) to determine the file system path of your web application:
String absolutePath = request.getServletContext().getRealPath("/images/uploaded");
// File uploaded to this directory will be accessible via
// `http://<yourserver>/<web-app>/images/uploaded/`
But be careful! The servlet specification does not guarantee, that getRealPath will return a path to a writable directory. And it may return null in case the virtual path cannot be translated to a real path!
If you want to be sure, that the destination is a writable directory, and you just want to upload files into a temporary directory for processing, consider using the web application's private temp directory:
File tempDir = (File)request.getServletContext().getAttribute(ServletContext.TEMPDIR);
// Files uploaded to that directory will NOT be automatically published to WWW.
Note that this directory is temporary only and may not survive a server restart! So it is not thought for durable persistance.
The most sensible and durable solution is to write the file into a database, or any other repository (e.g. JCR like Jackrabbit), or into a file directory that is NOT controlled by your web server (and is specified from outside, e.g. via system property or in web.xml).

Get resource folder in java war file

I'm creating a REST webservice that uses keyczar for encryption. I've generated both public and private keys and placed them under src/main/resources/RSA.
To instantiate the encrypter I need to pass to it the location of the files like Crypter crypterPrivate = new Crypter(PATH_RSA + "/private"); but I'm having problems with the RSA folder location when I deploy the war file.
I've tried some stuff I've googled like InputStream but it is not this case since I don't want to pass any file but the RSA folder location. Also have tried several different folders like /WEB-INF/classes/RSA (it's where is located in war file).
Any tips? Thank you
If keyczar can take a URL for its key location then this.getClass().getResource("/RSA/private") will give you a suitable URL. If it requires a native file path then you'll have to use
ServletContext ctx = // ...
String pathToKey = ctx.getRealPath("/WEB-INF/classes/RSA/private");
Exactly how you get hold of the ServletContext depends on your toolkit. Note that this will only work if the WAR file is expanded on disk when you deploy it, it won't work if the app is running directly from the compressed WAR file.
You can access this file via the classpath.
URL resourceUrl = URL.class.getResource("/WEB-INF/classes/RSA");
File resourceFile = new File(resourceUrl.toURI());
I'm pretty sure the Java version of Keyczar doesn't support this functionality, but I believe someone submitted a small patch in their issue tracker to add it:
http://code.google.com/p/keyczar/issues/detail?id=55
KeyczarClassLoaderReader reader = new KeyczarClassLoaderReader(PATH_RSA + "/private");
Crypter crypterPrivate = new Crypter(reader);

File upload to the server directory

I am uploading an excel file to the tomcat server. Which is saving inside my eclipse directory D:\workspace_Eclipse\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\StatusPortal\Job_doc\abc.xls
When ever i am accessing this file its giving me file not found Exception \Job_doc\abc.xls.
Its could not able to find the path which is i am giving while accessing the file like
\Job_doc\abc.xls
I am giving the path \Job_doc\abc.xls while accessing.
This is because you are using a relative path. Eclipse will use the current working directory to be a temp location for deploying the webapp. So the file is uploaded to the folder relative to this path (This happens when you start the app from eclipse Run On Server. Define your paths as static constants(May be you can use absolute paths for testing). After testing you can use the relative paths on production deployment.
Still, you can do alternate way. Dont use the integrated tomcat server of Eclipse. Use a standalone server, use the descriptor file to link the webapp in workspace to tomcat. After the save, just reload the app in tomcat manager and try.
Try reading your file using ClassLoader as below:
InputStream inputStream =
getClass().getClassLoader().getResourceAsStream("/Job_doc/abc.xls");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream ));
If you want to get the File object, then try as below:
URI uri = getClass().getClassLoader().getResource("/Job_doc/abc.xls").toURI();
File file = new File(uri);

Classpath Resource in Tomcat6 (Works in Jetty)

I'm having trouble with a legacy Web Application that I'm migrating to Maven3.
I need to obtain a file from the Classpath that in the directory structure is located in:
/src/main/resources/com/thinkglish/geoip/GeoIP.dat
When I create the .war file with the Maven build, I can confirm that this .dat file is located (as it should be) in:
WEB-INF/classes/com/thinkglish/geoip/GeoIP.dat
I'm trying two different approaches to get the resource from one of my classes, which implements javax.servlet.Filter:
ClassPathResource resource = new ClassPathResource("com/thinkglish/geoip/GeoIp.dat");
and
URL resource = getClass().getResource("/com/thinkglish/geoip/GeoIp.dat");
If I start the application using Maven's Jetty plugin, that works fine in both ways. However, when I deploy the application in a Tomcat and start the server, the resource cannot be located.
In the first case I get a java.io.FileNotFoundException: class path resource [com/thinkglish/geoip/GeoIp.dat] cannot be resolved to URL because it does not exist and in the second case the resource is null.
A curious thing about all this is that if I use one method or the other trying to obtain another resource from the Classpath (e.g. com/thinkglish/struts/i18n/MessageResources.properties or com/thinkglish/filter/LanguageFilter.class) it works without any problems.
Do you have any guess about this? Is it possible that the .dat extension has anything to do with this?
Edited - More data!
I added a new .properties mock file to the exact same directory in which the .dat file lives:
/src/main/resources/com/thinkglish/geoip/mock.properties
I tried to obtain it in Tomcat6 and it worked!
ClassPathResource resource = new ClassPathResource("com/thinkglish/geoip/mock.properties");
I'm starting to think that I need to do something else configuration-wise to make Tomcat6 accept the .dat file as a Classpath resource.
Thanks in advance!
I might be barking up completely the wrong tree here... but have you checked the capitalisation of GeoIP.dat / GeoIp.dat? Is Tomcat running on a case-sensitive OS?
Following should work:
String classpathLocation = "com/thinkglish/geoip/GeoIp.dat";
URL classpathResource = Thread.currentThread().getContextClassLoader().getResource(classpathLocation);
// Or:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(classpathLocation);

Categories

Resources