jeudi 26 juillet 2018

How to avoid NoSuchMethodException with primitives in Java

I'm working on legacy project and I've trapped into situation when I have to make additional init stuff with action object. In this code AdmAction is a basic interface and inside method I could have any of it's implementation. Some of implementations require additional properties must be initialized with values from utilParams.

private void initActionParams(AdmAction action, Map<String, Object> utilParams) {
    if (utilParams == null) {
      return;
    }
    utilParams.forEach((paramName, value) -> {
        try {
          Method setterMethod = action.getClass().getMethod(setterFor(paramName), value.getClass());
          setterMethod.invoke(action, value);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
          log.error(e.getMessage(), e);
          throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
        }
   });
}

utilParams looks like "serviceId": 10 of "ticketId": "8a30f5a7-809c-4551-8833-c2a60e4c6fd9". Code works fine when value is an Object type (String, Integer etc.) and when setter method of AdmAction implementation consumes the same. But there's one problem when I've got for example Integer type in utilParams and setter method in action which consumes int. Of course code throws NoSuchMethodException

Example:
Action impl:

public class Foo implements AdmAction {
    // ...
    public void setServiceId(int serviceId) {
        this.serviceId = serviceId;
    }
}

Causes an exception.

I've tried to improve code with method search:

private void initActionParams(AdmAction action, Map<String, Object> utilParams) {
    if (utilParams == null) {
      return;
    }
    utilParams.forEach((paramName, value) -> {
        try {
            Method setterMethod = Arrays.stream(action.getClass().getDeclaredMethods())
                .filter((Method method) -> method.getName().equals(setterFor(paramName)))
                .findFirst()
                .orElseThrow(NoSuchMethodException::new);
            setterMethod.invoke(action, value);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            log.error(e.getMessage(), e);
            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
        }
    });

I guess it's a little bit brute for actual case. Can anybody help me find the way to write better and more aesthetic code?





Aucun commentaire:

Enregistrer un commentaire