I would like to show errors logged by SLF4J in TextArea
in JavaFX. What I have so far is an appender
in logback-test.xml:
<appender name="err" class="logtest.AppTA">
<filter class="logtest.ErrFilter" />
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
TextArea
ready to receive stream:
public class Output extends OutputStream{
private final TextArea ta;
public Output(TextArea ta) {
this.ta = ta;
}
@Override
public void write(int b) throws IOException {
if (ta!=null) {
ta.appendText(String.valueOf((char) b));
}
}
}
and a class to handle appending:
public class AppTA extends AppenderBase<ILoggingEvent> {
PatternLayoutEncoder encoder;
OutputStream os;
@Override
protected void append(ILoggingEvent event) {
try {
if (isEncoderInitialized) {
this.encoder.doEncode(event);
}
} catch (IOException e) {
}
}
@Override
public void start() {
if (this.encoder == null) {
addError("No encoder set for the appender named [" + name + "].");
return;
}
try {
encoder.init(os);
} catch (IOException ex) {
Logger.getLogger(AppTA.class.getName()).log(Level.SEVERE, null, ex);
}
super.start();
}
public PatternLayoutEncoder getEncoder() {
return encoder;
}
public void setEncoder(PatternLayoutEncoder encoder) {
this.encoder = encoder;
}
}
Now the problem I'm having is that my TextArea
is in the controller class and I don't know how to link them together. Especially when SLF4J creates AppTA
instance on its own - I don't really have a way to pass my TextArea
to AppTA
used by logger.
How can I tackle this?
This answer is dependent on your underlying logging framework being logback. Since SLF4J only supports one logging implementation at a time I don't think its possible to solve in an implementation agnostic way.
The simplest way to solve this issue is to create your own appender and utilize static state so you can access the streams across the application.
Below I demonstrate a basic example of an appender that can have its output stream set statically at any time.
This has some limitations, mainly that it can only handle one outputstream at a time, bu tit shouldn't be too difficult to extend to support multiple.
In the below application when you click the log button it will log info and error messages, all output will go to stdout but only error messsages will be shown in the text area.
Basic JavaFx application class
Simple custom appender class
Logback config
You could configure Logback to write to System.out and System.err.
Configure those streams (setOut, setErr) in your application to write to the textarea.
This solution should work with any SLF4J binding without code changes.
Basically you would implement a read-only JavaFX console.
Also have a look at the following answer: https://stackoverflow.com/a/9219837/506855