logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alex Wu <alexyx...@gmail.com>
Subject Issue of creating and configuring custom appenders
Date Mon, 02 Jun 2014 07:05:48 GMT
Hi all, I have followed Ralph's suggestion in this issue and the source
code of ConsoleAppender from apache to tried to create a custom appender
for appending logs to a JTextArea.


But I am having trouble to make it to work, could anyone please give me
some help for this?

the problems I am facing are,

- I cannot find a way to pass that JTextArea object to my TextAreaAppender
- I am also having problem creating the manager, in ConsoleAppender, they
use "new OutputStreamManager(data.os, data.type, data.layout)", and it's
actually a "protected" constructor, how is this possible? BTW, eclipse is
also showing error about this. *Actually, I got around with this by
creating a subclass of OutputStreamManager in my test and make the
constructor public, not sure if I have done it in a right way though.*

Any help would be appreciated.

Test classes are as follow,


package testing;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

import javax.swing.JTextArea;

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender;
import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.helpers.Booleans;
import org.apache.logging.log4j.core.layout.PatternLayout;

import testing.ConsoleAppender.ConsoleManagerFactory;

public class TextAreaAppender extends
private static TextAreaManagerFactory factory = new
 public enum Target {

protected TextAreaAppender(String name, Layout<? extends Serializable>
layout, Filter filter,
OutputStreamManager manager, boolean ignoreExceptions) {
super(name, layout, filter, ignoreExceptions, true, manager);
// TODO Auto-generated constructor stub
    public static TextAreaAppender createAppender(
            @PluginElement("Layout") Layout<? extends Serializable> 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,
        final Target target = t == null ? Target.TEXTAREA :
        return new TextAreaAppender(name, layout, filter,
getManager(isFollow, target, layout), ignoreExceptions);
 private static OutputStreamManager getManager(final boolean follow, final
Target target, final Layout<? extends Serializable> 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;
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<? extends Serializable> 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<? extends Serializable> layout) {
            this.os = os;
            this.type = type;
            this.layout = layout;
     * Factory to create the Appender.
    private static class TextAreaManagerFactory implements
ManagerFactory<OutputStreamManager, FactoryData> {

         * Create an OutputStreamManager.
         * @param name The name of the entity to manage.
         * @param data The data required to create the entity.
         * @return The OutputStreamManager
        public OutputStreamManager createManager(final String name, final
FactoryData data) {
            return new OutputStreamManager(data.os, data.type,
data.layout);// protected constructor???


package testing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.IOException;
import java.io.OutputStream;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;

public class Log4j2Example {
class LogModel extends AbstractTableModel{

public int getColumnCount() {
// TODO Auto-generated method stub
return 1;

public int getRowCount() {
// TODO Auto-generated method stub
return 0;

public Object getValueAt(int rowIndex, int columnIndex) {
// TODO Auto-generated method stub
case 0: return null;
default: return null;
private final 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));
frame.add(textarea, BorderLayout.SOUTH);
frame.setSize(400, 400);

 static final Logger logger =
public static void main(String[] args) {
logger.trace("Entering Log4j Example.");
Hello hello = new Hello();
if (!hello.callMe()) {
logger.trace("Exiting Log4j Example.");


*<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
<Appenders> <Console name="CONSOLE" target="SYSTEM_OUT"> <PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console>
<TextArea name="TextArea" class="testing.Log4j2Example.TextAreaAppender">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} -
%msg%n" /> </TextArea> </Appenders> <Loggers> <Logger
name="testing.Log4j2Example" level="ALL">       <AppenderRef
ref="TextArea"/>     </Logger> <Root level="ERROR"> <AppenderRef
ref="CONSOLE"/> </Root> </Loggers></Configuration>*

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message