1

I'm writing a class for Message. Message comes with Header and Payload.

Header has following fields:

  1. Version
  2. Type

For Type "XYZ", the following Payloads are allowed.

  1. Configuration
  2. Metafile

where configuration can only be an HashMap of Key, value pairs. And Metafile can only be a String (file contents)

Will Builder pattern suit here to build a message "Version:123, Type:XYZ, Configuration, HashMap" ? Or what is the best way to model this problem in Java?

3

First of all, this is not a "problem" which needs "modelling". This is just a syntax issue.

Secondly, why on earth would you even think of using a builder pattern for this? Is it perhaps because you read "Clean Code", where on page 35 the author classifies methods into four categories, depending on whether they accept zero, one, two, or the incredibly high number of three arguments, with four arguments being, presumably, unthinkable? Oh, never mind him, he was just being silly.

Things should be as simple as possible, but not simpler
-Albert Einstein

Methods should accept as few arguments as possible, but not fewer than what they need to do their job.
--Mike Nakis

The builder pattern is generally an overkill for messages, because what you usually want to do with a message is to instantiate it, fill it, and send it on its way using as few lines of code as possible. Ideally, just one line of code.

As a matter of fact, sending a message should look syntactically identical to placing a function call, and the fact that it does not look identical in most mainstream languages is a shortcoming of those languages. What we basically want to do is to place an asynchronous call. The fact that a message is to be used to achieve this is just an implementation detail which should be hidden from us, and the fact that we still have to waste our time dealing with implementation details like constructing, filling, and sending messages, (let alone defining and maintaining entire class hierarchies of messages,) just shows that languages still have a long way to go.

So, in lack of any better mechanisms, the task of instantiating, filling, and sending a message should not be any more complicated than this:

sendMessage( new MyMessage( 123, XYZ, configuration, metafile ) );

Of course, the MyMessage class presumably extends some Message class, (which you are for some reason thinking of as a Header,) so the first statement of the constructor of MyMessage will be as follows:

super( version, type );
2

No, a builder is not unheard of for building messages. Spring Integration does something similar with a Builder. Spring Integration messages have a general structure like yours: a payload and a header.

  • There's the Message interface

    public interface Message<T> {
        T getPayLoad();
        MessageHeaders getHeaders();
    }
    
  • The MessageHeaders class (your Header) is just a Serializable POJO that implements Map<String, Object>

    public final class MessageHeaders implements Map<String, Object>, Serializable { ... }
    
  • The payload is just a POJO. You've already gotten XYZ

Putting it all together, you can have

public abstract class XYZMessage implements Message<XYZ>{

   private XYZ payload;
   private Headers headers;

   public abstract XYZ getPayload();
   public abstract getHeaders();

} 

Your builder will not look unlike what we have for Spring Integration. Granted, the Spring Framework's implementation is more meaty than you'll ever need, but you could still borrow a leaf from it. If you do, your usage would be as clean as the following

Message<Account> m = MessageBuilder.withPayload(a)
                                   .setHeader("VERSION", "123")
                                   .build();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.