mardi 27 février 2018

spring ReflectionUtils private field

I have a problem with java reflection. I use org.springframework.util.ReflectionUtils on my User class to "trim" white spaces from String attributes (let's not question my good practices now :).

The problem is, the attributes being private, that the reflection works in my DataLoader class but throws an exception when used in rest controller, which I think should be the right behavior. How come it works in the first example?

java.lang.IllegalStateException: Not allowed to access field 'username': java.lang.IllegalAccessException: Class TrimListener can not access a member of class User with modifiers "private"

User class

@Entity
@EntityListeners(TrimListener.class)
@Getter @Setter @NoArgsConstructor @AllArgsConstructor
public class User extends DatabaseObject {
    private String username;
}

TrimListener class

public class TrimListener<T extends DatabaseObject> {
    @PreUpdate
    @PrePersist
    public void trim (T object) {
        ReflectionUtils.doWithFields(object.getClass(), field -> {
            if(field.get(object) != null) {
                if(!field.get(object).toString().equals(field.get(object).toString().trim())) {
                    field.set(object, field.get(object).toString().trim());
            }
        }
    }, new TrimmableFieldFilter());
}

private class TrimmableFieldFilter implements ReflectionUtils.FieldFilter {
    @Override
    public boolean matches(Field field) {
        return (field.getType().equals(String.class));
    }       
}

DataLoader singleton, used to load sample data into DB. Here, the TrimmerListener works as it should, trimming username.

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class DataLoader {
    @PostConstruct
    public void loadData() {
        User user = new User("vladko ");
        userRepo.save(user);
    }
}

Rest controller, which should just persist user. This version causes exception to be thrown, because accessing the private field of User through org.springframework.util.ReflectionUtils

@RestController
@RequestMapping("/user")
public class UserController extends DatabaseObjectController<User> {
    @PostMapping("/create")
    public ResponseEntity<UserDTO> createUser(@RequestBody(required = true) User user) {
        userRepo.save(user);
        return ResponseEntity.ok().body(user.toDTO());
    }
}

Thank you.





Aucun commentaire:

Enregistrer un commentaire