title: SLF4j with Log4j2 ERROR Unable to invoke factory method in class class ...RollingFileAppender for element RollingFile
body: <p>I have some WebDriver tests running in parallel in TestNG. And I want to be able to have logging log to a separate file for each test that's run in a directory structure like this:</p>
  
  <pre><code>target\logs\TestNGSuiteName(SuiteStartTime)
      Test1ClassName.TestMethod1 (TestStartTime).log
      Test1ClassName.TestMethod2 (TestStartTime).log
  </code></pre>
  
  <p>etc.  </p>
  
  <p>Using Log4j and SLF4j is it possible to create a separate log file for each individual TestNG tests?</p>
  
  <p>I have attempted using a RollingFileAppender but it doesn't look like that is designed for having separate instances run for separate log files like I'm attempting to do here.</p>
  
  <p>And I'm getting the errors</p>
  
  <pre><code>ERROR Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile.
  Unable to create Appender of type RollingFile.
  </code></pre>
  
  <p>Log4j2.xml
   </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Configuration&gt;
          &lt;Routing name="Routing"&gt;
              &lt;Routes pattern="$${ctx:ROUTINGKEY}"&gt;
                  &lt;Route&gt;
                      &lt;RollingFile name="Rolling-${ctx:ROUTINGKEY}"
                                   fileName="target/logs/${ctx:suiteTimestamp}/${ctx:testName} (${ctx:testStartTime}).log"
                                   filePattern="target/logs/${ctx:testname} ${ctx:testStartTime}_%i.log.gz"&gt;
                          &lt;PatternLayout&gt;
                              &lt;pattern&gt;%d{HH:mm:ss.SSS} [%t] %p %c{3} - %m%n&lt;/pattern&gt;
                          &lt;/PatternLayout&gt;
                          &lt;Policies&gt; &lt;!-- 6 hour rollover--&gt;
                              &lt;TimeBasedTriggeringPolicy interval="6" modulate="true"/&gt;
                              &lt;SizeBasedTriggeringPolicy size="10 MB"/&gt;
                          &lt;/Policies&gt;
                      &lt;/RollingFile&gt;
                  &lt;/Route&gt;
              &lt;/Routes&gt;
          &lt;/Routing&gt;
      &lt;/Appenders&gt;
      &lt;Loggers&gt;
          &lt;Logger name="james.log" level="debug" additivity="false"&gt;
              &lt;AppenderRef ref="Routing"/&gt;
          &lt;/Logger&gt;
      &lt;/Loggers&gt;
  &lt;/Configuration&gt;
  </code></pre>
  
  <p>LumberJack.java
   </p>
  
  <pre><code>package james.log;
  
  import james.util.ConcurrentDateFormatAccess;
  import org.apache.logging.log4j.ThreadContext;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.testng.ITestContext;
  import org.testng.annotations.AfterMethod;
  import org.testng.annotations.AfterSuite;
  import org.testng.annotations.BeforeMethod;
  import org.testng.annotations.Test;
  
  import java.lang.reflect.Method;
  
  /**
   * @author james.affleck
   */
  public class LumberjackTest {
      private static final Logger logger = LoggerFactory.getLogger(LumberjackTest.class);
      private static ThreadLocal&lt;String&gt; methodLogName = new ThreadLocal&lt;&gt;();
      private static String suiteName = "";
  
      @BeforeMethod
      public void loggerDoTheThings(ITestContext context, Method method) {
          if(suiteName.isEmpty()) {
              String suite = context.getSuite().getName() + "(";
              String suiteTime = new ConcurrentDateFormatAccess().getCurrentDateSPrecision();
              suite += suiteTime + ")";
              suiteName = suite;
          }
  
          // Test filename = testClass.testMethodname
          String classname = this.getClass().getName();
          classname = classname.substring(classname.lastIndexOf(".") + 1); //get rid of package info we don't care about
          String testName = classname + "." + method.getName();
  
          // Using this to store logger instance for later
          String testStart = new ConcurrentDateFormatAccess().getCurrentDateMSPrecision();
          methodLogName.set(testName + testStart);
  
          ThreadContext.put("suiteTimestamp", suiteName);
          ThreadContext.put("testName", testName);
          ThreadContext.put("testStartTime", testStart);
      }
  
      @AfterMethod
      public void closeTheThings() {
          methodLogName.set(null);
      }
      @AfterSuite
      public void closeSuite() {
          suiteName = null;
      }
  
      @Test
      public void testLog1() {
          logThings();
      }
  
      @Test
      public void testLog2() {
          logThings();
      }
  
      public void logThings() {
          logger.info("info message");
          logger.debug("debug message");
          logger.warn("warn message");
      }
  }
  </code></pre>