[weld-dev] interceptors expected to be implemented via proxying or via subclassing?

Marius Bogoevici marius.bogoevici at gmail.com
Mon May 17 12:18:26 EDT 2010


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 at redhat.com>  wrote:
>>>
>>>        
>>>> From: Pete Muir<pmuir at redhat.com>
>>>> Subject: Re: [weld-dev] interceptors expected to be implemented via proxying or via subclassing?
>>>> To: "Marius Bogoevici"<marius.bogoevici at gmail.com>
>>>> Cc: "Mark Struberg"<struberg at yahoo.de>, weld-dev at 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 at lists.jboss.org
>>>>>> https://lists.jboss.org/mailman/listinfo/weld-dev
>>>>>>
>>>>>>              
>>>>> _______________________________________________
>>>>> weld-dev mailing list
>>>>> weld-dev at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/weld-dev
>>>>>            
>>>>
>>>>          
>>>
>>>
>>>
>>> _______________________________________________
>>> weld-dev mailing list
>>> weld-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/weld-dev
>>>        
>>      
>    



More information about the weld-dev mailing list