Logging in Spring framework -flow and configuration - spring

When we run a sample main program which reads a applicationContext.xml with a single bean..
how does Spring do the logging..and how can one overwrite the default logging.
I didnt see any log4j.xml in the spring dependencies as well..
Regards

This is described in the documentation:
Logging is a very important dependency for Spring because a) it is the only mandatory external dependency, b) everyone likes to see some output from the tools they are using, and c) Spring integrates with lots of other tools all of which have also made a choice of logging dependency. One of the goals of an application developer is often to have unified logging configured in a central place for the whole application, including all external components. This is more difficult than it might have been since there are so many choices of logging framework.
The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We compile against JCL and we also make JCL Log objects visible for classes that extend the Spring Framework. It's important to users that all versions of Spring use the same logging library: migration is easy because backwards compatibility is preserved even with applications that extend Spring. The way we do this is to make one of the modules in Spring depend explicitly on commons-logging (the canonical implementation of JCL), and then make all the other modules depend on that at compile time. If you are using Maven for example, and wondering where you picked up the dependency on commons-logging, then it is from Spring and specifically from the central module called spring-core.
The nice thing about commons-logging is that you don't need anything else to make your application work. It has a runtime discovery algorithm that looks for other logging frameworks in well known places on the classpath and uses one that it thinks is appropriate (or you can tell it which one if you need to). If nothing else is available you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). You should find that your Spring application works and logs happily to the console out of the box in most situations, and that's important.
(emphasis mine)
Follow several sections describing how to use various logging frameworks.

Related

AspectJ dependency missing in spring boot 2.1.1

I was trying to create a new Spring Boot project using start.spring.io. Searching for dependencies, I found that there was no AspectJ starter available. Has this dependency removed/deprecated from Spring Boot starters? Here is a screen shot:
I, however, was able to find the dependency on maven repositories website:
It was removed indeed. #jwenting explained in a nutshell why. This starer is required if you want to create your own aspect or if you want to use some advanced AOP mode.
Most users don't need it and whenever a library requires it, its starter brings it automatically. Having a dedicated entry was confusing as we saw a very large amount of users picking this up for no good reason.
Also, please keep in mind that start.spring.io is not an exhaustive list of what you can do with Spring. We're focusing on the getting started experience only and avoiding cases that could lead to confusion. This one is a good example of the latter.
it's an implicit dependency, meaning you don't have to include it because it's automatically pulled in by anything that needs it.
You can still add it explicitly, but there's no need to (and afaik it's never been needed).

Switching bindings for SLF4J as a runtime scoped dependency in Maven

Think to Simple Logging Facade (SLF4J) for Java. As a background, it provides an API by means of a simple facade pattern in a way that the underlying logging backend is determined at runtime by adding the desired binding to the classpath. It may be the standard java.util.logging, log4j, logback or tinylog.
The neat separation of the client application from the logging backend reduces the coupling between the specific application and any particular logging framework. This can make it easier to integrate a newly implemented client with existing code of other projects that have already made a choice of logging backend.
So considering the logging API SLF4J, for compilation you need only the slf4j-api and you shall avoid including any specific binding like slf4j-log4j12 as a compile dependency.
As result, slf4j-log4j12 is a good candidate for being a runtime scoped dependency instead of a compile dependency, because this will allow you to switch among slf4j bindings at runtime without having to recompile the application.
Question: where to set the switching among logging frameworks bindings at runtime in a Maven project? Any example?
Disclaimer: I am the author of SLF4J
Even though the documentation talks about changing the logging back-end at runtime, SLF4J allows to switch logging back-ends at build time but not at runtime.

Is there any reason not to co-locate small spring-boot starters with autoconfigures?

spring-boot uses "starters" to define a set of libraries dependencies a project may include. This maven module, a starter for Jersey, for example:
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters/spring-boot-starter-jersey
spring-boot uses autoconfigures to instantiate and configure the classes in the starter module. The autoconfigure for Jersey:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java
Is there any reason not to co-locate new 3rd party/private starters in the same module as the autoconfigures, instead of split across separate modules like the example above?
It's a good question, and one that we have debated inconclusively in the Spring Boot engineering team, so there is no correct answer. Relevant points for discussion:
spring-boot-autoconfigure started out as quite a small library (pre 1.0). It has grown now to the extent that its pom is kind of ridiculously long (and nearly everything is optional).
Starters perform more than one function, in the sense that they can be used to activate bits of autoconfiguration, but also (and more importantly)
, they are an opinionated, curated set of dependencies that might (and usually does) go beyond the minimum needed to activate some autoconfiguration. This is basically Marten's point.
Spring Boot .NEXT (1.3 at the point) will more than likely unbundle spring-boot-autoconfigure into multiple modules (e.g. there might be one for jetty, or maybe one for servlet containers, or something esle).
When the unbundling happens we might see some starters becoming obsolete (who knows at this point), but I suspect they will still exist. Spring Cloud has a lot of unbundled autoconfiguration, but still has starters, for instance.
For small third party libraries I see no reason why starters and autoconfiguration shouldn't be co-located. I think the only justification for allowing this thread on stackoverflow is if it can be re-worded to make the question more obviously about that.

