How to iterate an attribute with Java Reflection?

Asked

Viewed 335 times

4

In the method below, I use Reflection to set attributes from one class to another, based on mapping via Annotation. How do I map an attribute of a class that is an attribute of another?

For example, when using the following Annotation: @Origin(field="modeloCarro.nome") I want to access the attribute name attribute modeloCarro.

/*
 * Method should be implemented for copying non homonyms fields.
 * 
 * @param T dto is the object that will receive the values.
 * 
 * @param Object obj is the original object
 */
public void toDTOMappedFields(Object dto, Object obj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    Class<?> classOriginal = (Class<?>) obj.getClass();
    Class<?> classDTO = (Class<?>) dto.getClass();

    for (Field fieldDTO : classDTO.getDeclaredFields()) {
        if (fieldDTO.isAnnotationPresent(Origin.class)) {
            Origin origin = fieldDTO.getAnnotation(Origin.class);
            Field fieldOrigin = classOriginal.getDeclaredField(origin.field());
            fieldOrigin.setAccessible(true);
            fieldDTO.setAccessible(true);
            fieldDTO.set(dto, fieldOrigin.get(obj));
        }
    }
}

2 answers

1

I think what you want is this, or else something very similar:

/*
 * Method should be implemented for copying non homonyms fields.
 * 
 * @param T dto is the object that will receive the values.
 * 
 * @param Object obj is the original object
 */
public void toDTOMappedFields(Object dto, Object obj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    for (Field fieldDTO : dto.getClass().getDeclaredFields()) {
        if (fieldDTO.isAnnotationPresent(Origin.class)) {
            Origin origin = fieldDTO.getAnnotation(Origin.class);
            String attributeRef = origin.field();
            String[] parts = attributeRef.split("\\.");
            Object ref = obj;
            for (String p : parts) {
                Field fieldOrigin = obj.getClass().getDeclaredField(p);
                fieldOrigin.setAccessible(true);
                ref = fieldOrigin.get(ref);
            }
            fieldDTO.setAccessible(true);
            fieldDTO.set(dto, ref);
        }
    }
}

Obviously, it is still necessary to treat a lot of possible exceptions if some field does not exist (NoSuchFieldException), or if, when crossing the references, you have a null midway (NullPointerException), or you have problems with security permissions in Reflection (SecurityException), or data access problems of wrong types (IllegalArgumentException). The IllegalAccessException should never occur.

  • Thank you for the answer, it is very close to what I need, once I have the code with the solution I will post.

0


Being very direct and without reinventing the wheel. Take a look at the Apache Commons Beanutils.

There is even a method Beanutils.copyProperties who does exactly what you need.

Keep in mind that some exception treatment will be required.

I hope I’ve helped.

  • Thanks for the tip. I know and am using Beanutils in my solution, but I need something more. The copyProperties method copies attributes with the same name. I implemented a method to copy values via Annotation, now I need to map attributes within other attributes as per the question.

  • 1

    Take a look at the Beantopropertyvaluetransformer class, it should help =).

  • From what I saw is really what I need, I will see if the behavior of the method suits me, if yes, I will stop reinventing wheel haha. Thank you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.