AspectJ ITDs: implementing a generic interface - java

I want my class to implement an interface, but I want to provide the implementation of the methods using ITD in an aspect. Is this possible?
Interface:
public interface CloningService<T> {
public T clone(T object);
}
Default implementation:
public class DefaultCloningServiceImpl implements CloningService<T> {
public T clone(T object) {
// implementation of the clone method
}
}
Specific implementation:
public class PersonService implements CloningService<Person> {
// no code (!)
}
The class PersonService would declare that it implements the CloningService interface, but the actual implementation of the methods would be provided in DefaultCloningServiceImpl and an aspect would introduce them to PersonService.
I followed the example on Eclipse.com and I tried to use #DeclareParents to achieve the above functionality. However, I was getting a compiler error from AspectJ, which had to do with generics. It's as if the #DeclareParents annotation did not expect the generics to be used...
Thank you.

I'd recommend that you use code style aspectj to solve this rather than annotation style.
This could be done simply by having an aspect like this:
aspect CloningServiceAspect {
declare parents : PersonService extends DefaultCloningServiceImpl<Object>;
}
To make this more general and attached to an annotation, you can do something like this:
aspect CloningServiceAspect {
declare parents : (#CloningService *) extends DefaultCloningServiceImpl<Object>;
}
And if you wanted to package this up into a standalone jar, just make sure to add all code that you want to weave adds this jar to its aspect path (if using compile-time weaving).

I found the solution! It involves using the #DeclareMixin annotation from AspectJ to mix the default implementation of the clone() method:
#Aspect
public class CloningServiceAspect {
#DeclareMixin(value = "(#CloningService *)")
public static CloningService<?> createImplementation() {
return new DefaultCloningServiceImpl<Object>();
}
}
And then my service is annotated with #CloningService instead of implementing the interface:
#CloningService
public class PersonService {
// no code
}

Related

Get around early binding of static methods in java

I have a AbstractBaseRepository. All my Repositories extends from this class. I created another class RepositoryFactory to create any instance of Repository. Due to early binding of static method, I am facing problem.
public abstract class AbstractBaseRepository {
public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {
throw new RuntimeException("Override and provide valid initialization");
}
...
}
public class RepositoryFactory {
public static <T extends AbstractBaseRepository> T getRepository(Class<T> cls) {
return T.getNewInstance(entityManagerFactory);
}
...
}
an example subclass
public class DeviceModelRepo extends AbstractBaseRepository {
public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {
return new DeviceModelRepo(entityManagerFactory);
}
...
}
Whenever I call getRepository() with a valid subclass of AbstractBaseRepository, runtime exception is thrown. This is due to early binding of static methods. During compile time, getNewInstance gets bound with AbstractBaseRepository rather than at runtime with actual type of the class. Any good workarounds?
My first suggestion is using Spring. It is very easy to get a list of all beans created with a certain interface.
Also, if you think of your Repository instances as a type of "plug-in" you might see how Java's ServiceLoader class can help.
Also, another approach is to use a switch statement in the factory and create the instances for each case rather than using static methods on the Repository subclasses.
Finally, I don't recommend reflection solutions but there are ways to load the class based on its name and reflectively creating a new instance.
But overriding static methods is not possible.
What I have understood by seeing your code is that you want to have different implementations of AbstractBaseRepository such as DeviceModelRepo. Then you want a factory class to create the instance of specific implementation of AbstractBaseRepository. Here the major problem is you try to overriding static methods which can never be overwritten but subclass will hide the parent implementation. Please don't use static method for overriding. You can change your implementation as given below and this issue will be resolved.
public abstract class AbstractBaseRepository {
public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Then below implementation for subclass.
public class DeviceModelRepo extends AbstractBaseRepository {
public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Now I am providing you two implementation of factory class.
One is having different method for each of implementation, such as getDeviceModelRepository().
Another solution is to use reflection and get repository instance by passing the implementation repository class.
public class RepositoryFactory {
//Solution-1, create separate method for each of repository like below
public static AbstractBaseRepository getDeviceModelRepository() {
return new DeviceModelRepo(entityManagerFactory);
}
//Solution-2, use reflection to get instance of specific implementation
//of AbstractBaseRepository
public static <T extends AbstractBaseRepository> T
getRepository(Class<T> repoClass) throws Exception{
return repoClass.getConstructor(EntityManagerFactory.class)
.newInstance(entityManagerFactory);
}
...
}
With reflection solution, you can get the repository instance as given below.
RepositoryFactory.getRepository(DeviceModelRepo.class)

How to make pointcut expressions advise methods of beans that extend classes that are defined in third-party library?

I have a Spring bean defined like this:
package org.behrang.sample;
import foo.AbstractThirdPartyClass;
#Component
public class SampleBean extends AbstractThirdPartyClass<Input, Output> {
#Override
public Optional<Output> process(Input input) {
}
}
The AbstractThirdPartyClass class is defined in a third-party library named foo.
I want to implement an advice that applies to all methods in the
org.behrang.sample package, so I have implemented something like this:
#Aspect
#Component
public class SampleAspect {
#Before("execution(public * org.behrang.sample..*.*(..))")
public void sampleBefore(JoinPoint joinPoint) {
}
}
However this is not advising SampleBean::process(Input). If I remove the extends AbstractThirdPartyClass<Input, Output>
part, then the process method is advised.
Is there an elegant way to workaround this problem? For example, I can define an interface in org.behrang.sample with one method like this:
public interface Sampler<I, O> {
public Optional<O> process(I input);
}
And make the SampleBean implement it too. But this is way too ugly and anti-DRY.
Also I have enabled AOP using #EnableAspectJAutoProxy(proxyTargetClass = true) as manu beans defined in this project are not implementing any interfaces.

Spring aspect call on custom annotation on interface method

I have this interface:
public interface FakeTemplate {
#CustomAnnotation
void foo() {
}
}
And this implementation of the interface:
#Component
public FakeImpl implements FakeTemplate {
#Override
public void foo() {
//Do Stuff
}
}
And this aspect:
#Aspect
#Component
public class CustomAspect {
#Before(value = "#annotation(com.fake.CustomAnnotation)")
public void doStuffBefore(JoinPoint joinPoint} {
}
}
I'm using spring with AspectJ enabled using: #EnableAspectJAutoProxy(proxyTargetClass = true)
My issue is that the aspect doStuffBefore method is not being called before the execution of FakeImpl's foo() method. It Does work when I put the #CustomAnnotation on FakeImpl instead of FakeTemplate, but I'd much prefer to put the annotation on FakeTemplate as it's in a separate API package and I've kind of delegated it as the place where I put all my annotations.
I'd also like to ensure that the CustomAnnotation is called on every class that implements FakeTemplate without remembering to put the annotation on all the implementation classes themselves.
Is there any way to get the advice to be called if the annotation is only on the interface class?
Annotation inheritance doesn't work for methods in java.
But you can use other pointcut expression, something like
execution(public * FakeTemplate+.foo(..))
There is sort of a workaround. In your example, you can add an extra 'default' method e.g. named fooFacade to your FakeTemplate interface, annotate that with your #CustomAnnotation, and then delegate to the 'real' foo method:
public interface FakeTemplate {
#CustomAnnotation
default void fooFacade() {
foo();
}
void foo();
}
Now whenever you call fooFacade(), execution of the pointcut on #CustomAnnotation will be triggered.

How to provide base classes to autowire in Spring?

I'd like to write some base classes that should be picked by default to autowire with Spring. Only if these classes are extended, thus a custom implementation is provided for them, I want the custom implementation to be picked up, instead of the default one.
How can I achieve it when I don't want to make my default classes abstract (as the application should be able to run without custom implementations, just by the default ones)?
The the following example: I want to provide a basic handler for any errors. But this setup would only work if I make the BaseHandler abstract, which I don't want (as in this case I would force anyone using my library to implement the class).
#MessageEndpoint
public class BaseHandler {
#ServiceActivator(inputChannel = "errorChannel")
public A_Stadisdatensatz handle(Message<MessageHandlingException> message) {
process(message.getPayload());
}
/**
* Override to supply specific processing
*/
void process(Payload payload) {
//do some default processing
}
}
#MessageEndpoint
public class CustomHandler extends BaseHandler {
#Override
void process(Payload payload) {
//custom processing
}
}
If I run it this way, CustomHandler will never be picked up.
So, is it impossible?
I supose that you are using #Autowired to inject the dependencies. In that case you could use #Primary annotation to override defaults ones, ie
#Primary
#MessageEndpoint
public class CustomHandler extends BaseHandler {
#Override
void process(Payload payload) {
//custom processing
}
}

AspectJ compiler DeclareMixin error

I'm using the #DeclareMixin provided by aspectjrt-1.6.11.
The situation is:
#Aspect
public class anAspect {
#DeclareMixin(value="#an.annotation.package.* *", interfaces = {
FirstInterface.class, SecondInterface.class, ThirdInterface.class
})
public AggregateInterface magicMethod(Object instance) {
return new AggregateInterfaceImpl(instance);
}
public interface AggregateInterface extends FirstInterface,
SecondInterface, ThirdInterface {
}
}
So when i compile via aspectj-maven-plugin-1.4, the compiler says that the factory method (magicMethod() in my case) does not return something that implements any of the interfaces implemented.
The problem came out when I've introduced the Second and Third interface in the AggregateInterfaceImpl.
Have you got any idea of the problem? Is there anything I did wrong?
Thanks.
I've resolved this issue declaring different mixins attached to different factory methods.

Categories

Resources