Java Code modularization, check if they are all null or not

Viewed 143

Is there any clean way to check if they are all null or not for example getDescription(), getName(), getScript(), getTargets() and getTrigger() is null or not, checking in one line?

              ruleBean.setDescription(rule.getDescription());
          } else if (rule.getName() != null) {
              ruleBean.setName(rule.getName());
          } else if (rule.getScript() != null) {
              ruleBean.setScript(rule.getScript());
          } else if (rule.getTargets() != null) {
              ruleBean.setTargets(rule.getTargets());
          } else if (rule.getTrigger() != null) {
              ruleBean.setTrigger(rule.getTrigger());
          } else {
              return ResponseBean.builder().withData(request.getData())
                      .withMessage("No data provided for rule update").asFailure().build();
          } ```
3 Answers

You can write a single condition with Optional:

if (rule.getName() != null) {
 ruleBean.setName(rule.getName());
}

becomes:

Optional.ofNullable(rule.getName()).ifPresent(ruleBean::setName);

It's harder to chain this to give the "if else" behaviour you have, though.

It looks like what you're trying to detect with the "if/else" is whether some update was performed. To achieve this, you could have a method like:

<T> boolean did(T value, Consumer<? super T> consumer) {
  if (value == null) return false;
  consumer.accept(value);
  return true;
}

Then you can write your chain as:

boolean didSomething =
    did(rule.getName(), ruleBean::setName)
    || did(rule.getScript(), ruleBean::setScript) /* etc */;

if (!didSomething) {
  // Return your error response.
}

Because of the short-circuiting behaviour of ||, this will stop after the first call to did which "did" something, like the if/else if.

And if you actually want to apply the update for any non-null value, simply change || to |. The value of didSomething is still false if none of the conditions matched, as before.

Java validation API (JSR-380) can be very handy in this type of problems, if you can afford the dependencies.

In this specific case, you can just annotate your bean:


import javax.validation.constraints.NotNull;
// ...
public class Rule {

    @NotNull
    private String description;
    @NotNull
    private String name;
    @NotNull
    private String script;
    @NotNull
    private String targets;
    @NotNull
    private String trigger;

}

(there are more built-in constraint definitions)

And then validate using Hibernate Validator (the reference implementation of the validation API):


        Rule rule = new Rule();
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<Rule>> violations = validator.validate(rule);
        if (violations.isEmpty()) {
            //all good!
        } else {
            //bean is not valid
        }

In order to use this approach, you need two new dependencies in your pom.xml:

Java Validation API:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

and Hibernate Validator

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.13.Final</version>
</dependency>
  • If you have a lot of attributes in rule need to check, you can use reflection to make it clean a little.
  • If you just have a few attributes need to check, the if solution is a clean and readable way to do it.
  • Waring: the reflection solution may lead to a performance issue.

example code:

test.java
public class test{
    public static void main(String[] args)
    {
        Foo rule = new Foo();
        Foo ruleBean = new Foo();
        rule.setName("foo");
        rule.setTargets(1);

        # the field you need to check, not necessary to check all attributes.
        List<String> fields = Arrays.asList("Name", "Script", "Targets");
        for (String field : fields) {
            try {
                Object temp = rule.getClass().getMethod("get"+field).invoke(rule);
                if (temp != null) {
                    ruleBean.getClass().getMethod("set"+field,temp.getClass()).invoke(ruleBean,temp);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }

        System.out.println(ruleBean.getName());
        System.out.println(ruleBean.getScript());
        System.out.println(ruleBean.getTargets());
    }
}


Foo.java

public class Foo {
    private String name;
    private String script;
    private Integer targets;

    public void setName(String s) {
        this.name = s;
    }
    public String getName() {
        return this.name;
    }

    public void setScript(String s) {
        this.script = s;
    }
    public String getScript() {
        return this.script;
    }

    public void setTargets(Integer s) {
        this.targets = s;
    }
    public Integer getTargets() {
        return this.targets;
    }

}

result:

foo
null
1
Related