Logback separation by Spring Boot child() contexts - spring

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.

Related

ApplicationContext in Spring Boot [duplicate]

This question already has answers here:
application context. What is this?
(4 answers)
What is Application context and bean factory in spring framework [duplicate]
(1 answer)
Closed 3 years ago.
I have a Spring Boot app and it's running with Spring Data, MySQL, Spring Security and MVC. The app is running for me just as fine.
However, I keep hearing about ApplicationContext a lot and I was wondering when do I need to use it and would like to know what it does. Can someone give me an example and an overview of ApplicationContext and its use?
ApplicationContext is a core interface that Spring framework built on. If you're building a Spring application, you're already using the ApplicationContext. You can have great insight about this from Spring Framework Reference Documentation. As per this document, Spring framework consists with these modules;
The Context (spring-context) module builds on the solid base provided
by the Core and Beans modules: it is a means to access objects in a
framework-style manner that is similar to a JNDI registry. The Context
module inherits its features from the Beans module and adds support
for internationalization (using, for example, resource bundles), event
propagation, resource loading, and the transparent creation of
contexts by, for example, a Servlet container. The Context module also
supports Java EE features such as EJB, JMX, and basic remoting. The
ApplicationContext interface is the focal point of the Context module.
spring-context-support provides support for integrating common
third-party libraries into a Spring application context, in particular
for caching (EhCache, JCache) and scheduling (CommonJ, Quartz).
Spring ApplicationContext also inherits BeanFactory super-interface. So technically ApplicationContext is capable of doing all the things, BeanFactory interface is capable and much more. BeanFactory interface along with ApplicationContext provide the backbone of the Spring IoC container (Core container). Which is Bean management for your application.
The interface org.springframework.context.ApplicationContext
represents the Spring IoC container and is responsible for
instantiating, configuring, and assembling the aforementioned beans.
The container gets its instructions on what objects to instantiate,
configure, and assemble by reading configuration metadata. The
configuration metadata is represented in XML, Java annotations, or
Java code. It allows you to express the objects that compose your
application and the rich interdependencies between such objects.
ApplicationContext uses eager loading mechanism. So, every bean declared in your application, initialize right away after the application started and after, this ApplicationContext scope is pretty much read-only.
Initiate a Spring IoC container with custom bean definitions is pretty much staright forward.
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"daos.xml"});
Following file shows this daos.xml file content;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for data access objects go here -->
</beans>
After that you can access the beans define in the .xml like this;
JpaItemDao obj = (JpaItemDao) factory.getBean("itemDao");
These instances are now being initialized and managed by the ApplicationContext. But most users prefer to use #Bean annotation define beans to do the binding and #Autowired annotation to do the dependency injection. So, no need to manually feed a bean .xml to custom initialized ApplicationContext.
#Configuration
class SampleConfig {
#Bean
public JpaItemDao getJpaItemDao() {
return new JpaItemDao();
}
}
and inject in;
#Component
class SampleComponent {
#Autowired
private JpaItemDao itemDao;
public void doSomething() {
itemDao.save(); // Just an example.
}
}
Besided the bean management, ApplicationContext does some other important thing in the Spring core container. As per ApplicationContect javadoc, they are;
Bean factory methods for accessing application components. Inherited from ListableBeanFactory.
The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface.
The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface.
The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface.
Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a
single parent context can be used by an entire web application, while
each servlet has its own child context that is independent of that of
any other servlet.
Also, checkout the sub-interfaces of ApplicationContext that specifically designed for work on different use cases like WebApplicationContext.
ApplicationContext is a core concept (arguably the most important one) of spring used also in spring boot of course but and ideally hidden from the programmers in both cases, meaning that the programmer should not directly interact with it in a business code of the application.
Technically its an interface that has many implementations, the relevant one is picked depending on in which environment you're running and how do you configure the application.
So does it do? Its a class that basically is a registry of all the beans that spring has loaded. In general, starting up the spring mean finding the beans to load and putting them in the application context (this is relevant for singletons only, prototype-scopes beans are not stored in the ApplicationContext).
Why does spring need it?
For many reasons, to name a few:
To manage lifecyle of the beans (when the application shuts down, all beans that have a destroy method should be called)
To execute a proper injection. When some class A depends on class B spring should inject class B into class A. So by the time of creating the class A, class B should already be created, right? So spring goes like this:
Creates B
Puts B into application context (registry)
Creates A
For injection goals: gets B from the application context and injects into A
// an illustration for the second bullet
class B {}
class A {
#Autowired
B b;
}
Now there are other things implemented technically in application context:
Events
Resource Loading
Inheritance of application contexts (advanced stuff, actually)
However now you have an overview of what it is.
Spring boot application encapsulates the application context but you can still access it from many places:
in the main method when the application starts it returns an application context]
you can inject it into configuration if you really need
its also possible to inject the application context into the business bean, although we shouldn't really do so.
In simple words:
Spring is popular for dependency Injection.
So all the bean definitions(Objects) will be created by the spring and maintained in the container. So all the bean life cycle will be taken care by spring container.
So ApplicationContext is a interface It has different implementations will be there to initialize the spring container.
So ApplicationContext is the reference to Spring Container.
Some popular implementations are:
AnnotationConfigWebApplicationContext,
ClassPathXmlApplicationContext,
FileSystemXmlApplicationContext,
XmlWebApplicationContext.
Reference: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html

