reox
reox

Reputation: 5217

Annotate Methods to choose them later

Is it somehow possible to annotate a Java Method in that way that i later can give another Method a Field Identifier or something like that, so that this Method can call the right one?

I know that normally you would do this with interfaces, but in my case this would be a immense count of interfaces... I need to use this in Entity Classes for my Database (and i'm not allowed to use a ORM Mapper)

For example: I have the Entity

public class Account{
    private String username;
    private String password;
    private String name;
    private String mail;


    public void setUserName(String username){
        this.username = username;
    }

    public String getUserName(){
        return username;
    }

    [all other getter/Setter...]
}

Now i want to tell a Method that it need to validate a Field, for example the username field.

The Method that does should look like this:

public void validateField(XXX Field, Entity entity) throws ValidationFailedException, EmptyFieldException;

where XXX is somehow the FieldIdentifier.

Is that in any way possible in Java?

My only guess it that i Use public static final ìnt stuff in there to give every field a Method or so...

Upvotes: 1

Views: 123

Answers (4)

Nikola Yovchev
Nikola Yovchev

Reputation: 10216

What do you use? I don't see any annotations from which I can guess your framework. If you use Hibernate, you can use something like @NotNull or something else, or even do your custom validation: This is how you would go with your example:

public class Account{

    @NotNull(message="This field should not be null")
    private String username;
    @NotBlank(message="This string should not be empty or null")
    private String password;
    private String name;
    private String mail;


    public void setUserName(String username){
        this.username = username;
    }

    public String getUserName(){
        return username;
    }

    [all other getter/Setter...]
}

http://silentwalker.wordpress.com/2009/04/07/custom-validation-in-hibernate/

You can also create your own annotations without using any framework and use them @prepersist or whatever. Basically the sky is the limit.

P.S Since you don't want to use any non internal code, here is how you can approach:

First, you can define an annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotNull{
    public String message() default "";
}

Then, before persisting the class, you would inspect its fields:

So, you have something like this:

Field[] classFields = yourObjectPrePersist.getClass().getDeclaredFields();
for (int i = 0; i < classFields.length; i++) {
        classFields[i].setAccessible(true);//take notice that if you use a SecurityManager, you should work around it
        if (classFields[i].getAnnotation(NotNull.class) != null) {
            Object value = classFields[i].get(yourObjectPrePersist);
            //here check if value is null or not and then return the message
            if (value == null) {
                throw new SomeException(((NotNull) classFields[i].getAnnotation(NotNull.class)).message());
            }
        }
    }

Upvotes: 3

jjs
jjs

Reputation: 21

You could use a generic interface

public interface Field {
    public String getValue();
}

and call your validate method with anonymouse classes

validator.validate(new Field() {
    return account.getUsername()
});

(or with old java)

validator.validate(new Field() {
    public String getValue() {
        return account.getUsername();
    }
});

Otherwise what about using java.lang.Methode directly?

P.S.: Sorry for the quote, stackoverflow did not let me post my text directly, said it was not formatted correctly :-/

Upvotes: 0

ruakh
ruakh

Reputation: 183280

You can use reflection for this; see the documentation for java.lang.reflect.Field. The caller can pass in the field-name as a string, and validateField can use something like Field f = entity.getClass().getField(fieldName).

But this is not usually a great idea . . . reflection is awesome, but it requires a lot of boilerplate code, and you pay a high price in maintainability. (You also pay a performance penalty, though in my experience the maintainability penalty is much worse than the performance penalty.) Personally I use reflection a lot in test code (it can help in writing extremely comprehensive tests), and I make use of frameworks like Spring and Hibernate that depend on reflection, but I avoid it in my own production code.

Upvotes: 0

John Haager
John Haager

Reputation: 2115

Annotations don't seem like the right solution to the problem you describe.

One possibility would be to pass in the name of the field that needs to be validated, then used the java.beans.BeanInfo class to access the field values of the Entity. This will allow you to access arbitrary attributes of an object without having to deal with all of the complexity of reflection.

Upvotes: 0

Related Questions