Should I exclude Spring Framework jars that are not required?

I am developing a simple web application, using Spring Framework.
When I add Spring framework to my class path, I see that it has lot of jars which I never use (for example: spring-aop-3.2.3.RELEASE.jar).
Is it a good idea to keep the entire framework intact or remove unused jars?
If you need to remove unused jars, the best way is to use some dependency management tool like Ivy or Maven, and let the tool decide what the required dependencies are. Otherwise it will not be apparent what is really unused or not until you break something.
For instance, if you are using declarative transactions, then removing the AOP jar will cause breakage, because AOP is used to implement that functionality.
If you would rather not use dependency management, it's better to leave everything intact.
There are some cases where you do want to remove/exclude jars. Replacing commons-logging with slf4j is one example. Another example is excluding the log4j dependencies that get dragged in on account of some appender that's packaged with log4j but that you know you will never use. Dependency management tools allow you to tell them what needs to be excluded.
Doing without dependency management management and removing things because you never use them directly is too dangerous.

dealing with spring dependencies

I have a bunch of top level packages that are owned by the same team. All top level packages use spring. Then there are some libraries (jars) that are shared functionality and utilities between the top level packages. All pretty standard stuff.
In some cases it makes sense to make use of spring in a library package. Let's say I have a series of Aspects that are shared and I want to use spring's #Aspect/#Before/#After etc. annotations.
The problem is that there are fairly large top-level packages that are written with spring 2.5.6 dependencies, and the newer top-level packages are being created in spring 3. I generally think this is a good thing.
But then there's this little problem that I now have libraries that depend on spring-2.5.6, and those can't be used by spring-3 top level packages because of the mis-matching versions (I'm making the assumption here that sucking in two different spring versions is a very bad idea). It seems that my options are to avoid spring dependencies in libraries, or to accept that my libraries will need to provide multiple versions (1 for each version of spring used at the top package level). Option 1 seems preferable to option 2, but I'm hoping there's some interesting trick that gives me the best of both worlds.
If there was java standards for some of these things (#Inject?) then I could depend on the javax stuff and not on the spring specific stuff. Unfortunately #Inject etc. is only supported for spring 3+ so that fixes my problem at some future point but as long as I have 2.5.6 apps it doesn't help.
Ideas?
I should note that there are some existing libraries that depend on spring-2.5.6 and I view that as a deterrent to upgrading the top level package to spring-3. Because upgrading the top level package means also version bumping N libraries that depend on spring, which is annoying, given that I'm not even aware of the complete set of consumers of these libraries and what they might think of the spring version suddenly being bumped.
EDIT:
I'm wondering if I can create some library, and make a spring dependency with scope of provided. The spring version would be the minimum version that I can pick to get the feature set I want, so ideally I'd use 2.5.6 to make it compatible with a spring 2.5.6 app and a spring-3.0.5 app. Then when a consuming app creates a dependency on my library, it will also create a spring dependency for the real spring version in effect for that application. I'm thinking this should work, so long as the spring version is >= the version I pick for my library (and I happen to know that 2.5.6 is the lowest version in use for all apps).
My other option is to not create a spring dependency at all but DO provide a spring.xml that can be imported in the calling app. This means I can't use annotations or stuff like InitializingBean, but generally spring has provided a way to do things via annotation, or xml, or both, so this should work as well.
Thoughts?
As you rightly mentioned, having both 2.5.6 and 3.0 Spring dependencies will create problems. Only one version will be picked up at runtime which means either your top level packaged modules will fail or the other shared utilities will fail (depending on the version of Spring).
A similar issue was discussed in Java Classloader - how to reference different versions of a jar. It is not directly related to Spring but I cannot think of a direct solution to your problem. OSGi is a possible solution but not sure how feasible it is in your environment since it requires change in the container itself.
a) #Aspect #Before #After: These annotations are all in aspectjrt.jar, not Spring itself. They should work with either version
b) #Inject won't work but #Autowired will.

Resources