Thanks Marius!
That sums it up pretty well. My main concern is not _that_ we (OWB + Weld) currently work
that way, but that this behaviour is not really explicitly stated.
I can well live with the behaviour because there are ways to work around it. But those
ways should get clearly documented, otherwise we would confuse users pretty heavily.
For example:
public class MyService {
private @Inject MyService self;
@Secured(role=Admin)
public doA(){..}
@Secured(role=User)
public doU(){
self.doA();
}
}
txs and LieGrue,
strub
--- On Mon, 5/17/10, Marius Bogoevici <marius.bogoevici(a)gmail.com> wrote:
From: Marius Bogoevici <marius.bogoevici(a)gmail.com>
Subject: Re: [weld-dev] interceptors expected to be implemented via proxying or via
subclassing?
To: "Kenneth Saks" <ken.saks(a)oracle.com>
Cc: "Pete Muir" <pmuir(a)redhat.com>, "Mark Struberg"
<struberg(a)yahoo.de>, "Kenneth Saks" <Kenneth.Saks(a)sun.com>,
"Weld-Dev List" <weld-dev(a)lists.jboss.org>
Date: Monday, May 17, 2010, 4:18 PM
Well ... I'm not considering
interception of calls to 'this' an
ideological issue, so I think the discussion is still open,
but I want
to add a few more elements to the discussion:
Not only EJBs behave in this way (calls to "this" are not
intercepted),
but this is, for example, the case for Spring beans as well
(notably,
even when using subclassing via CGLib). The only case when
Spring beans
behave differently (and apply aspects on calls to "this")
is when
applying AspectJ load-time-weaving (which is a completely
different kind
of beast altogether).
Of course that there is room for treating JSR-299 and EJBs
differently
wrt interception/decoration. The main question is whether
we want to go
that way or not. Now, there are plenty of cases when the
invocation on
an otherwise intercepted method will not be
intercepted/decorated, like
for example:
public class SelfIntercepting {
void method A() {
}
void method B() {
}
@AroundInvoke
public void
aroundInvoke(InvocationContext ctx) {
((SelfIntercepting)
ctx.getTarget()).methodA();
}
}
In this case a call to methodB does not go twice through
methodA() - we
know that getTarget() returns a non-intercepted instance
(it's the
spec). However, if we had this.methodA(), would be expect
that to be
intercepted?
or, for example, if a decorator invokes a different method
(B) on a
delegate than the one it decorates (A), we do not apply the
whole
decorator chain on the new invocation, we just start at the
next
delegate. But, if the method (B) on the target class had an
interceptor,
will we expect it to be intercepted as well? Well ...
I would be all for doing things as Mark says, as I
recognize a lot of
situations where that is useful and I understand some of
the confusion,
however, my considerations are that the price to be paid in
inconsistency and need to clarify things on a case-per-case
basis
overweigh by far the benefits of a clear-cut explanation,
albeit not
satisfactory in all cases. I'd rather simply say: these are
managed
objects, therefore only contextual references are
intercepted/decorated.
There is a boundary that the container sets and we sort of
have to live
with that.
Perhaps we could find a way to do something similar to what
EJB does,
i.e. ala
@Inject @SelfDelegate SomeClasss contextualThis;
I have to say it - this will not win an aesthetics contest,
but I find
it overall cleaner than dealing with the whole mess of
"when is the
method intercepted, when is it not".
On 10-05-17 9:19 AM, Kenneth Saks wrote:
> On May 17, 2010, at 5:45 AM, Pete Muir wrote:
>
>
>> Hi Ken,
>>
>> Could you tell us where the EJB spec(s) says that
you only don't have to intercept references to this?
>>
> Hi Pete,
>
> An EJB invocation is by definition an invocation on an
EJB reference object. That's the only way to get the
additional services (CMT, method authorization,
special exception handling, interceptors, etc.) offered by
the container. The caller never holds a direct
reference to a bean instance.
>
> The case where code within a bean class method makes a
direct Java invocation of another method in the bean class
using "this" is just a plain Java SE method
invocation. There's no container interposition
involved. SessionContext.getBusinessObject()
was defined in part to allow one business method to make a
1st class EJB invocation on its own bean.
>
> --ken
>
>
>> Thanks!
>>
>> On 16 May 2010, at 09:36, Mark Struberg wrote:
>>
>>
>>> Hoi!
>>>
>>> Sorry, only came back yesterday night, so I
had no time to answere Marius' post before.
>>>
>>> Actually I don't really know if I should agree
or not.
>>>
>>> I would not really argue with the EJB spec,
because 299 and EJB are still different. For example in the
EJB spec Interceptors doesn't need to be Serializable
whereas in 299 they certainly do for passivatable scopes.
>>>
>>> Also, EJB-3.1 is coming from the EJB-2 mindset
where you really have separated remotes and stubs and many
people are _used_ that only remote calles get intercepted.
But I actually didn't find that backed in the EJB-3.1 spec
(4.3.12), any? Imo the spec does NOT say that interception
only happens if business methods get invoked from external!
It's only that _old_ EJB users got _used_ to that
behaviour.
>>>
>>> Let's make a small example:
>>>
>>> public class MyService() {
>>>
>>> @Secured(role=Admin)
>>> public void doThingA() {
>>> }
>>>
>>> @Secured(role=User)
>>> public void doThingU() {
>>> ...
>>> if (veryRareCase) {
>>> doThingA()
>>> }
>>> }
>>>
>>> }
>>>
>>> Clearly we would allow to call doThingA
without checking for admin rights. I don't like to split my
classes depending on the interceptors I'd like to apply.
That sounds _really_ dumb. Even more if you look at
interceptors which get applied without annotating the
classes in the code but from external like e.g. @Trace,
@Statistics, etc.
>>>
>>> This also happens if you have services where
not all methods share must be e.g. @Transactional or even
worse, use @Transactional with different payload.
>>>
>>> WE know WHY this behaves that way, but for 99%
of all users, this will get reported as bug (as seen on the
OpenEJB list lot of times).
>>>
>>> I'm sure we can do better!
>>>
>>> LieGrue,
>>> strub
>>>
>>>
>>> --- On Wed, 5/12/10, Pete Muir<pmuir(a)redhat.com>
wrote:
>>>
>>>
>>>> From: Pete Muir<pmuir(a)redhat.com>
>>>> Subject: Re: [weld-dev] interceptors
expected to be implemented via proxying or via subclassing?
>>>> To: "Marius Bogoevici"<marius.bogoevici(a)gmail.com>
>>>> Cc: "Mark Struberg"<struberg(a)yahoo.de>,
weld-dev(a)lists.jboss.org
>>>> Date: Wednesday, May 12, 2010, 1:46 PM
>>>> Agreed.
>>>>
>>>> On 11 May 2010, at 10:31, Marius Bogoevici
wrote:
>>>>
>>>>
>>>>> Mark,
>>>>>
>>>>> I asked a similar question
here:
>>>>>
http://lists.jboss.org/pipermail/weld-dev/2010-April/002485.html
>>>>>
>>>>> Gurkan answered here:
>>>>>
http://lists.jboss.org/pipermail/weld-dev/2010-April/002490.html
>>>>>
>>>>> So based on what I think, and also on
my understanding
>>>>>
>>>> of what Gurkan
>>>>
>>>>> says: one should not expect that
invocations to 'this'
>>>>>
>>>> are
>>>>
>>>>> intercepted/decorated - that doesn't
happen in EJB and
>>>>>
>>>> it is not
>>>>
>>>>> expected to happen for decorators.
>>>>>
>>>>> Marius
>>>>>
>>>>> On 10-05-11 2:24 AM, Mark Struberg
wrote:
>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> There is a subtle difference
between implementing
>>>>>>
>>>> interceptors via proxy or via subclasses.
>>>>
>>>>>> I have the following service which
imports data
>>>>>>
>>>> from a legacy system into my db. Since
commits are very
>>>> performance intense, they should get
imported in packages of
>>>> 100. So I'll get 100 'Employees' from my
legacy system and
>>>> then call a @Transactional method to store
them in my own
>>>> database.
>>>>
>>>>>> public void ImportService() {
>>>>>> public void
importEmployee() {
>>>>>>
>>>>>>
>>>>
List<LegacyEmployee> les;
>>>>
>>>>>> while ((les =
>>>>>>
>>>> getNext100EmployeesFromLegacy()) != nul)
{
>>>>
>>>>>>
>>>> importLegacyEmployees(le);
>>>>
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> @Transactional
>>>>>> protected
>>>>>>
>>>>
importLegacyEmployees(List<LegacyEmployee> les)
>>>> {
>>>>
>>>>>> for
(LegacyEmployee le:
>>>>>>
>>>> les) {
>>>>
>>>>>>
>>>> employeeService.store(le);
>>>>
>>>>>> }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> This would actually _not_ work
when using proxies
>>>>>>
>>>> for the interceptor handling, because
calling a method on an
>>>> own class doesn't invoke the
proxyhandler.
>>>>
>>>>>> So is this expected to work?
>>>>>>
>>>>>> I remember that the old spec
explicitly says that
>>>>>>
>>>> we need to use subclassing, but cannot
find this paragraph
>>>> anymore. So what does the spec require us
to do? And what is
>>>> Weld going to do?
>>>>
>>>>>> txs and LieGrue,
>>>>>> strub
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>>
_______________________________________________
>>>>>> weld-dev mailing list
>>>>>> weld-dev(a)lists.jboss.org
>>>>>>
https://lists.jboss.org/mailman/listinfo/weld-dev
>>>>>>
>>>>>>
>>>>>
_______________________________________________
>>>>> weld-dev mailing list
>>>>> weld-dev(a)lists.jboss.org
>>>>>
https://lists.jboss.org/mailman/listinfo/weld-dev
>>>>>
>>>>
>>>>
>>>
>>>
>>>
>>>
_______________________________________________
>>> weld-dev mailing list
>>> weld-dev(a)lists.jboss.org
>>>
https://lists.jboss.org/mailman/listinfo/weld-dev
>>>
>>
>