Can I set Spring Boot's log location programmatically? - java

Spring Boot's logging location can be set using the logging.file property in application.properties. However I want to set the location programmatically. My logic is not based on any Spring beans, only on trial-and-error because the same code has to run across different environments which may have different security configurations.
According to the documentation:
Since logging is initialized before the ApplicationContext is created, it isn’t possible to control logging from #PropertySources in Spring #Configuration files. System properties and the conventional Spring Boot external configuration files work just fine.) [sic]
So I know I can't use #Configuration files, but can I use some other way like a static initialiser and still manage to set the logging location programmatically?
(NOTE: I'm personally using SLF4J with Logback, but Spring Boot's logging framework is meant to cope with different logging facades/implementations and in fact uses Commons Logging internally.)
(NOTE 2: Some people have noted this as a duplicate of another question...but that question seems to be talking more about configuring the actual logging implementation, whereas this question is about Spring Boot's own configuration. In fact, I cannot immediately determine from those answers how to solve my specific question, as noted in a comment underneath the relevant answer. The answer to that other question focusses mainly on how to get the code to load at the correct point of context initialization, whereas my question is about how to set the logging location.)

There's another answer: Spring Boot programmatic logging configuration
Basically, it's possible to do that via the SpringApplicationInitializer (implementing ApplicationContextInitializer)
SpringApplication application = new SpringApplication(MySources.class);
application.addInitializers(new LoggingInitializer());
application.run(args);

Related

How to use log4j2 in the web application WITHOUT log4j-web.jar

I want to put the configuration file of the log4j2 (v2.17.0) outside of the war file. Therefore, I can change the logging configuration without redeploying the war file. The log4j2-web.jar provides mechanism to configure the configuration file outside of the war file along with other features.
Unfortunately, I am not allowed to use the log4j-web.jar file in web application.
According to the log4j2 FAQ, it is not recommended to use LoggerContext to load configuration file because it is not part of the public API.
Question:
Is there any valid way to use log4j2 in the web application without log4j-web.jar file?
Question: Is there any valid way to use log4j2 in the web application without log4j-web.jar file?
There are two potential ways that you could dynamically update the logging configs without using log4j2-web.jar .
Ignore the FAQ's recommendation1 and use LoggerContext.reload to reload the configuration.
It is possible that the Log4j2 team could change something in a future version so that this approach no longer works. But this is unlikely (IMO) ... and you can deal with that problem if / when it happens.
Use Log4j2's automatic reconfiguration mechanism. Basically, you tell Log4j2 to regularly check the config file to see if it has changed.
However ...
If I was you, I would want to understand why you are "not allowed" to use "log4j-web.jar". Is it for security reasons? If it is, you may need to talk to the security people so that you fully understand the security reasons.
Q: Why?
A: Because you appear to be wanting to duplicate some of the functionality of "log4j-web.jar". It may be that it is the functionality you are trying to duplicate that is the root of your security team's concerns. And if that is the case, then implementing the functionality by hand (i.e. without using "log4j-web.jar") could potentially be worse ... from a security perspective!
So ... find out! This is NOT a case where "asking for forgiveness rather than for permission" is a sound strategy.
1 - Actually, I don't read this as a "recommendation". Rather, I read it as a "warning of potential consequences". If they really thought that using LoggerContext.reload this was a bad idea, I think they would have used more explicit language.

Why Java Config is favorable in spring boot when compared to XML config?

I am new to spring-boot. I am building a rest based application using spring-boot and was working on setting up security using spring-security. It is my understnading that I can setup spring-security with either xml config or with Java config.
However, I found the following in spring-boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-configuration-classes.html
It is in favor of using Java Config as opposed to XML config. Changes in Java config requires recompilation. Yet, it makes me think why the documentation favors Java Config.
Configuration classes Spring Boot favors Java-based configuration. Although it is possible to call SpringApplication.run() with an XML
source, we generally recommend that your primary source is a
#Configuration class. Usually the class that defines the main method
is also a good candidate as the primary #Configuration.
Many Spring configuration examples have been published on the Internet
that use XML configuration. Always try to use the equivalent
Java-based configuration if possible. Searching for Enable*
annotations can be a good starting point.
15.1 Importing additional configuration classes You don’t need to put all your #Configuration into a single class. The #Import annotation
can be used to import additional configuration classes. Alternatively,
you can use #ComponentScan to automatically pick up all Spring
components, including #Configuration classes.
15.2 Importing XML configuration If you absolutely must use XML based configuration, we recommend that you still start with a #Configuration
class. You can then use an additional #ImportResource annotation to
load XML configuration files.
There are some advantages
Java is type safe. Compiler will report issues if you are configuring right bean class qualifiers.
XML based on configuration can quickly grow big. [Yes we can split and import but still
Search is much simpler, refactoring will be bliss. Finding a bean definition will be far easier.
There are still people who like XML configuration and continue to do it.
For more info you can refer Java configuration advantages Some more reasons

Get list of Spring property placeholder and their resolved values

I would like to make all property placeholder and their resolved values of a running Spring (Boot) application available for process monitoring. In the first step this could be just by writing them to the logs or by creating a 'resolved.properties' file similar to the application.pid file.
All properties where property placeholder are used (implicit/explicit) should be considered.
Motivation: It is usually hard during operation to know the values of resolved properties. System properties or command line arguments are "visible" but e.g. hidden default values in the code (like #Value("${timeout:30000}")) are hard to find out. I would like to be able to answer the question "How does the configuration of the running application looks like?" in a generic way that I can use in all of my spring applications.
I know about the Spring Boot Actuator /configprops endpoint, but this only includes #ConfigurationProperties. I would like to get a list of all properties where placeholder are used.
The requirement does not seem to be new (see here or here) but I wonder if there is an appropriate (bootiful) way nowadays.
There is (currently) no way to obtain all the properties in the Environment abstraction. This is intentional as can be read here. This is also why it isn't possible to obtain all the values used for resolution.
The values and resolutions are logged at runtime telling which key was resolved from where at runtime. But that logging is quite verbose and logged each time a StringValueResolver is used.
You might get a partial result by providing your own customized PropertySourcesPlaceholderConfigurer which maintains a collection of resolved key/value pairs. But not every resolution uses the PropertySourcesPlaceholderConfigurer some directly use a StringValueResolver implementation bypassing the PropertySourcesPlaceholderConfigurer.
It doesn't cover all your needs (ie: properties from all files, default values, application arguments, etc.).
I'll still keep the answer for other readers/future reference.
Spring Boot's Actuator /env endpoint
You may use the /env endpoint. It lists a bunch of stuff but it also includes the content of application.properties (near the end):
applicationConfig: [classpath:/application.properties]={myproperty=blah, server.port=8080}

How to prevent Spring Boot Devtools from caching few files

I am using spring cache to cache my database results, when spring cache is enabled along with spring boot devtools we receive weird exception ClassCastException due to known limitation is spring dev tools.
Now I want to exclude the class which contains cache from auto restart or reload, How we can achieve this?
You can workaround this issue pretty easily.
First of, you can disable caching completely, simply add the following to your configuration:
spring.cache.type=none
You could add that as a system property, or in the run configuration of your IDE so that it only applies when you're using devtools on your box.
Then you can switch to a cache manager implementation that does not serialize the content of object. One way to achieve that is to create a cache manager in memory with a certain profile:
#Configuration
#Profile("dev")
public DevConfig {
public CacheManager cacheManager() {
return new SimpleCacheManager();
}
}
And then enable the dev profile (again via a property or in the run config of your IDE). This might now work if you have complex eviction rules.
Finally, you can fix the underlying problem by adding (including) the cache library (the component that is responsible of the serialization) in the application classloader. See this link for more details.
The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader. When the application is restarted, the restart classloader is thrown away and a new one is created. This approach means that application restarts are typically much faster than “cold starts”, since the base classloader is already available and populated.
By default, any open project in your IDE is loaded with the “restart” classloader, and any regular .jar file is loaded with the “base” classloader. If you work on a multi-module project, and not every module is imported into your IDE, you may need to customize things. To do so, you can create a META-INF/spring-devtools.properties file.
The spring-devtools.properties file can contain properties prefixed with restart.exclude and restart.include. The include elements are items that should be pulled up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that is applied to the classpath, as shown in the following example:
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar
see Spring boot devtools docs

Best practices for an application-wide logger

After a lot of attempts, I have am finally able to formulate a question. I hope it makes some sense and is easy to understand. Working on a web-application that uses Spring and Jersey. I am required to implement an application-wide logger that should log all the activities performed on the application into a database. For the time being I have used the HAS-A implementation and called the logging method everywhere a CRUD operation is performed. Something like this:
LogBean lBean=new LogBean("rickesh#email.com","update","address","127.0.0.1");
logToDatabase(lBean);
But this causes a lot of repeated lines of code and I have to repeatedly keep instantiating and calling the log method every section the CRUD operation in performed. Is there any way I can pull out the logging from the controller layer, the REST layer? Are there any specific functionality in Spring or Jersey with which I can perform logging on a separate layer and I don't have to keep repeating the same lines of code everywhere. Please advice.
If you are getting messy with writing your logs you should look into AOP. If you are already using spring you should read about Spring AOP, and for logging per se, read using Spring AOP for logging
AOP is a better way but if getting to learn it to resolve this issue is going to take longer then here is a simple alternative.
Add log4j JAR to your WebApp. Make sure, log4j version bundled in your WebApp doesn't conflict with the version already with your Application Server
Place a log4j.xml for FILE and CONSOLE appendars in your class path (src/main/resources)
There is a Log4JConfigureListener provided by Spring which you can declare under section in your web.xml
Additionally, if too much log is generated, you can limit the output of the loggers via either log4j.xml in your application to certain packages only or via using Root logger configuration for your project specific packages. For example, in JBoss you can add a "category" for a package at a specific LOG level
Your specific "separate layer" should have a separate and distinct package name to target the log appendars for that layer
Hope this helps!

Categories

Resources