Delay spring xml imports

I have an application where I have to read all application properties from properties files. Then override them from a external cache framework. Then initialize spring beans.
I am using Java Config of spring to read properties and override them. And using #import to load xml files. But xml files import as soon as context starts loading, resulting all the xml beans being initialized.
So is there a way I can delay xml files import until I load all the properties first?
You can use the following code.
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
or individually add lazy-init on beans which you don't want to load.
Or
There are lot of ways you can achieve your requirement One of which can be use of depends-on or #DependsOn if you are looking for annotation based configuration,
You can read property file after that you can create a cache bean and use
depends-on to let the container know you bean is depending on some other bean you can initialise a cache bean and use the same as you see fit.
See this example for better clearity.
<bean id="primaryBean" depends-on="cacheBean"></bean>
Now IoC guarantees that depending bean will be created before the bean which depends on this bean, So you will have an instance of this bean, and can use it.
Other than this you can implement LifeCycle interface
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
For more references you can refer spring docs.

Spring: confusion over the right learning path

The past few days I've been teaching myself Spring Boot and created a REST web service server and client, then added basic authentication and deployed as a standalone and a war package. I did this through incorporating spring-boot-starter-web, spring-boot-starter-test, spring-boot-starter, spring-boot-starter-security, spring-boot-starter-tomcat, spring-web, jackson-databind in my gradle project and copying hten modifying via various websites.
After getting confused by the multitude of websites doing things in completely different ways (completely different annotations, some use of configuration files) it worked and I then modified it using an interceptor/message converter, raw headers and then through a rest template builder.
However, I feel like I really have no idea how or why it worked, even though I wrote a fair bit of code to get it all working, including Basic authentication, in 4 different ways. It just magically worked, and I don't like it: for example, if I wanted to add more stuff that wasn't 'boot' based, how would I do it, or what are all the annotations doing and why are they required, e.g. #SpringBootApplication, #Configuration, or why are some classes #Bean and others not).
To cut a long story short, spring is a massive framework (the website listing the packages takes over a page by itself), should I really be learning spring core/framework before anything else, then maybe spring MVC or spring web services before learning boot?
I can find many resources on teaching me the various packages, but none that tells me why they work or where to really start and specifically nothing will tell me how the packages interlink. It's quite overwhelming.
I expect this will get closed down as not constructive, but it seemed to be the best place to get an answer on Spring.
A very short history of Spring
Lets start with a little history lesson... The year is 2002 and most Java developers have been laboring in the J2EE space and a lot of them were not happy. One of them was Rod Johnson who wrote a book called Expert One-on-One J2EE Design and Development and it was how one could develop enterprise application without EJBs and in a better fashion. The code for this book became the foundation of the Spring Framework.
Spring Configuration
Lets take a look at a simple Java class.
#Component("hello")
public class HelloWorld {
private String name = "World!";
public void setName(String name) {
this.name=name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}
Spring Configuration - Property Files
In the beginning the only configuration option was to use a properties file. Lets name this file application-context.properties. To create an instance of the java class above and set a name, the following content in the application-context.properties was needed.
hello.(class)=biz.deinum.samples.configurations.HelloWorld
hello.name=Marten!
The (class) was a special property (there are more like (scope) and (abstract) see the javadoc for more options. This would indicate which class was needed to be loaded. To use the properties file one would have to create a PropertiesBeanDefinitionReader pass that a BeanFactory. (Which in turn can be passed to an ApplicationContext if you need fancy features like AOP)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:application-context.properties");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();
However that property based configuration was a bit limiting and XML was concurring the world. Hence the first steps into XML configuration where born.
Spring Configuration - XML Files (part 1)
To represent the same configuration with XML the following would be needed.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="biz.deinum.samples.configurations.HelloWorld">
<property name="name" value="Marten!" />
</bean>
</beans>
When loaded this would create an instance of HelloWorld with the same settings as the property file. Loading it would require an XmlBeanDefinitionReader.
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:/applicationContext-basic.xml");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();
Spring Configuration - XML Files (part 2)
XML is quite verbose but readable. But configuring things like AOP (Transactions for instance),MVC etc. are quite labor some. (Or things like security see this for the predecessor of Spring Security without a namespace). So the new and improved XML had the notion of namespaces allowing things like <tx:annotation-driven /> <aop:config /> etc.
Spring Configuration - Annotation Driven
The next step was the introduction of Java5, which allowed annotations. As the whole Java community asked for annotation based configuration this was added. Hence the introduction of #Component, #Autowired and the likes.
Adding #Component to the HelloWorld class and use the namespace to enable component scanning reduces the amount of XML one has to write.
Assuming #Component("hello") is on the HelloWorld class the following XML is needed.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="biz.deinum.samples.configurations" />
</beans>
To load this configuration the just change the location of the file to load.
Spring Configuration - Java Config
Then all of a sudden the love for XML was over and people wanted to use a language they know and that language is Java. Hence the birth of Java Based configuration.
#Configuration
public class HelloWorldConfiguration {
#Bean
public HelloWorld hello() {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Marten!");
return helloWorld;
}
}
The #Bean annotation is an indication that this method produces a bean and is processed using ASM before being actually loaded by Spring. However Java Config processing is quite complex and works only with an ApplicationContext. You can either add the #Configuration class to an xml file and load that to have it processed or use a specialized AnnotationConfigApplicationContext to load (or detect) it.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
context.getBean("hello", HelloWorld.class).sayHello();
In XML we have namespaces for making configuration easier. In Java Config land we have the various #Enable* annotations like #EnableTransactionManagement which is the same as <tx:annotation-driven /> in XML.
Thoughts / Suggestions
Which configuration option to use, if you are new I suggest start with Java based configuration, although XML is probably a bit easier to understand (IMHO). All configuration options still work today, you can even mix and match them if need arises.
For Spring it doesn't matter, what matters for Spring are the BeanDefinitions which source is used to construct them (properties, xml or java configuration) doesn't matter.
Spring Boot
Thus far the only thing covered is Spring itself. No other project has been touched (although have been mentioned). But as you can imagine time goes on and as configurations and application complexity grew we wanted more convention over configuration. One of the reasons Spring Boot has seen the light.
Marking a class with #SpringBootApplication makes that class a #Configuration, will enable component-scanning (starting from the same package the annotated class is in) and will enable auto configuration.
#SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(HelloApplication.class, args);
BeanFactoryHelper.sayHello(context);
BeanFactoryHelper.statistics(context);
}
#Bean
public HelloWorld hello() {
HelloWorld hello = new HelloWorld();
hello.setName("Marten!");
return hello;
}
}
This class will launch the application, say hello, print some info on the context and end. Without you creating an application context or factory yourself.
Why the #Bean method well the HelloWorld class is in a package not covered by the default component scanning of Spring Boot and hence we need to declare the bean. We can do this in the HelloApplication class because that is also an #Configuration (due to that being a meta annotation on #SpringBootApplication).
Now if you replace #SpringBootApplication with #SpringBootApplication(scanBasePackageClasses = HelloWorld.class) you could remove the #Bean annotation as the HelloWorld would now be detected by component scanning (enabled by the #ComponentScan meta annotation on #SpringBootApplication).
The code for this answer can be found here.
Spring framework it's about dependency injection and it's used for REST web services, but that doesn't mean you can't have Spring in any basic application.
To cut a long story short, spring is a massive framework (the website listing the packages takes over a page by itself), should I really be learning spring core/framework before anything else, then maybe spring MVC or spring web services before learning boot?
You should learn how spring works in general and how does instantiations work. Basically it does a search in your project and instantiate every class annotated with #Component (#Service, #RestController, #Controller ... and so on). When you #Autowire, a reference is passed to your variable.
After getting confused by the multitude of websites doing things in completely different ways (completely different annotations, some use of configuration files) it worked and I then modified it using an interceptor/message converter, raw headers and then through a rest template builder.
Most of the examples that you can find on the internet older than 1-2 years are probably outdated(but not always). When you search for something keep this in mind. This is the main cause why there are so many implementations.
I can find many resources on teaching me the various packages, but none that tells me why they work or where to really start and specifically nothing will tell me how the packages interlink. It's quite overwhelming.
It is overwhelming. It is a big framework with a large domain of applicability. Best place to learn how things work is: https://spring.io/docs/reference

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.

