Oh, I think I did not express myself clearly here. These methods should not
go away. And they will still return the right right types (T
toSerializable(LogEvent event) and byte[] toByteArray(LogEvent event
respectively). What changes is that getLayout() in the appender no longer
returns a generic Layout<T> but a Layout<? extends Serializable>. So all
the code that deals with Appenders no longer has to accomodate the layout
that they may use. But the generic is used only where it counts, in the
Layout itself. And for the caller, the result is the same respectively (if
you hold only a Layout in your hand, you can get a byte array and a class
that implements Serializable, if you hold a concrete implementation in your
hand, you can get the same byte array and also a more concrete type).
Nothing changes here but a whole world of casts and awkward constructs
around the Appenders goes away.
I hope that explains a bit better what I would like to accomplish.
Thanks,
Henning
On Sun, Aug 11, 2013 at 6:33 PM, Ralph Goers <[email protected]>wrote:
> The Layout interface has a toByteArray method that, of course, returns a
> byte array. However, it also has a toSerializable method that returns the
> generic type. FYI - these used to be named format and formatAs but were
> renamed last October after discussion as it was believed the current names
> are clearer. AbstractStringLayout's implementation of toByteArray simply
> does toSerializable(event).getBytes(charset), so most Layouts just
> implement toSerializable and return a String.
>
> Getting rid of the toSerializable method isn't really an option. The JMS
> appenders use it and if returns a String then then send a TextMessage,
> otherwise they send an ObjectMessage. I don't see how that could be
> accomplished with only the toByteArray method.
>
> Ralph
>
>
>
> On Aug 11, 2013, at 4:14 PM, Remko Popma wrote:
>
> I wouldn't mind taking another stab at this. Currently in transit, cannot
> check source, But it seems to me that if we know we eventually need a byte
> array, then why not have that as part of the contract of the Layout
> interface.
> Do we ever serialize into anything else than a byte array?
>
> If Layout just returned a fixed byte array (or Serializable object, but
> why not just the byte array...), then we would not need the generics
> anymore.
>
> AbstractStringLayout can be implemented with an abstract method, say,
> public String serializeToString(LogEvent);
> for example, that subclasses need to implement.
>
> I'll take a more detailed look when I get back later today.
>
>
> On Monday, August 12, 2013, Ralph Goers wrote:
>
>> I think I want to comment on the generic appenders a bit more.
>>
>> In Log4j 1.x Layouts always return Strings. That is actually very
>> limiting. Logback started that way but then switched from Layouts to
>> Encoders. As described at http://logback.qos.ch/manual/encoders.html,
>> Encoders transform the LogEvent into a byte array and also write to an
>> OutputStream. In Log4j 2 the Appenders (which usually delegate to a
>> Manager) are responsible for managing and writing to the OutputStream. This
>> means Layouts should return byte arrays, not Strings, to provide the
>> flexibility that is required. However a large number of Layouts to return
>> Strings. All of these will extend AbstractStringLayout, which will handle
>> converting from the String to a byte array. Since AbstractStringLayout
>> cannot guarantee that its subclasses return a String without the generic it
>> would have to do:
>>
>> Serializable serializable = toSerializable(event);
>> if (serializable instanceof String) {
>> ((String) serializable).getBytes(charset);
>> } else {
>> throw new IllegalArgumentException("Some error message about bad
>> type");
>> }
>>
>> instead of just
>>
>> toSerializable(event).getBytes(charset);
>>
>> Turning what is now a compile time error into a runtime error.
>>
>> My recollection was that Gary tried this once and found that removing the
>> generic had issues in other places but I don't recall what they were.
>>
>> Ralph
>>
>>
>>
>> On Aug 11, 2013, at 12:19 PM, Ralph Goers wrote:
>>
>> Gary and I have discussed the generic on the Appender before. It is
>> problematic to have it and just as problematic to leave it off. IOW, it is
>> awkward either way.
>>
>> As Nick, points out the "interesting construct" below has absolutely
>> nothing to do with the generic on the Appender.
>>
>> I don't know how to compare your pull request to trunk since that is
>> maintained in svn, at least for now.
>>
>> Ralph
>>
>>
>> On Aug 10, 2013, at 4:31 PM, Henning Schmiedehausen wrote:
>>
>> Hi,
>>
>> I was toying with the log4j 2 API for a new project and I stumbled over
>> the fact that it uses a generic for Appender<T> without actually being
>> generic. The only generic part is the Layout. So as a result there is this
>> weird construct of Appender<SomeSerializableType> which is actually
>> dictated by the layout in use.
>>
>> This leads to really interesting constructs such as
>>
>> public abstract class AbstractDatabaseAppender<T extends
>> AbstractDatabaseManager> extends AbstractAppender<LogEvent>
>>
>> I was wondering whether this is necessary as it makes the API very
>> cumbersome to use and read so I removed the generic from Appender and
>> subsequently went through the log4j 2 code base and mostly removed stuff
>> that was no longer needed once that was gone. The result is at
>>
>> https://github.com/apache/logging-log4j2/pull/1
>>
>> I will also file a JIRA for this.
>>
>> I know that the 2.0 release should be coming soon (being at beta8), but I
>> feel that making that change in the API before it is set in stone with 2.0
>> woulc be really beneficial for anyone who wants to port code to 2.0 / write
>> new code.
>>
>> Thanks for considering,
>> Henning
>>
>>
>>
>>
>