Spring Framework
  1. Spring Framework
  2. SPR-5327

Consider migrating from Commons-Logging to SLF4j

    Details

    • Type: Refactoring Refactoring
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 3.0 M4
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      Currently Spring Framework depends on Commons-Logging. All of us know that for long time Commons-Logging has very bad reputation and is the source of many problems, bug, memory leaks etc.
      The SLF4j is the newer implementation of similar idea, and many people claim it works much better than Commons-Logging. It contain even some adapter for Commons-Logging users, allowing for gradual transition. Perhaps with Spring 3, along with migration to Java 5, is the best time to migrate also to SLF4J and remove dependency on Commons-Logging?
      In fact, you can probably do it somehow automatically, writing the script that will replace in all java files the imports and logger types.

        Issue Links

          Activity

          Hide
          Dave Syer added a comment -

          Sorry Neale, but I don't think it's going to happen - we don't want WAS users to be the only group for whom Spring works out of the box. You should only need an exclusion for spring-core, as that's the only POM that should depend on commons-logging. If that's not the case you can raise a separate JIRA ticket.

          Show
          Dave Syer added a comment - Sorry Neale, but I don't think it's going to happen - we don't want WAS users to be the only group for whom Spring works out of the box. You should only need an exclusion for spring-core, as that's the only POM that should depend on commons-logging. If that's not the case you can raise a separate JIRA ticket.
          Hide
          Neale Upstone added a comment -

          Ah. Had that lightbulb moment (ding!), which I'll share for all, and.. I suggest should be the standard approach for Spring examples and for Spring Roo.

          The wrong way of fighting to exclude SLF4J is as demonstrated in https://src.springframework.org/svn/spring-samples/mvc-ajax/trunk, which is to include a maven artifact, and exclude it. You can end up with something like this, which works. It makes sense that any single dependency recording an exclusion should exclude for all.

          pom.xml
            <dependencies>
              <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>3.0.5.RELEASE</version>
                <scope>compile</scope>
                <exclusions>
                 <exclusion>
                     <artifactId>commons-logging</artifactId>
                     <groupId>commons-logging</groupId>
                 </exclusion>
                </exclusions>
              </dependency>
              <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-oxm</artifactId>
                <version>3.0.5.RELEASE</version>
                <scope>compile</scope>
              </dependency>
            </dependencies>
          

          This is unclear, and for anyone who doesn't know the detailed black box magic of Maven's internals, they may duplicate these (just create a vanilla project under Spring Roo 1.1.2 and you'll see this demonstrated).

          The clear way of expressing what Dave has clarified above (that it only needs excluding on spring-core), is to use dependencyManagement:

          pom.xml
            <dependencyManagement>
              <dependencies>
                  <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>3.0.5.RELEASE</version>
                    <exclusions>
                     <exclusion>
                         <artifactId>commons-logging</artifactId>
                         <groupId>commons-logging</groupId>
                     </exclusion>
                    </exclusions>
                  </dependency>
              </dependencies>
            </dependencyManagement>
          
            <dependencies>
              <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>3.0.5.RELEASE</version>
              </dependency>
              <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-oxm</artifactId>
                <version>3.0.5.RELEASE</version>
              </dependency>
            </dependencies>
          

          Simpler still, for a multi-module project, the dependencyManagemnt entry would go in a parent POM.

          Show
          Neale Upstone added a comment - Ah. Had that lightbulb moment (ding!), which I'll share for all, and.. I suggest should be the standard approach for Spring examples and for Spring Roo. The wrong way of fighting to exclude SLF4J is as demonstrated in https://src.springframework.org/svn/spring-samples/mvc-ajax/trunk , which is to include a maven artifact, and exclude it. You can end up with something like this, which works. It makes sense that any single dependency recording an exclusion should exclude for all. pom.xml <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.0.5.RELEASE</version> <scope>compile</scope> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>3.0.5.RELEASE</version> <scope>compile</scope> </dependency> </dependencies> This is unclear, and for anyone who doesn't know the detailed black box magic of Maven's internals, they may duplicate these (just create a vanilla project under Spring Roo 1.1.2 and you'll see this demonstrated). The clear way of expressing what Dave has clarified above (that it only needs excluding on spring-core), is to use dependencyManagement: pom.xml <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.0.5.RELEASE</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>3.0.5.RELEASE</version> </dependency> </dependencies> Simpler still, for a multi-module project, the dependencyManagemnt entry would go in a parent POM.
          Hide
          Juergen Hoeller added a comment -

          FYI, and FWIW, Hibernate 4.0 migrates away from SLF4J and uses their own JBoss Logging now. So it doesn't look like common Java open source projects actually agree on SLF4J on the way forward.

          Juergen

          Show
          Juergen Hoeller added a comment - FYI, and FWIW, Hibernate 4.0 migrates away from SLF4J and uses their own JBoss Logging now. So it doesn't look like common Java open source projects actually agree on SLF4J on the way forward. Juergen
          Hide
          Aaron Digulla added a comment -

          That isn't entirely correct. Someone seems to love the JUL API so much that they wrapped it in Java 5 (varargs support) and wrote a couple of plugins to translate it to various logging frameworks (JUL, log4j and slf4j are supported even though slf4j isn't mentioned in the docs). It's in 4.0 release the POM as a test dependency, though.

          The code looks fast enough but I'm not sure how much value you get from adding another log-layer on top of the existing ones.

          Since I can't find any pointers why they did it, my guess is currently that the JBoss logging layer allows to i18n the log messages. Great if you need it but I'm wary of the performance impact.

          That said, I'd still vote to replace JCL with slf4j for these reasons:

          • slf4j gives consumers options
          • JCL's automatic logging framework recognition is flawed/broken/insufficient, depending on your point of view.
          • JCL is dead, slf4j is still supported by it's developer
          • Re backward compatibility: You're leaking a dependency. Eventually, you will have to fix that anyway. Why not replace something broken with something good? Yes, developers will complain but frameworks like logback have so many useful features and their config is so much more simple and more powerful that I regret every day that I didn't upgrade from log4j.

          For example: I've written an appender with logback that logs nothing until an error happens. At that time, it will log the last 20 INFO messages and the last 200 DEBUG messages. The whole code is about 250 lines. I get a log file which only contains interesting information plus a fast logger.

          To drive this home: I'm patching my third-party dependencies to use slf4j if they depend on JUL. The last bigger project on my list was BIRT (patched 400+ files). ZK is probably next.

          Spring uses JCL, which is not a very big problem because I can use the slf4j bridge which causes only a small performance loss but I always prefer frameworks that don't tie my to a certain logging implementation at runtime. The problem with JUL is that the translation is very, very expensive.

          Show
          Aaron Digulla added a comment - That isn't entirely correct. Someone seems to love the JUL API so much that they wrapped it in Java 5 (varargs support) and wrote a couple of plugins to translate it to various logging frameworks (JUL, log4j and slf4j are supported even though slf4j isn't mentioned in the docs ). It's in 4.0 release the POM as a test dependency, though. The code looks fast enough but I'm not sure how much value you get from adding another log-layer on top of the existing ones. Since I can't find any pointers why they did it, my guess is currently that the JBoss logging layer allows to i18n the log messages. Great if you need it but I'm wary of the performance impact. That said, I'd still vote to replace JCL with slf4j for these reasons: slf4j gives consumers options JCL's automatic logging framework recognition is flawed/broken/insufficient, depending on your point of view. JCL is dead, slf4j is still supported by it's developer Re backward compatibility: You're leaking a dependency. Eventually, you will have to fix that anyway. Why not replace something broken with something good? Yes, developers will complain but frameworks like logback have so many useful features and their config is so much more simple and more powerful that I regret every day that I didn't upgrade from log4j. For example: I've written an appender with logback that logs nothing until an error happens. At that time, it will log the last 20 INFO messages and the last 200 DEBUG messages. The whole code is about 250 lines. I get a log file which only contains interesting information plus a fast logger. To drive this home: I'm patching my third-party dependencies to use slf4j if they depend on JUL. The last bigger project on my list was BIRT (patched 400+ files). ZK is probably next. Spring uses JCL, which is not a very big problem because I can use the slf4j bridge which causes only a small performance loss but I always prefer frameworks that don't tie my to a certain logging implementation at runtime. The problem with JUL is that the translation is very, very expensive .
          Hide
          Adriano Machado added a comment -

          @Aaron Digulla: can you share that logback appender?

          Show
          Adriano Machado added a comment - @Aaron Digulla: can you share that logback appender?

            People

            • Assignee:
              Dave Syer
              Reporter:
              Grzegorz Borkowski
              Last updater:
              Adriano Machado
            • Votes:
              20 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                1 year, 19 weeks, 3 days ago