Vojtěch
Vojtěch

Reputation: 12416

Inheritance in annotation parameters

I am trying to inherit following parameter in a java interface (an example from Spring Data JPA, but the question is generally about parameters to annotations):

public interface ItemRepository<T extends Item> extends BaseRepository<T> {

    public final String type = null;



    @Query("select distinct i from " + type + " i " +
            "join i.tags t " +
            "join fetch i.locale where t = ?1")
    public List<T> findByTag(Tag t);
}

so that in inherited interfaces I could have just:

public interface EventRepository extends ItemRepository<Event> {

    public final static String type = "Event";
}

But unfortunately the string value of variable "type" is associated to the variable too late, so when the annotation is created, the value is still null. Can I force the compiler to associate the variable from the child interface?

Thanks

Upvotes: 2

Views: 1937

Answers (3)

Vojtěch
Vojtěch

Reputation: 12416

In the end, I was so unhappy about the behaviour and inflexibility, so that I wrote myself a small tool. An example of using is here:

https://github.com/knyttl/Maite/wiki/Maite-Persistence

There are two children classes and the parent class which define the functionality. But the trick is in a fluent interface of building the query. What do you think?

Upvotes: 0

m0skit0
m0skit0

Reputation: 25863

I'm no Java expert, but I don't think you can do so. Parent classes have no knowledge about children. However you can do something like:

public interface ItemRepository<T extends Item> extends BaseRepository<T> {

    public final String type = null;

    public static final String QUERY_PART1 = "select distinct i from ";
    public static final String QUERY_PART2 = " i " + 
            "join i.tags t " +
            "join fetch i.locale where t = ?1";
    public List<T> findByTag(Tag t);
}  

public interface EventRepository extends ItemRepository<Event> {

    public final static String type = "Event";

     @Query(QUERY_PART1 + type + QUERY_PART2)
}

Upvotes: 1

Luke Woodward
Luke Woodward

Reputation: 64949

In short, no. You can't force the compiler to 'associate the variable from the child interface'.

The Java compiler needs to be able to determine all annotation values at compile time. It needs to write out into the class file for ItemRepository a constant value to put in the @Query annotation. What constant value would you imagine this would be for your code?

As it happens, the compiler can determine from your code a value for this annotation at compile time. However, it's not exactly the value you want. (I am assuming that you've accidentally omitted the static modifier from the field type in ItemRepository - I believe your code wouldn't compile otherwise. It also wouldn't compile if you replaced your type field with a getType() method.)

Your code looks like it can determine at compile time the annotation values for the subinterfaces. The problem is that it's not possible to determine at compile time the annotation value for the superinterface ItemRepository.

Upvotes: 1

Related Questions