Hi Joern,<br><br>The reason for using generics in the Encoder interface is to avoid having to cast.  (hmm, I guess that&#39;s always the reason to use generics ?)<br><br>Take for example, the ObjectEncoder: it needs an ObjectOutputStream, so it wraps the given OutputStream in an ObjectOutputStream:<br>
<br>public class ObjectEncoder implements Encoder&lt;ObjectOutputStream&gt; {<br><br>  public void encode(ILoggingEvent event, ObjectOutputStream output) throws IOException {<br>    output.writeObject(event);<br>  }<br><br>
  public ObjectOutputStream decorate(OutputStream os) throws IOException {<br>    return new ObjectOutputStream(os);<br>  }<br>}<br><br><br>On the other hand, the ProtobufEncoder can use a plain OutputStream, so its decorate impl is simply a no-op:<br>
<br>public class ProtobufEncoder implements Encoder&lt;OutputStream&gt;{<br><br>  private ProtoBufConvertor convertor = new ProtoBufConvertor();<br><br>  public void encode(ILoggingEvent event, OutputStream output) throws IOException {<br>
    LoggingProtos.LoggingEvent ev = convertor.convert(event);<br>    ev.writeTo(output);<br>  }<br><br>  public OutputStream decorate(OutputStream os) throws IOException {<br>    return os;<br>  }<br>}<br><br>Clear now ?<br>
<br>Maarten<br><pre class="prettyprint lang-java"><span class="pln"></span><span class="pun"><br></span></pre><br><div class="gmail_quote">On Tue, Feb 16, 2010 at 11:18 PM, Joern Huxhorn (JIRA) <span dir="ltr">&lt;<a href="mailto:noreply-jira@qos.ch">noreply-jira@qos.ch</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
    [ <a href="http://jira.qos.ch/browse/LBCORE-128?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&amp;focusedCommentId=11533#action_11533" target="_blank">http://jira.qos.ch/browse/LBCORE-128?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&amp;focusedCommentId=11533#action_11533</a> ]<br>

<div class="im"><br>
Joern Huxhorn commented on LBCORE-128:<br>
--------------------------------------<br>
<br>
</div><div class="im">My branch was meant to implement what I need in a manner of least possible impact.<br>
I detached the implementation of FileAppender from WriterAppender, extending UnsynchronizedAppenderBase instead.<br>
<br>
</div><div class="im">writerWrite(String s, boolean flush) (which I didn&#39;t rename even though there&#39;s no writer anymore but a stream instead) is now using convertToBytes(String s) and writeBytes(byte[] bytes, boolean flush), i.e. the appender writes bytes into a stream instead of writing a String into a Writer. Encoding of the String isn&#39;t handled by the Writer anymore. Instead, String.getBytes(charset) is used to transform into bytes. The charset is initialized once during startup.<br>

<br>
I&#39;ve also taken a look at Maartens Encoder but I fear I don&#39;t really get the reason for either the decorate method or the use of generics in that case.<br>
<br>
In the meantime, I&#39;ve also implemented streaming encoder/decoder interfaces for sulky/Lilith.<br>
<a href="http://github.com/huxi/sulky/tree/master/sulky-codec/src/main/java/de/huxhorn/sulky/codec/streaming/" target="_blank">http://github.com/huxi/sulky/tree/master/sulky-codec/src/main/java/de/huxhorn/sulky/codec/streaming/</a><br>

Those are a supplement of my previous byte[]-based encoders/decoders and allow chaining. I use generics to define the type that is encoded/decoded. The decoration of the stream is meant to be encapsulated in the actual implementation.<br>

<br>
I realize that this does not allow reusing of the same encapsulated stream, though. This means that encoding using Java serialization is less efficient since duplicate strings, for example, are serialized over and over instead of only once, referencing the already serialized string.<br>

It has the advantage that written byte[] are not dependent on previously written ones, on the other hand. This is crucial for random event access, in my case.<br>
<br>
I don&#39;t say Maartens design is bad and mine is better. Neither you nor (especially!) Maarten should get this impression.<br>
<br>
If you are actually aiming for a bigger change than my small patch then it might be a good idea to keep the layout concept, even for binary files, and add the ability to use binary layouts that would also contain the encoder for the event.<br>

I&#39;ve enabled binary headers and footers by declaring writeHeader() &amp; writeFooter() protected instead of private in FileAppender - so I could (re)implement them as needed in my extending class.<br>
<br>
If Layout would/could handle binary data for header, footer and actual events instead, extending RollingFileAppender wouldn&#39;t be necessary anymore. One could simply declare a LilithLayout (with parameters?) instead.<br>

This would be a much cleaner design but I feared that such a fundamental change wouldn&#39;t have any chance of being accepted for inclusion.<br>
<br>
Thanks for taking a look at this issue. I really appreciate it!<br>
<br>
</div><div><div></div><div class="h5">&gt; Please support implementation of binary log files in RollingFileAppender/FileAppender<br>
&gt; -------------------------------------------------------------------------------------<br>
&gt;<br>
&gt;                 Key: LBCORE-128<br>
&gt;                 URL: <a href="http://jira.qos.ch/browse/LBCORE-128" target="_blank">http://jira.qos.ch/browse/LBCORE-128</a><br>
&gt;             Project: logback-core<br>
&gt;          Issue Type: Improvement<br>
&gt;          Components: Appender<br>
&gt;    Affects Versions: 0.9.17<br>
&gt;            Reporter: Joern Huxhorn<br>
&gt;            Assignee: Ceki Gulcu<br>
&gt;<br>
&gt; This was discussed briefly at <a href="http://marc.info/?l=logback-dev&amp;m=124905434331308&amp;w=2" target="_blank">http://marc.info/?l=logback-dev&amp;m=124905434331308&amp;w=2</a> and I forgot to file a ticket about this.<br>

&gt; Currently, RandomFileAppender =&gt; FileAppender =&gt; WriterAppender is using the following method in WriterAppender to actually write the data:<br>
&gt; protected void writerWrite(String s, boolean flush) throws IOException<br>
&gt; Please add an additional method like<br>
&gt; protected void writerWrite(byte[] bytes, boolean flush) throws IOException<br>
&gt; to write to the underlying stream directly.<br>
&gt; writerWrite(String, boolean) could call that method after performing the transformation internally, making this change transparent for the rest of the implementation.<br>
&gt; Using a binary format for logfiles could have tremendous performance impact as can be seen here: <a href="http://sourceforge.net/apps/trac/lilith/wiki/SerializationPerformance" target="_blank">http://sourceforge.net/apps/trac/lilith/wiki/SerializationPerformance</a><br>

<br>
--<br>
This message is automatically generated by JIRA.<br>
-<br>
If you think it was sent incorrectly contact one of the administrators: <a href="http://jira.qos.ch/secure/Administrators.jspa" target="_blank">http://jira.qos.ch/secure/Administrators.jspa</a><br>
-<br>
For more information on JIRA, see: <a href="http://www.atlassian.com/software/jira" target="_blank">http://www.atlassian.com/software/jira</a><br>
<br>
<br>
_______________________________________________<br>
logback-dev mailing list<br>
<a href="mailto:logback-dev@qos.ch">logback-dev@qos.ch</a><br>
<a href="http://qos.ch/mailman/listinfo/logback-dev" target="_blank">http://qos.ch/mailman/listinfo/logback-dev</a><br>
</div></div></blockquote></div><br>