So I'm working on Spring Boot autoconfiguration for Axon Framework. I run into a nice interface in Axon framework that is unfortunately too specific. So I generalize. The original, pared down:
public interface AuditDataProvider {
Map<String, Object> provideAuditDataFor(CommandMessage<?> command);
} Aha! A SAM interface, interesting. So I craft my look-a-like:
public interface AuditDataProvider {
Map<String, Object> provideAuditDataFor(Message<?> command);
} Not much difference. Note the method parameter is Message rather than CommandMessage. This works fine as the implementation I have in mind uses getMetaData(), defined in Message and inherited by CommandMessage—so the original Axon interface is overspecified, using a more specific parameter type than needed.
(Keep this in mind: most times use the most general type you can.)
Ah, but other parts of the Axon framework ask for an AuditDataProvider (the original code, above) and I'm defining a new, more general interface. I cannot extend the original with mine; Java correctly complains that I am widening the type: all CommandMessages are Messages, but not all Messages are CommandMessages.
Java 8 method references to the rescue!
public interface MessageAuditDataProvider {
Map<String, Object> provideAuditDataFor(final Message<?> message);
default AuditDataProvider asAuditDataProvider() {
return this::provideAuditDataFor;
}
} Because I accept a supertype in my new interface relative to the original, my method reference works simply and cleanly.
No comments:
Post a Comment