I have a dependency utilities.jar which has a dev.properties file in the root directory when compiled (in src/main/resources when uncompiled). The jar has a class (PropertiesUtil.java) that loads the properties with:
PropertiesUtil.class.getResourceAsStream("/dev.properties");
This jar is included as a dependency in my webapp. The webapp has its own dev.properties file in its root directory when compiled (in uncompiled form its in the src/main/resources folder).
The utilities.jar does not load its own internal dev.properties file but instead the webapp's dev.properties file.
I tried different methods like
PropertiesUtil.class.getClassLoader.getResourceAsStream("dev.properties");
without success.
I am using Gradle to compile the utilities.jar and the webapp into a war. The properties filename need to be the same because I pass in a JVM property
-Dproperty.filename=[dev|qa|prd].properties
when starting up the webapp. This system property is used to load the correct properties files for the webapp and the utilities.jar.
The utilities.jar is a separate project and packaged with gradle clean build and uploaded to an artifact server. The webapp pulls the utilities.jar from the artifact server when building the war.
I think this problem is occurring because you have two different files with exactly the same path (even though one is inside a jar) inside your classpath. It's very possible one dev.properties is getting overwritten.
I recommend changing the path of at least one of the properties files to be outside of the project root. For example, put the uncompiled dev.properties for Utilities at:
/src/main/resources/utilities/dev.properties
Then access it with:
PropertiesUtil.class.getClassLoader.getResourceAsStream("/utilities/dev.properties");
Then the two properties files won't stomp on each other anymore, and that should fix your problem.
Related
We have a maven project which has only yaml files and relevant text files under src/main/resource folder. We are packing this as Jar file. The structure is as:
src\main\resource
application-configone.yml
application-configtwo.yml
license.txt
application-configone.yml file has entry for license.txt file
license
path: src\main\resource\license.txt
Now we import this Jar artifact in another web application. In web application yml file, we are importing the yml file from Jar as
spring.active.profile = configone, configtwo
The issue that we are getting is that web application fails to start as it is not able to read/get license.txt file defined in application-configone file.
How can we read/access license.txt file which is packaged in a jar in our web application
The easiest way is to put the file under resources directory.
In project where read, create a
appContext=new ClassPathXmlApplicationContext()
and use that to reach the file.
Use relative path from resources folder (in your example you use resource without s on the end, maven default is resources). You can obtain any files on your classpath to this anyway.
res = appContext.getResource("classpath:licence.txt")
It will give back a Resource object. You can use it's inputStream now as you want.
Take a look inside the jar which contains the resources (appconfs and txt), so you can be sure it was built properly, and the files was copied into the classpath.
I'm using Intellij.
I have a jndi.properties file (used for connecting to a Wildfly instance).
By default, Maven includes this file inside the JAR , after build. This is not good, as the jndi.properties contains the URL and credentials to the Wildfly instance and in production these will be different.
I managed to exclude the jndi.properties file by placing it in a separate folder (called config), and then in Intellij -> Module Settings -> Sources I marked the config folder as Resources and Excluded. This way, when I run the application inside Intellij, it works fine. But when I build the JAR, even if I place a folder called config outside the JAR, I still get an exception because no jndi.properties file is found in the classpath.
The same happens if I declare the config folder in the Dependencies tab in the Module Settings.
I also tried specifying the classpath when I run the java cmd line tool, but it seems that -cp does not work along with -jar.
I know two alternatives, but I don't really like them: have jndi.properties in JAVA_HOME/lib (not good, it will be common for all applications) or at runtime (-Djava.naming.provider.url etc, not as clear as a configuration file in my opinion).
Is there any way I could specify the jndi.properties file location at runtime?
I am trying to learn about the Spring framework for Java and I am not sure where about's I am supposed to put the applicationContext.xml file for configuring the spring beans. My directory structure is as follows:
Do I put in .settings? Or should it be put at the top level within springapp?
Thanks for the help.
Put into directory WebContent/WEB-INF.
Resources placed into WEB-INF folder are not accessible from web, they are application internal resources. This is good, because your applicationContext.xml shouldn't be accessible from web.
Other good options are WebContent/WEB-INF/classes or just src (both are equal).
Files and folders with . contains Eclipse configuration files, they are internal for Eclipse - do not use them.
I recommend to put it in the src (or src/META-INF) folder and access it via classpath:applicationContext.xml (or classpath:META-INF/applicationContext.xml). (Eclipse will copy this file to WebContent/WEB-INF/classes when it build the war archive.)
Because:
The mayor advantage of src over src/main/webapp/WEB-INF / WebContent-WEB-INF is, that you can access the src files even in the tests (via classpath:applicationContext.xml)
Do NOT put it .settings because the content of this directory gets not deployed in the Web App (it is eclipse configuration folder)
Of course when you use maven, then put the file in src\main\resources (or src\main\resources\META-INF), Maven will copy them to the classpath folder while compiling.
WEB-INF or its subdirectories. This folder's content is packed directly into the root war file, so files that are directly under this folder are accessible as resources with path like '/foo.xml' (or in spring notation classpath:/foo.xml
It needs to be in the classpath. You can put the original editable instance anywhere (e.g. a config directory off the root) but then you will need to have your build management tool (e.g. Ant or Maven) copy it into the classpath for the runtime.
Recently I separated the core functionality of my core servlets application into a jar file. This jar file is now deployed in tomcat's lib folder and the application(i.e. servlets, jsps, properties files..etc) is deployed independently as a war file.
The jar files needs specific properties files. I place these properties files right under the "src" folder(i.e. in the top of the classes hierarchy) in the war file.
In the past when everything was in the same project and deployed in one war file. The properties files were accessible by the related classes. Now when these classes are deployed in a jar, they can't see the properties files located in the war file (i.e. deployed web application).
What could I be missing here ?
An example how I load my proeprties files:
properties.load(getClass().getResourceAsStream("/appconfig.properties"));
Thank you for your time.
You shouldn't get it by the class' own classloader. As the class is now managed by Tomcat, it only knows about Tomcat's internal resources, not about webapp-specific resources. You should get it by the context classloader of the current thread. That classloader knows about all resources dedicated to the current webapp.
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("appconfig.properties"));
Regardless of this, the proper location of such a properties file representing the global app configuration would not be inside the WAR file. You should rather place the properties file on a fixed path outside Tomcat and the WAR file and then add that fixed path to the shared.loader property of Tomcat's /conf/catalina.properties so that it becomes part of the classpath. This allows you for freely editing the configuration file without the need to rebuild/redeploy the whole WAR. Note that you still need to use the context classloader to load it.
Yes, that won't work because the jars in tomcat lib folder are loaded by a different classloader that knows nothing about your webapp's classes. In other words, tomcat lib is the parent class loader of the webapp classloader (which are created one per each webapp).
If you want to make it work, you can either place the properties file in an external location and make it known to the jar inside tomcat lib via absolute file path or place the jar back inside webapp's lib.
Here's some reference from the Tomcat site.
http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html
Typically, environment variables are used to identify $CATALINA_HOME which will then be prefixed to the relative file path in order to avoid hardcoding the absolute paths.
String catalinaHome = System.getProperty("CATALINA_HOME");
properties.load(new FileInputStream(new File(catalinaHome + "/path/to/appconfig.properties")));
I currently started working on a maven web-app project that needs to be launched with the jetty:run-exploded goal for development/debugging in eclipse.
Now, I have an XML file which contents I need to access at runtime. My problem is: where to put the file so that the code that does the reading works both in "exploded" and packaged (i.e. in the WAR) mode?
Putting the file in src/main/java (so as to be in the classpath) won't cut it since maven filters out all non-java files on packaging.
When the file is in src/main/resources, one mean would be to figure out the root path of the project (during eclipse development) and look into that directory - but this won't be the case anymore when the project will be packaged.
Of course I could go into writing code that tries to read the file from both locations, but this seems rather cumbersome. Any suggestions?
Files in src/main/resources are copied to the target/classes directory and are available on the class path. Just read them from the class path. As explained in How do I add resources to my JAR? from the maven documentation (with a test resource here):
In a unit test you could use a simple
snippet of code like the following to
access the resource required for
testing:
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream("/test.properties" );
// Do something with the resource
...
In such case I put the file under src/main/resources directory and use Spring's ClassPathResource. This way the file is accessible in IDE, during Maven build process and in runtime.