Specify jndi.properties location outside built JAR - java

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?

Related

Take logback.xml to outside of the jar

I am using logback with slf4j in my Maven Java project. Currently logback config file (logback.xml) is in src -> main -> resources folder. And it is working fine.
My issue is, I need to give my client the ability to configure logging as he prefers. For that logback.xml should be outside the jar when I build it. But as xml is inside src folder it is inside the jar and no one can change it after build.
How to achieve this?
Specifying the location of the default configuration file as a system property
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml -jar myapp.jar
From offcial docs
Logback config file location can be specified in application.properties or application.yml.
application.yml
logging:
config: logback-spring.xml
This allows you to place jar and log-back.xml at the same folder.
Please note that logback-spring.xml file in your project folder should not be included in your jar. This can be achieved setting on build.gradle or pom.xml.
build.gradle
bootJar {
archiveName 'your-project.jar'
exclude("*.xml")
}
The logback.xml file needs to be on the classpath, but it doesn't need to be inside any specific jar. The details of how you want to do this depend on the exact deployment mechanism that's being used: How does whatever's starting this application set the classpath? Whatever that mechanism is, you should be able to configure it to include wherever you're putting the logback.xml file, and then just don't include in in the src/main/resources to be embedded in the jar file.
Depending on the complexity of what you're going for, you may find the maven-assembly-plugin useful for creating your distribution of dependencies.
Using Scala SBT (1.2.1) on Windows:
Batch file:
#cd %~dp0
#set JAVA_OPTS=-Dlogback.configurationFile=logback.xml
#sbt clean run
worked for me (strange ...)

Dependency jar not loading its own resource file

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.

Java - how to get properties file from other modules

In one of module 'scheduler' classes I need to use data from properties file from modules : backend, common end entity-managers (e.g). Properties file are held in (module)/src/main/resources. How to achieve that?
You can access them easily using the ClassLoader.
this.getClass().getClassLoader().getResourceAsStream("myproperties.properties");
This will return the stream to the file, even if the file is in a different jar file.
Remind: Modules should stay seperated, try changing your code to go without such dependencies. Is it possible to set the necessery values on schedular initialization instead of reading them in scheduler itself?
Below are the two options I can think of:
1) In eclipse, for scheduler module, add other modules (e.g. backend) as dependencies (R-click on project > Build Path > Configure Build Path > Projects > Add). This will add the classpath entries of the added projects in scheduler classpath. If you are using maven, you may have to add the projects as internal dependencies in pom.xml of scheduler module as well.
2) Externalize the properties file by putting it outside your project structure, somewhere on the filesystem - e.g. under C:\properties directory. Add this directory to your project classpaths for modules, which use the property file. You can do this in eclipse by (R-click on project > Build Path > Configure Build Path > Libraries > Add Variable). Also ensure that the directory is there on your classpath when you run your application. If you are running it as standalone java application, then add the path in -cp switch of java command. If you are running it in any container, add the directory to your container's classpath.

Trying to reference a folder with my .properties and log4j files in IntelliJ

I don't want to put my .properties and log4j files in my /resources folder in my spring MVC appication because these will get put into the jar at compile time, and I want to be able to edit these files on my server when I deploy my application.
So I created a folder and dropped my log4j, *.properties files, and my spring-context.xml file in it.
I have a maven multi project, and my folders look like:
/myapp-persists
/myapp-web
/src/main/conf
The /src/main/conf has my property files, so in IntelliJ I went to the myapp-web module and added a 'jar or directories' dependancy, pointed to that folder and chose 'classes'.
It didn't work, my files were not picked up and starting the server resulted in a crash, the property files were not detected.
What am I doing wrong here?
It seems me doing this via intelliJ is going to cause my maven builds to fail then right? I really don't want to create a separate maven project for this.
You can just use the context menu on /src/main/conf and choose Directory : Add as Source. In the preferences you should set keep source folders in the maven settings (not really sure about the naming of the menu/settings - no idea at hand, sorry). The jar dependency is not needed.

What is the Maven idiom for accessing configuration files?

For example suppose I'm using the standard project structure and have
src/main/config/config.xml
To access this I presume
new File("src/main/config/config.xml");
would be incorrect
There is no "Maven Idiom" for accessing configuration files. Maven is a build platform, not an execution platform. So the conventions for accessing configuration files that apply are really just the conventions of the Java platform that you are using; e.g.
the plain J2SE way of doing it, or
the J2EE and/or webapp way of doing it, or
the J2ME way of doing it, or
...
Maven only comes into the picture because you (presumably) have resource files in your project / version control that need to be included in the JAR or WAR or whatever artifacts that you are building. To get this to work in Maven, you simply need to understand how Maven copies non-Java files into the artifacts.
In the simple (JAR) case, the default behavior is to copy anything in src/main/resources/ into the JAR, with the same relative name; e.g. src/main/resource/foo/bar.xml becomes /foo/bar.xml in the JAR file.
For WAR files, the default is to copy anything src/main/webapp to into the WAR file. So if you wanted a file to be accessible in the webapp as a classpath resource with the name /foo/bar.xml you would put it in src/main/webapp/WEB-INF/classes/foo/bar.xml. (I'm assuming that you know how webapp classpaths work ... or that this isn't your use-case.)
A config file is just a resource on your classpath like any other, so use:
URL resource = getClass().getResource("config.xml");
You'll need to do the usual Use as Source Folder on your src/main/config folder for this to work in Eclipse with m2e.
I think config files should be in src/main/resources by default.

Categories

Resources