How to configure log4j to log Spring injections - spring

How can I configure log4j to write an entry to the log every time it injects a class?
My use case is this: I have Autowiring enabled. I have some interfaces with multiple implementing classes. I want to be able to see in the log which impl class gets injected to another class.
Any thoughts?

How can I configure log4j to write an entry to the log every time it injects a class? ... Any thoughts?
My thought is that the real problem is to get Spring or your application to generate the log events; e.g. to call the relevant methods on a Logger at the relevant point.

Related

How to load PropertySources sooner in Spring Boot

I have currently a problem in my DEV environment. I have for Spring Security two configurations, one for the Admin part of my application and the other for the rest of the user. For the admin part, I create one or another depending on beans decorated with a Conditional annotation. This conditionals rely on some property that is loaded from a class that is annotated with #PropertySource and this is important, this property I cannot set it neither in application.properties nor application-<environment>.properties. The problem comes that when these conditionals are evaluated because are spring security classes, the properties that are expected to perform such evaluation are not available, they come in a later stage, when Spring boot do some refresh context. My question is how I can do it do this class annotated with #Configuration #PropertySources to be loaded much sooner, right after the Profile is processed.
Thanks in advance.

Run Mongock before #Configuration annotated class

I want to use Mongock migration tool to initialize my app's configuration that is stored in database.
The problem I have is that one of my configs is used in class that is annotated with #Configuration. As Mongock changesets are executed after #Configuration it cannot retrieve not existing yet value from database and that results in a crash of application. Is there a way to postpone creating #Configuration class? Or should I initialize this one config without using mongock?
I don't fully understand your issue. I think that you need Mongock to run before your class annotated with #Configuration is processed. As you mention, SpringMongock requires the configuration class to be processed, as it requires the Spring ApplicationContext. However, you can run Mongock as standalone runner and use it(run it) wherever you want, as it doesn't depend on Spring context.
Mongock documentation
I hope it helps.

Logback separation by Spring Boot child() contexts

I am creating child() contexts dynamically in Spring Boot and I would like to log each context to a separated file. Is this possible?
The reason to do that is because I have a dynamic spring-integration configuration for different adapters. This is quite useful for working with different connections with the same adapter configuration but there is much information for just one log file.
I saw a Thread separation even a JNDI context separation but I do not know what is the best way to do this. Is this possible just configuring the logback.xml file?
Update:
Maybe the option is MDC and I am not understanding the concept. For instance, could you explain how to apply MDC for a Spring #MessageEndpoint element with multiple Spring Integration elements such as #Transformer, #ServiceActivator and #Router like the following one:
#MessageEndpoint
public class TestComponents {
private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);
#Router(inputChannel = "inputRouter")
public MessageChannel router(Message<String> demo) {
..
LOGGER.trace(“TEST”);
…
LOGGER.error(“TEST”);
…
}
#ServiceActivator(inputChannel="inputService")
public void service(Message< String > demo) {
..
LOGGER.trace(“TEST”);
..
}
#Transformer(inputChannel="inputTransformer", outputChannel="outputTransformer")
public byte[] transformerToByte(Message<String> demo) {
..
LOGGER.debug(“TEST”);
..
}
}
The example could be also applicable to a #Component with different methods.
I am worry about performance due to the paragraph described in the documentation:
Please note that MDC as implemented by logback-classic assumes that
values are placed into the MDC with moderate frequency
I don't think this can be done easily. I don't have a lot of experience with Logback, but I'm quite familiar with Log4J, Spring, Tomcat and classloading.
Logback, like log4J uses a static factory method to produce a singleton logger, this means that static state is stored in the class loader.
In spring you can specify which class load is used to load the context, but a class loader will only load a class/resource that can't be loaded by the parent class loader (you will discover this if you override URLClassLoader.getResource). This is a problem because when Spring Boot start, logging is initialised and loaded by the 'root' class loader.
The only way I can see you preventing this is to remove the logback jar from your classpath, and create a new URL class loader (containing only the logback jar and configuration) for loading the root Spring context and another class load for loading the child contexts (same jar different configuration). Since the logback jar is not part of the system classpath, you should be able to have two separate logback configuration, because static is scoped by class loaders.
EDIT
Diving a little deeper I noticed that it is not enough to have a class loader that loads logback-core and logback-classic jars, due to the way the LoggingSystem class is initialised (LogSystem line 126, version 1.4.1), the entire spring-boot jar (and potentially every thing else) needs to be loaded by the same class loader. Which means you will not be able to use the jar bundling typically used to run spring boot applications.
You can use MDC (Mapped Diagnostic Context) from logback in combination with SiftingAppender.
Below I'll explain how it should work:
MDC allows you to have a discriminator which can be used to separate log files based on its value. At this stage you need to do MDC.put('child-context-key', 'childContextId') before any top stack method from child context is executed, and MDC.remove('child-context-key') after execution.
After that you can configure ch.qos.logback.classic.sift.SiftingAppender which will use 'child-context-key' value as discriminator to separate your log files.
example:
<appender name="CHILD-CONTEXT-SIFT-APPENDER" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
<key>child-context-key</key>
<defaultValue>defaultChildContextId</defaultValue>
</discriminator>
<sift>
<appender name="CHILD-CONTEXT-SIFT-FILE-APPENDER"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/path/to/your/log/file/${child-context-key}.log
</file>
</sift>
</appender>
Also you can follow this example form logback which shows how to configure separate log files for web application modules based on JNDI discriminator.

Spring Boot Unit test pre-initialization before #Configuration

I have a SpringBootTest where I need to initialize some stuff before the Spring #Configuration classes are processed. My data sources are loaded from JNDI, so I need to initialize the JNDI context before it processes the #Configuration class that contains my data source configuration. How can I accomplish this? I tried by using the setUp method in my unit test, but that doesn't work.
I wound up doing something similar to what's posted here: http://en.newinstance.it/2009/03/27/mocking-jndi/
Yeah, it's a little unorthodox to "mock" JNDI, but I wanted a true unit test where if JNDI were available and the data sources were under JNDI, my code was able to pull the data sources out and use them appropriately.

Is it possible to use Spring without a configuration file?

In my unit tests I want to configure Spring in code (API, Annotations) so they will not depend on bean configuration files.
Can this be done?
For example:
Class Dependency {}
Class A
{
#AutoWired
Dependency d;
}
When testing A, I want to be able to create an instance of it with the Dependency member resolved, without having to use configuration files.
Thank you!
In short, yes, you can start a spring application context with any of the implementations of org.springframework.context.support.AbstractApplicationContext. Namely, if you don't want to load the definitions from an XML file, you can use the org.springframework.context.support.StaticApplicationContext or org.springframework.context.support.GenericApplicationContext to start the context.
With the context instantiated, you can start creating beans with the BeanFactory, either the oen default to the selected context or a custom one, that suits your needs.
In practice, it's lot more work than that. It's easier if you just use plain XML configuration, but it can be done.
You can use the Java configuration instead of the XML configuration.
You can use the AnnotationConfigApplicationContext to create application context programatically without bean configuration files.

Resources