Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    log4j dependency issue on server side

    Is there any particular reason that a dependency on log4j is hardcoded in the server side isomorphic code?

    For a number of reasons we wish to use slf4j however removing the log4j jar results in the following

    Code:
    Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/spi/RootCategory
    	at com.isomorphic.datasource.DSRequest.<clinit>(DSRequest.java:108) ~[isomorphic_core_rpc.jar:na]
    Obviously this class is not included in the log4j over slf4j binding (at least as of version 1.6.1)

    Any suggestions?

    SmartGWT Pro 2.3

    TIA

    Andreas

    #2
    hmmm, never mind... problem partially caused by my confusion about differences between log4j.jar & slf4j-log4.jar

    Have worked around the issue by judicious ordering of jars on classpath.

    Andreas

    Comment


      #3
      Hmmm, could you explain how you got around it? I'm seeing the exact same issue.

      I have log4j-over-slf4j, slf4j-simple on the classpath and get that error.

      Comment


        #4
        I've looked a little bit more, and it seems that the log4j-over-slf4j bridge is missing a couple of classes, like rootcategory, loggerrepository, etc.

        There's a bug on slf4j's bugzilla here: http://bugzilla.slf4j.org/show_bug.cgi?id=161, where they're basically saying that they won't fix it, since the spi package is kinda unusual and contains 20+ classes.

        Any pointers here? I'd really like to get rid of log4j and redirect all to logback...

        cheers

        Comment


          #5
          No response here? would be great to hear your thoughts on this issue.

          Comment


            #6
            We really need to use SLF4j, and the dependencies on log4j.spi code is really a problem.

            We are using smartgwt 2.3 for compatiblity with GWT 2.1.1 and the gwt designer.

            The issue comes up since we are using "logback" as the underlying logger, not log4j. This means most of the log4j classes are not present,including LoggerRepository, Appender, etc.

            It would seem better if there was a separate "isomorphic-logging" jar that could be replaced based on the underlying logger: log4j, logback or others.
            Last edited by sknutson; 6 Mar 2011, 16:06.

            Comment


              #7
              Why don't you just use logback and log4j in tandem?

              Comment


                #8
                Because it's confusing to have multiple configuration files in different places.
                Because you'll end up with more logfiles than you'd want since you need to have multiple loggers configured.
                Because i perhaps want to use logback-specific functionality for all my logging.

                Comment


                  #9
                  Using SmartWGT Power v2.5 on RHEL 6.1.

                  We are required to use Logback, and I haven't been successful in getting it to work with my module. No matter where I put logback.xml (under /war/ or under /war/WEB-INF/) it does not appear to get 'used'. What are these dependencies mentioned earlier in this thread and please tell me if there is no possibility of getting SmartGWT to work with Logback, because I'll need to escalate that issue ASAP, it could have a lot of impact on us.

                  Thanks-
                  Susan

                  Comment


                    #10
                    Susan what's your specific need: redirecting all Isomorphic logging to logback, or just being able to use logback for your own logging?

                    There's no problem with the latter. For the former, you would need to think about where the logs are ultimately intended to go - log4j and logback can be working in tandem and potentially log to the same location (eg a database, or syslog).

                    Comment


                      #11
                      We only need to use logback for our own logging. Sounds like I can add logback.xml in there along with /src/log4j.isc.config.xml, and put the logback jars in place, and it should work alright.

                      Comment


                        #12
                        Originally posted by mathias View Post
                        Because it's confusing to have multiple configuration files in different places.
                        Because you'll end up with more logfiles than you'd want since you need to have multiple loggers configured.
                        Because i perhaps want to use logback-specific functionality for all my logging.
                        +1

                        I worked around #2 & 3 by creating a Slf4jAppender for Log4j, which I'll include below. It was inspired by the log4j-over-slf4j bridge's org.apache.log4j.Category implementation.

                        The approach isn't ideal. Other frameworks that could use the log4j-over-slf4j bridge have to be configured to use Log4j with this appender instead, or if they support it an alternative API that can be bridged to SLF4J.

                        I really wish SmartClient would just use SLF4J, or a compatible facade or logger implementation. Even Log4j without the SPI usage would do the trick. We have 110 jars in our web app representing over two dozen frameworks/APIs. SmartClient is the only one that was a pain to get logging the way we wanted.

                        Does the Log4j SPI usage enable any features for end-users of SmartClient?

                        Ian

                        log4j.isc.config.xml:

                        Code:
                        <?xml version="1.0" encoding="UTF-8" ?>
                        <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
                        <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
                        
                        	<appender name="slf4j" class="com.mycompany.common.util.log4j.Slf4jAppender" />
                        
                        	<root>
                        		<level value="info" />
                        		<appender-ref ref="slf4j" />
                        	</root>
                        
                        </log4j:configuration>
                        Slf4jAppender.java:

                        Code:
                        package com.mycompany.common.util.log4j;
                        
                        import org.apache.log4j.AppenderSkeleton;
                        import org.apache.log4j.Level;
                        import org.apache.log4j.spi.LoggingEvent;
                        import org.apache.log4j.spi.ThrowableInformation;
                        import org.slf4j.Logger;
                        import org.slf4j.LoggerFactory;
                        import org.slf4j.Marker;
                        import org.slf4j.MarkerFactory;
                        import org.slf4j.spi.LocationAwareLogger;
                        
                        public class Slf4jAppender extends AppenderSkeleton {
                        
                        	private static final Marker FATAL_MARKER = MarkerFactory.getMarker("FATAL");
                        
                        	private final String fqcn = getClass().getName();
                        
                        	@Override
                        	protected void append(final LoggingEvent log4jEvent) {
                        
                        		final Logger slf4jLogger = getSlf4jLogger(log4jEvent);
                        
                        		final int slf4jLevel = getSlf4jLevel(log4jEvent);
                        
                        		final Marker slf4jMarker = getSlf4jMarker(log4jEvent);
                        
                        		final String message = getMessage(log4jEvent);
                        
                        		if (slf4jLogger instanceof LocationAwareLogger) {
                        
                        			final Throwable throwable = getThrowable(log4jEvent);
                        
                        			locationAwareLog(slf4jLogger, slf4jLevel, slf4jMarker, message, throwable);
                        
                        		} else {
                        
                        			log(slf4jLogger, slf4jLevel, slf4jMarker, message);
                        		}
                        	}
                        
                        	@Override
                        	public void close() {
                        
                        		// NoOp.
                        	}
                        
                        	@Override
                        	public boolean requiresLayout() {
                        
                        		return false;
                        	}
                        
                        	private Logger getSlf4jLogger(final LoggingEvent log4jEvent) {
                        
                        		final String loggerName = log4jEvent.getLoggerName();
                        
                        		return LoggerFactory.getLogger(loggerName);
                        	}
                        
                        	private int getSlf4jLevel(final LoggingEvent log4jEvent) {
                        
                        		final Level log4jLevel = log4jEvent.getLevel();
                        
                        		switch (log4jLevel.toInt()) {
                        		case Level.TRACE_INT:
                        			return LocationAwareLogger.TRACE_INT;
                        		case Level.DEBUG_INT:
                        			return LocationAwareLogger.DEBUG_INT;
                        		case Level.INFO_INT:
                        			return LocationAwareLogger.INFO_INT;
                        		case Level.WARN_INT:
                        			return LocationAwareLogger.WARN_INT;
                        		case Level.ERROR_INT:
                        			return LocationAwareLogger.ERROR_INT;
                        		case Level.FATAL_INT:
                        			return LocationAwareLogger.ERROR_INT;
                        		default:
                        			throw new IllegalStateException("Unknown Log4J level " + log4jLevel);
                        		}
                        	}
                        
                        	private Marker getSlf4jMarker(final LoggingEvent log4jEvent) {
                        
                        		final Level log4jLevel = log4jEvent.getLevel();
                        
                        		return (Level.FATAL.equals(log4jLevel)) ? FATAL_MARKER : null;
                        	}
                        
                        	private String getMessage(final LoggingEvent log4jEvent) {
                        
                        		final Object messageObject = log4jEvent.getMessage();
                        
                        		return (messageObject == null) ? null : messageObject.toString();
                        	}
                        
                        	private Throwable getThrowable(final LoggingEvent log4jEvent) {
                        
                        		final ThrowableInformation log4jThrowableInformation = log4jEvent.getThrowableInformation();
                        
                        		final Throwable throwable =
                        				(log4jThrowableInformation != null) ? log4jThrowableInformation.getThrowable() : null;
                        		return throwable;
                        	}
                        
                        	private void locationAwareLog(final Logger slf4jLogger, final int slf4jLevel, final Marker slf4jMarker,
                        			final String message, final Throwable throwable) {
                        
                        		final LocationAwareLogger locationAwareLogger = (LocationAwareLogger) slf4jLogger;
                        
                        		locationAwareLogger.log(slf4jMarker, fqcn, slf4jLevel, message, null, throwable);
                        	}
                        
                        	private void log(final Logger slf4jLogger, final int slf4jLevel, final Marker slf4jMarker, final String message) {
                        
                        		switch (slf4jLevel) {
                        		case LocationAwareLogger.TRACE_INT:
                        			slf4jLogger.trace(slf4jMarker, message);
                        			break;
                        		case LocationAwareLogger.DEBUG_INT:
                        			slf4jLogger.debug(slf4jMarker, message);
                        			break;
                        		case LocationAwareLogger.INFO_INT:
                        			slf4jLogger.info(slf4jMarker, message);
                        			break;
                        		case LocationAwareLogger.WARN_INT:
                        			slf4jLogger.warn(slf4jMarker, message);
                        			break;
                        		case LocationAwareLogger.ERROR_INT:
                        			slf4jLogger.error(slf4jMarker, message);
                        			break;
                        		default:
                        			throw new IllegalStateException("Unknown SLF4J level " + slf4jLevel);
                        		}
                        	}
                        }

                        Comment


                          #13
                          I am disappointed that it's been 2 years and this hasn't been addressed at all.

                          Using Log4j directly is all but deprecated, the best practice since some time now is to use Slf4j, and its a simple fix.

                          Comment


                            #14
                            Hi Team, Can we use logback in our application?> please suggest

                            Comment


                              #15
                              This is a very old thread. See the Server Logging topic in the docs - you can use logback or other frameworks since we now have slf4j.

                              As with your other questions, please try to make better use of the documentation.

                              Comment

                              Working...
                              X