A bunch of questions on Spring 3 framework

Here are the questions resulted from reading the Spring Reference, please help.
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
(2) We have the following config instructions:
<context:annotation-config/>
<context:component-scan base-package=".."/>
<mvc:annotation-driven/>
Do these instructions duplicate theirselfs? In which cases yes, in which no?
(3) I am a bit stuck with all that ways Spring introduces to convert from string to object: PropertyEditor, Conversions, Formatting..
Here is a simple use case:
I have a Spring MVC controller that processes some POST request. That request is a result of filling some form. The form is a web representation of some entity.
So, given a the user submits a new Project form. In that form exist a date field and a manager's name field to be selected from the list of existing managers. The entered date should be converted to Date property of Project object, and manager's name - to Manager property, created or located by this name (i.e. I want to inject Manager into his Project). What should I use in this case? Property editors, formatters, something else?
(4) Generally, may I say that all the #interface classes that are found on classpath can be used by Spring as annotations?
In other words, how can I know which annotations can be used in my project? All that can be found in my classpath, or I need to register them somehow?
(5) I tried to use spring aop without aspectj.jar: just created an Aspect and addred XML definition for this aspect (without any annotations). As a result it throws "class not found Exception: org/aspectj/weaver/BCException".
So looks like I cannot use Spring AOP without aspectJ library?
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
Spring is typically usd in two environments - in web development and in desktop applications/standalone servers. In the former case the ApplicationContext is created automatically via ContextLoaderListener defined in web.xml or WebContextInitializer in Servlet 3.0 container.
In the latter case (standalone application) you are responsible for creating and destroying the application context.
(2) We have the following config instructions:
<context:component-scan base-package=".."/> provides all the functionality of <context:annotation-config/> plus (surprise!) component scanning. <mvc:annotation-driven/> is completely independent and it recognizes spring-mvc annotations like #Controller.
[...]The entered date should be converted to Date property of Project object[...]
Register custom editor within #Controller:
#Controller
public class FooController {
#InitBinder
public void binder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
public void setAsText(String value) {
try {
setValue(new SimpleDateFormat("yy-MM-dd HH:mm:ss").parse(value));
} catch (ParseException e) {
setValue(null);
}
}
});
}
}
[...]how can I know which annotations can be used in my project?[...]
I found this awesome annotations support sheet some time ago (I am not an author). It will tell you which annotations are enabled when.
All that can be found in my classpath
#Inject is enabled if it is found on the CLASSPATH, other annotations need to be enabled manually, see above.
So looks like I cannot use Spring AOP without aspectJ library?
You can use Spring without CGLIB if you only use interface proxies (i.e. you only apply aspects on classes implementing at least one interface). Otherwise you need CGLIB to dynamically create subclasses.

Resources