I'm at the final step of developing (and especially deploying) a client server application where I have a secured connection using TLS. I got the keystore and truststore for the client and the server and currently I load them as SystemProperties before creating the SSLSocket / SSLServerSocket like this:
Properties systemProperties = System.getProperties();
systemProperties.put("javax.net.ssl.keyStore", "./auth/labkey.jks");
systemProperties.put("javax.net.ssl.keyStorePassword", "<somepassword>");
systemProperties.put("javax.net.ssl.trustStore", "./auth/labtrust.jks");
systemProperties.put("javax.net.ssl.trustStorePassword", "<somepassword>");
System.setProperties(systemProperties);
This works fine but - as I already thought - doesn't when packaging everything into a .jar file. Currently my project folder consists of the normal src folder in which I keep all the packages with the sourcecode files. The keystore and truststore are kept in a folder called "auth" which is on the same level as the src folder.
I know from previous projects that the relative path changes when packaging additional files into the .jar however the first thing is I don't know how I should properly handle these file to have them packed into the .jar (currently they are only included when I create a package for them in the source folder or declare the auth folder as an additional source folder).
I tried both approaches and after testing a lot of different relative paths (which is the second problem: finding the right relative path) I couldn't figure out how to properly address them.
Any advice or hint would be really appreciated.
EDIT:
After trying out several things in context with suggested ideas I can narrow the problem down to the path to the keystore and truststore file being my actual problem. I'm quite sure if I were able to access it relatively there would be an option to use, however for accessing the files I HAVE to provide a path in any kind, no matter which approach I'm going to use. The fact that I'm not able to get the proper relative path to the file is therefore the main problem which I need to get solved.
So accordingly these questions come to my mind:
How do I correctly add these files to the .jar?
Will I need to make the auth folder a source folder or do I need to put it in a package or is there any need or possibility to configure the files correctly by configuring the build path?
What will then be the relative path to the files?
Quick edit: this has been answered before in previous threads - I'm sure my explanation is sub-par here, but this came up recently for me as well and this was my solution
You may want to use getClass().getClassLoader.getResourceAsStream("filename.properties")
Properties properties = new Properties();
String propertiesFileName = "config.properties";
inputStream = getClass().getClassLoader().getResourceAsStream(propertiesFileName);
if (inputStream != null) {
properties.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propertiesFileName + "' not found.");
}
Related
I have a question regarding file handling.
I automate a page using selenium, and I need to upload a file in this page.
I want to put the file in resource folder and read it's path in the test (since many OS and path will be different to any computer WIN/MAC).
I put the file manually in the resource folder, and it put it in:
X:\Project_11_01_2021\src\test\resources
when I used the ClassLoader and try to find the file it not found it,
I saw that if I manually put it in this path it find it, found.
X:\Project_11_01_2021\out\test\resources
the problem is that I am using git and if I add to the resources it upload to git and every one will get the change, and when I put in out\test\resources it is not displayed in the source tree to commit to git.
is their a way that classLoader will search in the first location? and not in the second?
[][path that worked]
[][when here not worked]
/******* test *******/
public void entertax() throws Exception {
WebDriver deiver2 = getWebDriver();
Thread.sleep(1000);
ClassLoader classLoader = getClass().getClassLoader();
String path = classLoader.getResource("TAX12.pdf").getPath();
System.out.println("\n\n path is " + path);
deiver2.switchTo()
.activeElement();
deiver2.findElement(By.xpath("//input[#type='file']"))
.sendKeys(
"X:\\Project_11_01_2021\\out\\test\\resources\\fw8TAX12.pdf");
System.out.println("END");
}
This issue looks more like an IDE configuration problem.
Your code classLoader.getResource("TAX12.pdf") looks correct (1. using classLoader.getResource() method && 2. specifying the correct relative path within the resources folder).
I assume why the code fails to find the file is due to the fact that the resources folder is not part of your applications classpath (I'm assuming your trying to run the code from your IDE which apparently seems to be IntelliJ).
I'm not regularly using IntelliJ, but you can specify the classpath settings in the Module settings.
In the Module settings specify the resources folder as a resource:
When successfully added the resources folder to the classpath it should display an icon like this in the project explorer:
After adding the resources folder to your classpath everything should work.
EDIT:
In case you're using Maven also make sure to specify the resources folder as such in the pom.xml file correspondingly.
Also make sure to spell the name of the file you're looking for "TAX12.pdf" correctly, since it seems to differ in your code and in your screenshots (not sure if it differs only because posting it here or also in your real code base).
I've got a project to do with 2 other classmates.
We used Dropbox to share the project so we can write from our houses (Isn't a very good choice, but it worked and was easier than using GitHub)
My question is now about sharing the object stream.
I want to put the file of the stream in same dropbox shared directory of the code.
BUT, when i initialize the file
File f = new File(PATH);
i must use the path of my computer (C:\User**Alessandro**\Dropbox)
As you can see it is linked to Alessandro, and so to my computer.
This clearly won't work on another PC.
How can tell the compiler to just look in the same directory of the source code/.class files?
You can use Class#getResource(java.lang.String) to obtain a URL corresponding to the location of the file relative to the classpath of the Java program:
URL url = getClass().getResource("/path/to/the/file");
File file = new File(url.getPath());
Note here that / is the root of your classpath, which is the top of the directory containing your class files. So your resource should be placed inside the classpath somewhere in order for it to work on your friend's computer.
Don't use absolute paths. Use relative paths like ./myfile.txt. Start the program with the project directory as the current dir. (This is the default in Eclipse.) But then you have to ensure that this both works for development and for production use.
As an alternative you can create a properties file and define the path there. Your code then only refers to a property name and each developer can adjust the configuration file. See Properties documentation.
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"));
I am making an java application which reads a file from a particular location. The location of the file is in the folder retrived from
getCanonicalPath().
The problem i am facing is that when i am running my application in Eclipse the canonical path is different from the one which Dr Java sees. So, what should i do before delivering my application to the client to make sure that it sees the file no matter which ide/command prompt is used to run the application. Obviously it would not be a good idea to copy the same file across all possible folders to cover different possibilities of getCanonicalPath.
Thanks
One of the solution is to have this file in your classpath and load it from your classpath, with a code like
URL url = getClass().getClassLoader().getResource(path);
if(url != null) {
try {
return new File(url.toURI().getPath());
} catch (URISyntaxException e) {
return null;
}
}
This is standard if this file is a configuration file. Usually in a standard java project layout you put this in the folder src/main/resources.
If this is more of a data file, you should put in a configuration file its path, and have different configurations, one for your station and one for production on the client machine. Of course in this case the configuration file is in the class path ;).
A common solution is to place the file in a directory which is in the class path. If you use getResource or getResourceAsInputStream you can find the file regardless of where it is provided its in the class path. if you use maven you can be sure how the classpath is setup regardless of the IDE used.
You should always load file ClassLoader using API like Test.class.getClassLoader().getResource(name),Test.class.getClassLoader().getResourceAsStream(name) More Information available here
when i am loading some data into my java program, i usually use FileInputStream. however i deploy the program as a jar file and webstart, so i have to use getRessource() or getRessourceAsStream() to load the data directly from the jar file.
now it is quite annoying to always switch this code between development and deployment?
is there a way autmate this? i.e. is there a way to know if the code is run from a jar or not?
when i try to load it withoug jar like this:
InputStream is = this.getClass().getResourceAsStream("file.txt");
the returned inputstream is simply null, although the file is definitely in the root directory of the application.
thanks!
Why do you use FileInputStream during development? Why not just use getResourceAsStream from the very start? So long as you place your files in an appropriate place in your classpath, you shouldn't have any problems. It can still be a file in the local filesystem rather than in a jar file.
It's helpful to develop with the final deployment environment in mind.
EDIT: If you want something in the root directory of your classpath, you should either use:
InputStream x = getClass().getResourceAsStream("/file.txt");
or
InputStream x = getClass().getClassLoader().getResourceAsStream("file.txt");
Basically Class.getResourceAsStream will resolve relative resources to the package containing the class; ClassLoader.getResourceAsStream resolves everything relative to the "root" package.
You could read your data always as a ressource. You only have to add the path where the data lies to your classpath.
If your data stays in WEB-INF/somewhere/mydata.txt inside your jar file, you will access it with:
getClass().getResourceAsStream( "/WEB-INF/somewhere/mydata.txt" )
Now, if you create a development directory /devel/WEB-INF/somewhere/mydata.txt and put /devel to your classpath, your code will work in development and production.
EDIT after explanation in question:
In your case this.getClass().getResourceAsStream( "mydata.txt" ) the resource is taken from the same position where the classfile of this is taken from. If you want to keep this, then you have to create a directory /devel/<path of package>/mydata.txt and again add /devel to your classpath.
How about setting a system property in your dev environment, via the -D switch? e.g. java -D:mypropertyname=mypropertyvalue
You could set the property in ant scripts in your dev environment, other environments don't get the property:
e.g.
public static boolean isDevEnvironment(){ return System.getProperty("mypropertyname")!=null;}
You might find a better way to hack it from one of the existing System Properties
If a file is considered part of your deployed application (as opposed to be part of the installation specific files) and can be located through the classpath then consider simply always using getResourceAsStream since it works regardless of the actual deployment scheme as long as it is in the classpath.
You might also find the information available from the JVM relevant (if allowed by the security manager):
// Get the location of this class
Class cls = this.getClass();
ProtectionDomain pDomain = cls.getProtectionDomain();
CodeSource cSource = pDomain.getCodeSource();
URL loc = cSource.getLocation(); // file:/c:/almanac14/examples/
http://www.exampledepot.com/egs/java.lang/ClassOrigin.html?l=rel
There shouldn't be any difference between development vs deployment, IHMO.
Classloader.getResource or getResourceAsStream works well, you can read resources and even write them.You can write your own Protocol handles and access everything as an URL/URI, which allows you to read and write resources and also allows proper identification of who actually provide the resource.
The only problem is if an URLStreamHandlerFactory is already registered(in a J2EE application the container could install a factory and you don't have any way to go over and install your own) and you cannot use your handlers "anywhere".
Knowing that, it is preferred to implement your own "resources". At that time when I need it I couldn't find something like that so I had to implement my own ResourceManager. For me it looks more intuitive to access a resource like
Resource layout = ResourceManager.resolve("view://layout/main.jsp")
instead of
URL layout = Classloader.getResource("some_package/view/layout/main.jsp")