[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Using AspectJ Aspect with CDI and dependency injection

Hi Eric,

90% of everything I do around Java programming or testing with Spock &
Geb I do with IntelliJ IDEA because all around it is the superior IDE.
But whenever I use AspectJ I usually do it with Eclipse because AJ is an
Eclipse project and so are AJDT, i.e. they are maintained better than
IDEA's AJ support which existed early on but the progress of which
suddenly stalled years ago. Old tickets never get implemented, AJ
support in IDEA is basically orphaned from my perspective. This is kinda
unfortunate because there is not so much missing, but JetBrains does not
allocate any resources there.

Anyway, from my experience I can say that both IDEA and Eclipse can
handle Maven projects fairly well, but funnily imported AspectJ Maven
projects work better in IDEA than in Eclipse because the overall Maven
support in IDEA is better. In Eclipse there are always some small issues
about lifecycle bindings I don't even want to know about as a user, but
I have to tweak it anyway, always not being 100% sure what I am doing.

As for my POMs, what they exactly look like depends on the setup. Is it
a one-module project? Do I want to use an aspect library from a separate
JAR? Is it compile-time or post-compile-time (binary) weaving? I posted
several samples over the years on StackOverflow, just search with my
user ID and the corresponding tags:

user:1082681 [aspectj] [maven]

The resulting URL would be:
https://stackoverflow.com/search?q=user%3A1082681+%5Baspectj%5D+%5Bmaven%5D

You can e.g. copy & paste from here (I just picked the first ones I
found in the above search result):

Single module project:
https://stackoverflow.com/a/25480409/1082681

Multi-module project with Aspect library:
https://stackoverflow.com/a/33855519/1082681

Just update the properties to AspectJ Maven plugin version 1.11 and to
AspectJ version 1.8.13 or 1.9.1 and you are all set.

Feel free to ask follow-up questions.

Cheers
-- 
Alexander Kriegisch
https://scrum-master.de


Eric B schrieb am 14.07.2018 02:22:

> If you can share your maven config to get the two compilers to work
> together nicely, that would be appreciated. Which IDE do you use? I
> recently switched to IntelliJ to be more compatible with my team, and
> it seems that it doesn't handle maven AJ compilation/weaving as
> nicely/transparently as Eclipse does. I tend to need to either launch
> the maven compile process by hand, or manually activate a post-build
> trigger on the maven-compile process. Eclipse, on the other hand,
> "magically" uses the ajc compiler instead of javac on a AspectJ
> faceted project without any issues/worries.
> 
> 
> I think I will need to revert to a factory based approach for the
> Aspect, whereby I will manually "inject" the required dependencies. I
> can at least use DI to inject dependencies into my factory, and then
> use the aspectOf() method to retrieve the Aspect and inject the
> appropriate fields/members there. It's the closest that I've been able
> to figure out. Unfortunately, I'm not able to retrieve everything from
> the joinpoint context, as I need to access some services that aren't
> used by the target class, and hence, aren't available through the JP.
> However, they are in the application context - hence the desire to
> have CDI inject the service into the Aspect for me.
> 
> 
> On Fri, Jul 13, 2018 at 1:04 AM Alexander Kriegisch wrote:
> 
>> I forgot to mention: Or can you get the dependencies your aspect
>> needs to work with from the joinpoint context via args(), this(),
>> target(), @annotation(), @target() etc.? This is what aspects usually
>> do. What kind of dependency other than the ones available from the
>> joinpoint context does the aspect need? And if it does need them,
>> why? Maybe you should refactor your aspect in that case. A
>> cross-cutting concern is usually be implemented with AOP because you
>> want to avoid tangling, not because you want to increase it.
>> 
>> 
>> Alexander Kriegisch schrieb am 13.07.2018 11:56:
>> 
>>> I usually do not disable Maven Compiler, I just configure it and
>>> AspectJ Maven in a way so as not to interfere with each other. Let
>>> me know if you are interested. But of course disabling Maven
>>> Compiler completely is a safe bet for that kind of problem, too.
>>> 
>>> As for your JEE/CDI problem: I am not a framework guy, I neither use
>>> Spring nor JEE, mostly because programming is not my job (used to be
>>> 20 years ago) and I just do it for fun. So maybe I am not the most
>>> qualified person to answer that. But generally speaking, you already
>>> kinda nailed it: Aspect lifecycle is handled by AJ, not via CDI. And
>>> frankly, I even think it shouldn't. We have a bit of a hen and egg
>>> problem here, if you think about it. AOP is meant to implement
>>> cross-cutting concerns, i.e. AOP needs "to be there first",
>>> especially when thinking about AspectJ doing bytecode weaving during
>>> class-loading, which is what you essentially do with LTW. So the
>>> weaving agent needs to be up and running before any of the
>>> application classes are even loaded into the JVM. Spring AOP is a
>>> different kind of beast because it uses delegation via dynamic
>>> proxies, not bytecode weaving. Furthermore, a Spring aspect is also
>>> a Spring component and only works for other Spring components, i.e.
>>> there is a strong dependency on the surrounding framework.
>>> 
>>> Maybe there is a way to get CDI working for aspects, but if there
>>> is, then only in some kind of "lazy instantiation" scenario, i.e.
>>> aspect weaving and class-loading is finished but DI into the aspect
>>> is only done later, e.g. when the aspect first accesses the injected
>>> object. To me this feels a little creepy though because suddenly the
>>> aspect would depend on the application and you could run into issues
>>> with aspects that ought to be kicking in early, such as logging or
>>> tracing. For aspects which are designed to only be used after the
>>> application is already wired up, you might have a chance. Someone
>>> else might be able to help you there. Does it work for you if you
>>> ask some kind of factory to provide you with a dependency? I know,
>>> it is not DI and more difficult to test, but you can still provide
>>> setters for the aspect's dependencies and then easily unit-test the
>>> aspect, injecting mocks.
>>> 
>>> 
>>> Eric B schrieb am 13.07.2018 10:32:
>>> 
>>>> Thanks for pointing that out. I can't believe I missed it. I had
>>>> intentionally tried to disable the maven compiler using
>>>> -Dmaven.main.skip=true, but I must have forgotten to use it for
>>>> this attempt.
>>>> 
>>>> I'm still perturbed as to how to get CDI to inject an AJ aspect
>>>> though. I cannot seem to find the magic solution (if one exists) to
>>>> configure the project such that I can get injections into my Aspect
>>>> bean. I'm using LTW and realize that the lifecycle of the aspect is
>>>> done via AJ and not through CDI. Nonetheless, in Spring, there is
>>>> always the SpringBeanAutowiringSupport utility that you can use to
>>>> wire an existing bean. Do you know if there is anything equivalent
>>>> in JEE to accomplish DI in an Aspect?
>>>> 
>>>> 
>>>> On Thu, Jul 12, 2018 at 9:38 PM Alexander Kriegisch wrote:
>>>> 
>>>>> The error comes from Maven Compiler, not from AspectJ Maven, i.e.
>>>>> Javac tries to compile something you probably want to be compiled
>>>>> by Ajc. Without seeing your POM I cannot say more, but the
>>>>> configuration with regard to those two plugins is probably the
>>>>> root cause of your problem.
>>>>> 
>>>>> 
>>>>> Eric B schrieb am 12.07.2018 23:22:
>>>>> 
>>>>>> I'm trying to figure out a way to inject dependencies into an
>>>>>> Aspect that is running under Wildfly 10 with CDI.
>>>>>> 
>>>>>> From what I can tell, by definition, I need to have a no-argument
>>>>>> constructor in the Aspect, which already implies AJ cannot
>>>>>> support the constructor injection pattern. Please correct me if I
>>>>>> am mistaken.
>>>>>> 
>>>>>> Secondly, once I have fields annotated with @Inject, I'm not sure
>>>>>> how to tell CDI to inject beans into my aspect. If I remember
>>>>>> correctly, in Spring, I can use the .aspectOf() as a
>>>>>> factory-method to declare the bean to Spring. This was
>>>>>> accomplished using XML definitions.
>>>>>> 
>>>>>> However, when I try to do something similar in CDI, using
>>>>>> @Produces, it does not seem to be work; the compiler throws
>>>>>> errors that the .aspectOf() method in my aspect does not exist.
>>>>>> 
>>>>>> public classUserAccountAspectFactory {
>>>>>> 
>>>>>> @Produces publicUserAccountStatusAspect
>>>>>> injectUserAccountStatusAspectDependencies()throwsNoSuchMethodException,
>>>>>> InvocationTargetException, IllegalAccessException {
>>>>>> 
>>>>>> returnUserAccountStatusAspect.aspectOf(); } }
>>>>>> 
>>>>>> [ERROR] Failed to execute goal
>>>>>> org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
>>>>>> (default-compile) on project adams-aspects: Compilation failure
>>>>>> 
>>>>>> 
>>>>>> [ERROR]
>>>>>> /C:/dev/Projects/develop/aspects/src/main/java/model/interceptor/UserAccountAspectFactory.java:[11,39]
>>>>>> cannot find symbol
>>>>>> 
>>>>>> [ERROR] symbol: method aspectOf()
>>>>>> 
>>>>>> [ERROR] location: class model.interceptor.UserAccountStatusAspect
>>>>>> 
>>>>>> Which surprises me b/c when I look at the
>>>>>> UserAccountStatusAspect.class file, I see that ajc has added the
>>>>>> .aspectOf() method to the compiled class.
>>>>>> 
>>>>>> I'm obviously doing something wrong, but not quite sure what. Can
>>>>>> anyone point me in the right direction please?