2

Below is my builder class in which two fields are mandatory which are userId and clientId.

public final class InputKeys {

    private final long userId;
    private final int clientId;
    private final long timeout;
    private final Preference preferences;
    private final boolean debugFlag;
    private final Map<String, String> attributeMap;

    private InputKeys(Builder builder) {
    this.userId = builder.userId;
    this.clientId = builder.clientId;
    this.preferences = builder.preference;
    this.attributeMap = builder.attributeMap;
    this.timeout = builder.timeout;
    this.debugFlag = builder.debugFlag;
    }

    public static class Builder {
    protected final long userId;
    protected final int clientId;
    protected long timeout = 500L;
    protected Preference preference;
    protected boolean debugFlag;
    protected Map<String, String> attributeMap;


    public Builder(long userId, int clientId) {
        this.userId = userId;
        this.clientId = clientId;
    }

    public Builder attributeMap(Map<String, String> attributeMap) {
        this.attributeMap = attributeMap;
        return this;
    }

    public Builder preference(Preference preference) {
        this.preference = preference;
        return this;
    }

    public Builder debugFlag(boolean debugFlag) {
        this.debugFlag = debugFlag;
        return this;
    }

    public Builder timeout(long timeout) {
        this.timeout = timeout;
        return this;
    }

    public InputKeys build() {
        return new InputKeys(this);
    }
    }

    //getters  here
}

Now I will be calling this builder class like this -

InputKeys keys = new InputKeys.Builder(12000L, 33L).build();

But it might be possible that somebody can pass wrong inputs values such as they are passing negative userId's and negative clientId's, negative timeout values or empty attributeMap. How to deal in these kind of situation in my builder class?

If I am having IllegalArgumentcheck for each variables in if else if block, then my whole Builder class gets flooded up with IllegalArgumentException check?

Is there any better way of doing this?

3 Answers3

1

Make methods which have common logic, eg

private void assertNonNegative(long val, String attr) {
    if (val < 0) {
         throw IllegalArgumentException(attr + " cannot be negative");
    }
}
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • Which means, I will be using this method for each variable check correct? And where I will be having this check? Can you provide any example of this where to use it? So for two mandatory case it will be like this? `public Builder(long userId, int clientId) { assertNonNegative(userId, "userId"); assertNonNegative(clientId, "clientId"); this.userId = userId; this.clientId = clientId; }` –  Jan 11 '14 at 09:06
  • Yes, this is it, also if have Builder.setSomthing you can do it in setter not in Builder.build(), take a look at java.lang.ProcessBuilder – Evgeniy Dorofeev Jan 11 '14 at 09:52
0

I suggest to move all checks to the build method. There is nothing wrong about this approach.

Moreover, it is a typical case to implement constraints like "if field a is specified then field b is mandatory" in the build method.

oceansize
  • 623
  • 3
  • 16
  • Thanks oceansize for the suggestion. Can you provide an example how we can do these checks in build method properly? –  Jan 11 '14 at 09:45
  • Just some **if** checks (before returning a built object) with throwing `IllegalArgumentException` - same as above. – oceansize Jan 11 '14 at 09:52
0

What you need is a more declarative way to validate argument input in order to avoid repeating validation code again and again.

I suggest to use java annotations to indicate that a variable should belong to a specific range of values.

If you use Java EE or a framework like Spring you could use java annotations and let the framework do the value check. See this and this regarding validation with Java EE.

Giving an example to validate the properties of a Name class:

public class Name {
    @NotNull
    @Size(min=1, max=16)
    private String firstname;

    @NotNull 
    @Size(min=1, max=16)
    private String lastname;
}

The java EE would handle all the validation.

Hope I helped!

Pantelis Natsiavas
  • 5,293
  • 5
  • 21
  • 36