title: How to output logs to a JTextArea using Log4j2
body: <p>I have been trying to output logs to a JTextArea for days and still no luck. Basically what I have tried is creating my own custom appender following existing appender like consoleAppender and tried to configure it in log4j2.xml. I feel I am heading the right direction but somehow I couldn't get it to work. I have asked in log4j2 user mailing list and no one seems to care to help me. Hopefully I can get my help here. If you know how to achieve it, please give me steps or even code snippets.</p>
  
  <p>Thank you for your help in advanced.</p>
  
  <p>Okay, since someone down voted my question as it doesn't show any effort then I'd better show some. I didn't show anything I have done was because I am not so sure what I was doing was the correct way and people might have their own approach.</p>
  
  <p>the problems I am facing are, </p>
  
  <ul>
  <li>I cannot find a way to pass that JTextArea object to my TextAreaAppender</li>
  <li>When I tried to run the test classes, always getting an error saying TextAreaAppender CLASS_NOT_FOUND, but I have tried all the possible way I can find to specify the class attribute in log4j2.xml</li>
  </ul>
  
  <p>codes are as following,</p>
  
  <p><strong>TextAreaAppender</strong></p>
  
  <pre><code>public class TextAreaAppender extends AbstractOutputStreamAppender&lt;OutputStreamManager&gt;{
      private static TextAreaManagerFactory factory = new TextAreaManagerFactory();
  
      public enum Target {
          TEXTAREA
      }
  
      protected TextAreaAppender(String name, Layout&lt;? extends Serializable&gt; layout, Filter filter,
              OutputStreamManager manager, boolean ignoreExceptions) {
          super(name, layout, filter, ignoreExceptions, true, manager);
          // TODO Auto-generated constructor stub
      }
  
      @PluginFactory
      public static TextAreaAppender createAppender(
              @PluginElement("Layout") Layout&lt;? extends Serializable&gt; layout,
              @PluginElement("Filters") final Filter filter,
              @PluginAttribute("target") final String t,
              @PluginAttribute("name") final String name,
              @PluginAttribute("follow") final String follow,
              @PluginAttribute("ignoreExceptions") final String ignore) {
          if (name == null) {
              LOGGER.error("No name provided for TextAreaAppender");
              return null;
          }
          if (layout == null) {
              layout = PatternLayout.createLayout(null, null, null, null, null, null);
          }
          final boolean isFollow = Boolean.parseBoolean(follow);
          final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
          final Target target = t == null ? Target.TEXTAREA : Target.valueOf(t);
          return new TextAreaAppender(name, layout, filter, getManager(isFollow, target, layout), ignoreExceptions);
      }
  
      private static OutputStreamManager getManager(final boolean follow, final Target target, final Layout&lt;? extends Serializable&gt; layout) {
          final String type = target.name();
          //should change to getOutputStream(JTextArea), 
          //but not sure how I can pass textarea object to this class
          final OutputStream os = getOutputStream(follow, target);
          return OutputStreamManager.getManager(target.name() + "." + follow, new FactoryData(os, type, layout), factory);
      }
  
      private static OutputStream getOutputStream(JTextArea ta){ 
          return new TextAreaOutputStream(ta); 
      }
      private static class TextAreaOutputStream extends OutputStream {
          private final JTextArea output;
          public TextAreaOutputStream(JTextArea ta){
              this.output = ta; 
          }
          @Override
          public void write(int i) throws IOException{
              output.append(String.valueOf((char) i)); 
          }
      }
  
      /**
       * Data to pass to factory method.
       */
      private static class FactoryData {
          private final OutputStream os;
          private final String type;
          private final Layout&lt;? extends Serializable&gt; layout;
  
          /**
           * Constructor.
           * @param os The OutputStream.
           * @param type The name of the target.
           * @param layout A Serializable layout
           */
          public FactoryData(final OutputStream os, final String type, final Layout&lt;? extends Serializable&gt; layout) {
              this.os = os;
              this.type = type;
              this.layout = layout;
          }
      }
      /**
       * Factory to create the Appender.
       */
      private static class TextAreaManagerFactory implements ManagerFactory&lt;OutputStreamManager, FactoryData&gt; {
  
          /**
           * Create an OutputStreamManager.
           * @param name The name of the entity to manage.
           * @param data The data required to create the entity.
           * @return The OutputStreamManager
           */
          @Override
          public OutputStreamManager createManager(final String name, final FactoryData data) {
              return new TextAreaOutputStreamManager(data.os, data.type, data.layout);// protected constructor???
          }
      }
  
      private static class TextAreaOutputStreamManager extends OutputStreamManager{
  
          public TextAreaOutputStreamManager(OutputStream os, String name,
                  Layout&lt;?&gt; layout) {
              super(os, name, layout);
              // TODO Auto-generated constructor stub
          }
      }
  }
  </code></pre>
  
  <p><strong>UI test class</strong></p>
  
  <pre><code>public class Log4j2Example {
      class LogModel extends AbstractTableModel{
  
          @Override
          public int getColumnCount() {
              // TODO Auto-generated method stub
              return 1;
          }
  
          @Override
          public int getRowCount() {
              // TODO Auto-generated method stub
              return 0;
          }
  
          @Override
          public Object getValueAt(int rowIndex, int columnIndex) {
              // TODO Auto-generated method stub
              switch(columnIndex){
                  case 0: return null;
                  default: return null;
              }
          }
  
      }
      private final static JTextArea textarea = new JTextArea();
      private final LogModel model = new LogModel();
      private final JTable table = new JTable(model);
      static Log4j2Example INSTANCE = new Log4j2Example();
      JFrame frame = new JFrame();
  
      void run(){
          frame.setLayout(new BorderLayout());
          table.setBorder(new TitledBorder("Table"));
          textarea.setBorder(new TitledBorder("Text Area"));
          textarea.setPreferredSize(new Dimension(100, 150));
          textarea.setEditable(false);
  
          frame.add(table);
          frame.add(textarea, BorderLayout.SOUTH);
  
          frame.setVisible(true);
          frame.setSize(400, 400);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }
  
      static final Logger logger = LogManager.getLogger(Log4j2Example.class.getName());
      public static void main(String[] args) {
          INSTANCE.run();
          System.out.println("test");
          logger.trace("Entering Log4j Example.");
          Hello hello = new Hello();
          if (!hello.callMe()) {
              logger.error("Ohh!Failed!");
          }
          logger.trace("Exiting Log4j Example.");
  
  
      }
  }
  </code></pre>
  
  <p><strong>log4j2.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Configuration status="WARN"&gt;
      &lt;Appenders&gt;
          &lt;Console name="CONSOLE" target="SYSTEM_OUT"&gt;
              &lt;PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /&gt;
          &lt;/Console&gt;
          &lt;TextArea name="TextArea" class="testing.Log4j2Example.TextAreaAppender"&gt;
              &lt;PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /&gt;
          &lt;/TextArea&gt;
      &lt;/Appenders&gt;
      &lt;Loggers&gt;
          &lt;Logger name="testing.Log4j2Example" level="ALL"&gt;
            &lt;AppenderRef ref="TextArea"/&gt;
          &lt;/Logger&gt;
  
          &lt;Root level="ERROR"&gt;
              &lt;AppenderRef ref="CONSOLE"/&gt;
          &lt;/Root&gt;
      &lt;/Loggers&gt;
  &lt;/Configuration&gt;
  </code></pre>