How to configure logging when running a JAR? - java

I am new to Java logging API and need some help with this problem:
While creating the application, my config file was stored in the project root folder, so I used -Djava.util.logging.config.file=logging.properties switch to run the program.
But then I exported the executable JAR.
How to configure the logging now? It doesn't work, when I specify the path to config file with the -D switch.

You can't specify JVM arguments into the MANIFEST.MF file so you have to specify the logging properties at the command line or with a shortcut :
java -Djava.util.logging.config.file=logging.properties -jar yourjar.jar
Otherwise you could package a properties file(logging.properties in your case) in the JAR, read that at
startup and put those settings into the system properties.

The javadoc says:
In addition, the LogManager uses two optional system properties that
allow more control over reading the initial configuration:
"java.util.logging.config.class"
"java.util.logging.config.file"
These two properties may be set via the Preferences API, or as command
line property definitions to the "java" command, or as system property
definitions passed to JNI_CreateJavaVM.
If the "java.util.logging.config.class" property is set, then the
property value is treated as a class name. The given class will be
loaded, an object will be instantiated, and that object's constructor
is responsible for reading in the initial configuration. (That object
may use other system properties to control its configuration.) The
alternate configuration class can use readConfiguration(InputStream)
to define properties in the LogManager.
So, either use the java.util.logging.config.file system property, and store the config file out of the jar file (which is probably a good idea if you want to be able to customize the logging properties in order to debug or analyze some weird behavior), or store the config file wherever you want (in the jar file, for example), and use the java.util.logging.config.class system property to load and instantiate a class that will read the file in the jar file (Using Class.getResourceAsStream()).

I know it's little late to answer this question but I ran into this issue few days back with the runnable jar and I solved it like this:
java -Djava.util.logging.config.file=logging.properties -cp test.jar com.sample.test.Main
where test.jar is the name of your jar and com.sample.test.Main is the fully qualified name of your main class.

Related

Use single profile-specific property file from multiple application.properties files

I have a few spring-boot microservices and I want to use a single profile-specific property file for all the microservices. profile-specific property file should be outside of the jars.
example:
The application-common-profile.properties file and jar files are inside the same folder
java -jar Microservice-1.jar --spring.config.location=classpath:/application.properties --spring.profiles.active=common-profile
java -jar Microservice-2.jar --spring.config.location=classpath:/application.properties --spring.profiles.active=common-profile
the above commands won't take the common-profile properties. please help to achieve this. Thanks.
IMPORTANT DETAILS
This jar file doesn't contain 'application-common-profile.properties' file. this file resides outside the jar but in the same folder. if I put my 'application.properties' file inside the same foder then it is working(retrieving the properties) with the below command.
java -jar Microservice-1.jar --spring.config.location=C:/folderpath/ --spring.profiles.active=common-profile
I can place other microservices 'application.properties' files in same folder with different names(ex: application-microservice-2.properties). and also the profile property files with different names.(ex: application-microservice-2-common.properties ) It's okay having different application.properties files. but need to have one common profile property file.
FIXED
I added common profile property file(application-common.properties) and jars in same folder and run below commands simply and it is working. I think adding unnecessary arguments was the problem.
java -jar Microservice-1.jar --spring.profiles.active=common
java -jar Microservice-2.jar --spring.profiles.active=common
If your application.properties file is bundled in your jar, then simply adding the profile-specific property file to your working directory will allow it to be picked up. However, when you set spring.config.location you're overriding the path that Spring will look up these properties from, you should drop this, it's not necessary. Spring will look in your working directory for the properties files by default if they're not bundled in the jar.
Personally, I would avoid trying to maintain the property files in the environments in favor of environment variables.
Bundle your jar with the top-level application.properties included in it, and for the variables that are different given the environment, set environment variables for them.
e.g. if you want to override spring.datasource.driver-class-name, set the environment variable SPRING_DATASOURCE_DRIVER_CLASS_NAME. I think you'll find this approach is far more flexible.

Custom application properties in spring boot using IntelliJ

I'm trying to use application properties, other than application.properties, say application_local.properties within resources directory.
So that I can have 2 properties files, one for local and other the server.
As mentioned in many blogs, I should use below command:
spring-boot:run -Dspring.config.location=/Users/myuser/work/MyProject/my-app/src/main/resources/application_local.properties
But this is not working, it is still fetching values from application.properties.
What am I missing, please suggest?
Thanks
1- Follow the naming convention application-{profile}.properties
application-local.properties
2-set profile
-Dspring.profiles.active=local
Briefly, you can use these two links:
How to load property file based on spring profiles
spring-profiles
-Dspring.profile.location takes directory as input. The purpose of this property is to specify additional directory location to keep your property files.
You are using property file name in your command.
Refer to detailed # Answer at other thread here
Instead you can use as suggested by #mehardad
The -D option will send parameters to Java virtual machine. In order to send parameters to Spring boot, the command option of '--' must be used.
Example:
Suppose, there is an option named 'spring.profiles.active' defined in the application.properties file as follows:
spring.profiles.active=dev
This option can be overwritten using command line parameter as follows:
java -jar application.jar --spring.profiles.active=prod
Use Spring profiles and choose at runtime, locally would
-Dspring.profiles.active=local
The property file should be called application-local.properties

