Stefano Cazzola
Stefano Cazzola

Reputation: 1687

How to handle generic result with AspectJ?

I have an aspect (written with aspectj syntax public aspect ....) that manipulates the result of many methods that return a Collection in order to paginate the result.

I can't (or I don't know how to) use generics in advices, so wherever I call one of the advised methods I get the warning

unchecked conversion when advice applied at shadow method-call(java.util.Collection ...), expected java.util.Collection<T> but advice uses java.util.Collection [Xlint:uncheckedAdviceConversion]

How can I get rid of this?

Stefano

-- Adding aspect code excerpt

public aspect PaginationSupportAspect extends ServiceSupportAspect {

    private static final Logger log = LoggerFactory.getLogger(PaginationSupportAspect.class);

    private pointcut paginate(Criteria criteria) : call(Collection org.jcz.persistence.Service+.*(Criteria));

    @SuppressWarnings({ "unchecked", "rawtypes" })
    Collection around(Criteria criteria, Service service) : paginate(criteria) && target(service) {
        log.trace(String.format("Executing <%s> @ <%s>", this.getClass(), thisJoinPoint.toLongString()));

        return doPaginate(proceed(criteria, service), criteria.getPagination(), service);
    }

    /**
     * 
     * @param source
     * @param criteria
     * @return
     */
    private <T extends EntitySupport> Collection<T> doPaginate(Collection<T> source, Pagination pagination, Service<T> service) {
        // IMPLEMENTATION OMITTED BECAUSE IT'S QUITE LONG

        // What it does is to create another Collection<T> that holds the pagination coordinates (page number, size, count) 
        // and only the elements of the requested page
    }

}

Usage example

Collection<MyEntity> entities = myEntityService.findAll(criteria);

That's where I get the warning

Upvotes: 0

Views: 838

Answers (1)

kriegaex
kriegaex

Reputation: 67297

The bad news: I do not know how to avoid the warning because I am not so proficient in Java generics, specifically not in connection with AspectJ because there not everything you might expect is syntactically allowed, e.g. binding the target() to a parametrised type (because of type erasure limitations).

Probably you are having the same problem as this one on the AspectJ mailing list.

The good news: I finally managed to reproduce your problem with a minimal code sample, using a lot of dummy classes, doing some educated guesses about how you use them in your application:

Dummy/helper classes/aspects:

package org.jcz.persistence;
public class EntitySupport {}
package org.jcz.persistence;
public class MyEntity {}
package org.jcz.persistence;
public class Pagination {}
package org.jcz.persistence;

public class Criteria {
    public Pagination getPagination() {
        return new Pagination();
    }
}
package org.jcz.persistence;

import java.util.ArrayList;
import java.util.Collection;

public class Service<T> {
    public Collection<T> findAll(Criteria criteria) {
        return new ArrayList<T>();
    }
}
package org.jcz.persistence;
public abstract aspect ServiceSupportAspect {}

Your aspect, slightly changed:

package org.jcz.persistence;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.log4j.Logger;

public aspect PaginationSupportAspect extends ServiceSupportAspect {
    private static final Logger log = Logger.getLogger(PaginationSupportAspect.class);

    private pointcut paginate(Criteria criteria) :
        call(Collection org.jcz.persistence.Service+.*(Criteria)) && args(criteria);

    @SuppressWarnings({ "unchecked", "rawtypes" })
    Collection around(Criteria criteria, Service service) : paginate(criteria) && target(service) {
        log.trace(String.format("Executing <%s> @ <%s>", this.getClass(), thisJoinPoint.toLongString()));
        return doPaginate(proceed(criteria, service), criteria.getPagination(), service);
    }

    private <T extends EntitySupport> Collection<T> doPaginate(
            Collection<T> source, Pagination pagination, Service<T> service)
    {
        System.out.println("doPaginate");
        return new ArrayList<T>();
    }
}

And now a little driver application reproducing the Xlint warning:

import java.util.Collection;

import org.jcz.persistence.Criteria;
import org.jcz.persistence.MyEntity;
import org.jcz.persistence.Service;

public class Application {
    public static void main(String[] args) {
        Service<MyEntity> myEntityService = new Service<MyEntity>();
        Criteria criteria = new Criteria();
        Collection<MyEntity> entities = myEntityService.findAll(criteria);
        System.out.println("Found entities: " + entities);
    }
}

Maybe someone else can make something of it which I cannot. The best I could do was reproduce it. I will try to point Andy Clement to this post. Good luck!

Upvotes: 1

Related Questions