Note that you will shoot yourself in the foot with such an appender by
causing memory to be exhausted unless the appender never lets the contents
of the text area grow beyond some limit.

Gary


On Mon, Jun 2, 2014 at 3:05 AM, Alex Wu <alexyx...@gmail.com> wrote:

> 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.
>
> https://issues.apache.org/jira/browse/LOG4J2-303
>
> 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,
>
> *TextAreaAppender.java*
>
> 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
> AbstractOutputStreamAppender<OutputStreamManager>{
> private static TextAreaManagerFactory factory = new
> TextAreaManagerFactory();
>  public enum Target {
>         TEXTAREA
>     }
>
> 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
> }
>  @PluginFactory
>     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,
> 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<? 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;
> }
> @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<? 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
>          */
>         @Override
>         public OutputStreamManager createManager(final String name, final
> FactoryData data) {
>             return new OutputStreamManager(data.os, data.type,
> data.layout);// protected constructor???
>         }
>     }
> }
>
> *Lo4gj2Example.java*
>
> 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{
>
> @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 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) {
> logger.trace("Entering Log4j Example.");
> Hello hello = new Hello();
> if (!hello.callMe()) {
> logger.error("Ohh!Failed!");
> }
> logger.trace("Exiting Log4j Example.");
>  INSTANCE.run();
> }
> }
>
> *log4j2.xml*
>
> *<?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>*
>



-- 
E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
Java Persistence with Hibernate, Second Edition
<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Reply via email to