how to make logback identify logback.xml?

Currently when I execute my code I it doesn't create any log file.
the logback.xml is configured fine, however I don't see a way to configure where to find the xml file
Per the Logback manual chapter on Configuration:
Let us begin by discussing the initialization steps that logback follows to try to configure itself:
Logback tries to find a file called logback-test.xml in the classpath.
If no such file is found, logback tries to find a file called logback.groovy in the classpath.
If no such file is found, it checks for the file logback.xml in the classpath.
If no such file is found, service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of com.qos.logback.classic.spi.Configurator interface by looking up the file META-INF\services\ch.qos.logback.classic.spi.Configurator in the class path. Its contents should specify the fully qualified class name of the desired Configurator implementation.
If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.
The standard approach that this is trying to tell you about would be to have logback.xml be in the classpath for "normal" running, and have a logback-test.xml in the classpath to describe how you want to log when running automated tests. (For example, you may want to log to a file in your regular application, but have your automated unit tests just log to the console.) The exact process of putting a file into the classpath depends on what build system you're using. For example, with the default settings in the popular Maven build system, you would put logback.xml inside src/main/resources, and (if desired) a logback-test.xml inside src/test/resources. If you're having trouble with this step, you may want to search for or ask another question with more details about the build toolchain you're using. Also be sure to read "What is a classpath?"
Another approach, also listed in the Logback manual:
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 chapters.configuration.MyApp1
Note that the file extension must be ".xml" or ".groovy".
This wouldn't be as common, but sometimes if you need to run in a particular environment with a certain logging configuration, or run some sort of automated test directing output to a different place than your normal tests, it can come in handy to just outright configure the path like that.

How to modify a properties file in spring boot jar

I am writing a Spring Boot Application.
This application talks to a Main Frame through MessageQueues
So inorder to talk to that MainFrame we are provided with a java jar(which has the code that talks to MessageQueues ). lets call it proxy jar.
We have to use the operations written from the above mentioned proxy jar .
We dont write any code to read/write to MessageQueues (IBM MessageQueues) in our application, this is done by the proxy jar and its dependent runtime jar.
So here comes the problem, this Proxy jar is coded in such a way that it looks for a file called 'commcfg.properties' in the classpath (expects the name to be exactly same). Actually the Proxy jar uses another dependent jar (lets call runtime jar)which reads the queue details from commcfg.properties and reads/writes from Message Queues.
commcfg.properties have the values of MessageQueue and Host and port of those Queues . In short Queue details.
So the trouble is these MessageQueue details will be different in different environments. I need to use the commcfg.properties according to environment
So far my trials to solve this.
Lets say I have two environments .
So I will have two different set of values of commcfg.properties
I have created files as follows
commcfg.DEV.properties
commcfg.PROD.properties so that they will be in classpath
Next I have written code such that it will pick up the particular property
file depending on Environment and rename it to commcfg.properties(as the
Proxy jar and its helper dependent Runtime jar need the exact name to be
commcfg.properties).
In my local workspace I could do this .
But when deployed (we use docker) that gets packaged into spring boot jar.
So my hack is not working as we cannot rename files with in jars.
Another thought I had:
Before I call my functionality code , I will put the commcfg.properties in
class path (project/src/main/resources)
I will read it and modify the values as needed per environment.
The values I will have them in application.properties.
But again I doubt that with in jar I cannot modify the file.
Hoping I am clear
Kindly help me out..
In spring boot, You can register your properties file with a Java annotation #PropertySource
#SpringBootApplication
#PropertySource("classpath:commcfg.properties")
public class ApplicationConfig
{
public static void main(String args[])
{
SpringApplication.run(ApplicationConfig.class);
}
}
and let the commcfg.properties file contain the DEV environment details
messageQueue.name=myMessageQueue
messageQueue.host=host
messageQueue.port=4040
Now build your jar file and you get yourjar.jar
Now run it in DEV environment with default values
java -jar yourjar.jar
run it in QA environment with overriding the default values in your config file
java -jar --messageQueue.name=diffrenthost --messageQueue.host=diffrenthost --messsageQueue.port=diffrentport yourjar.jar
This way you can override your default values. I hope this helps
you can put the properties files on the same path of spring-boot jar, the config items can override the properties in the jar.

Using batch file to run a jar file

I found a way to set the classpath for the resource file. I am using a batch file to run my JAR. I have set the path like this
echo off
cd..
set BASEDIR=E:\SampleSourceCode
java -Dfile.encoding=UTF-8 -cp %BASEDIR%\lib\*;%BASEDIR%\data\;%BASEDIR%\resources\ com.example.main.Main
But now when I do any changes to the contents of the resource folder (properties file), the GUI does not recognize the database from the data folder. How do I proceed?
I think you're asking:
Q: If I change the contents of an external properties file, will a running Java process automatically update the property files originally read from the file?
A: No, it won't.
The general solution is:
Modify the property in your program
Have your program re-write the external properties file
the best way to set a library to execute a .jar file that requires outside resources, is simple use the following batch file:
javaw -Djava.library.path=<path to library> -jar <name>.jar
in this way, anything that you change will still be accepted as long as it occurs in your path to library.(or in the jar itself.)

Categories