Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java reflection loss of annotation information

I'm having an issue with reflection. I decided I wanted to create a SQL Query Generator using reflection. I created my own annotations to determine what classes can be used, what attributes can be stored ect. The code works as I want it to, however the issue lyes in using this project as a dependency in others.

I have another project using OJDBC and im trying to use my library to generate the Queries based on class. However when I pass a class from my ojdbc project there is a loss of all class information, the class is appearing as java.lang.Class and even the annotaion information is lost. Does anyone know why this is happening?

private static <T> void appendTableName(Class<T> cls) throws NotStorableException {
    Storable storable = cls.getAnnotation(Storable.class);
    String tableName = null;
    if (storable != null) {
        if ((tableName = storable.tableName()).isEmpty())
            tableName = cls.getSimpleName();
    } else {    
        throw new NotStorableException(
                "The class you are trying to persist must declare the Storable annotaion");
    }
    createStatement.append(tableName.toUpperCase());
}

The cls.getAnnotation(Storable.class) is losing the information when the following class is passed to it

package com.fdm.ojdbc;

import com.fdm.QueryBuilder.annotations.PrimaryKey;
import com.fdm.QueryBuilder.annotations.Storable;

@Storable(tableName="ANIMALS")
public class Animal {

@PrimaryKey
private String name;

public String getName() {
    return name;
}

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

}

The animal class is in the ojdbc project and the appendTableName method belongs to my query builder. I have tried generating the querybuilder project into a jar and use maven install to add it to my repository and still no luck.

Thanks for the quick reply, however this isn't problem as the Annotation I created has Retention set to Runtime see below.

package com.fdm.QueryBuilder.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(value = { ElementType.TYPE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Storable {
    public String tableName() default "";
}

My annotation is set to runtime yet the class information is still being lost.

like image 404
billy.mccarthy Avatar asked May 19 '15 16:05

billy.mccarthy


1 Answers

When you want an annotation which is usable at runtime you need to add an annotation to it.

@Retention(RetentionPolicy.RUNTIME)
public @interface Storable {

Without this, the annotation is not visible at runtime.

For more information, here is the source for this annotation.

/**
 * Indicates how long annotations with the annotated type are to
 * be retained.  If no Retention annotation is present on
 * an annotation type declaration, the retention policy defaults to
 * {@code RetentionPolicy.CLASS}.
 *
 * <p>A Retention meta-annotation has effect only if the
 * meta-annotated type is used directly for annotation.  It has no
 * effect if the meta-annotated type is used as a member type in
 * another annotation type.
 *
 * @author  Joshua Bloch
 * @since 1.5
 * @jls 9.6.3.2 @Retention
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
like image 153
Peter Lawrey Avatar answered Oct 21 '22 05:10

Peter Lawrey