You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Thibaut Robert <th...@gmail.com> on 2013/09/04 17:45:11 UTC

Re: Jax-RS SpringResourceFactory and lifecycle methods

On Fri, Aug 30, 2013 at 12:15 PM, Sergey Beryozkin <sb...@gmail.com> wrote:
> Hi
>
> On 30/08/13 10:58, Thibaut Robert wrote:
>>
>> On Thu, Aug 29, 2013 at 6:26 PM, Sergey Beryozkin <sb...@gmail.com>
>> wrote:
>>>
>>> Hi
>>>
>>> On 29/08/13 14:45, Thibaut Robert wrote:
>>>>
>>>>
>>>> On Thu, Aug 29, 2013 at 2:36 PM, Sergey Beryozkin <sb...@gmail.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> Hi, actually, Spring is not calling lifecycle methods when prototype
>>>>> scope
>>>>> beans are used, directly or when wrapped in SpringResourceFactory. I've
>>>>> only
>>>>> managed to confirm it is calling these methods for singletons (if not
>>>>> wrapped in this factory) or per-request beans.
>>>>
>>>>
>>>> Strange, I don't see the same behovior:
>>>> - for prototype, spring calls the postConstruct methods. It never
>>>> calls the predestroy (because it doesn't know when to do so).
>>>> - for singleton, spring calls the postConstruct too at application
>>>> startup, even when wrapped in SpringResourceFactory
>>>> I use spring 3.1.2 btw.
>>>>
>>>>> I think we need to keep the current behavior enabled by default, and
>>>>> I'm
>>>>> adding a 'callLifecylceMethods' boolean property to disable it if
>>>>> preferred:
>>>>> the only issue here is that in order to disable it one has to directly
>>>>> configure SpringResourceFactory which is not as convenient as simply
>>>>> listing
>>>>> the bean names, but I'm getting concerned I may break someone's code if
>>>>> I
>>>>> disable SpringResourceFactory calling the lifecycle methods by default
>>>>
>>>>
>>>> I don't share this opinion, but I can handle the burden of having to
>>>> declare the SpringResourceFactory. I understand well the compatibility
>>>> concern too.
>>>
>>>
>>>
>>> I've found what the problem was in my tests, apparently putting
>>> PostConstruct and PreDestroy annotations on interface is not really valid
>>> in
>>> Spring, so after I pushed them down to the abstract class I started
>>> seeing
>>> prototype beans post-constructed too.
>>>
>>>
>>>>
>>>>> If you know how to get prototype beans called their lifecycle methods
>>>>> then
>>>>> let me know please, I would not then worry about a case where we have
>>>>> regular singletons wrapped in the factory because no practical reason
>>>>> for
>>>>> doing it exists I guess,
>>>>
>>>>
>>>>
>>>> For me the only arguable case is whether to call postdestroy after the
>>>> request for prototype beans. Doing so makes sense for me. Spring doc
>>>> says: All lifecycle management past that point [the bean creation]
>>>> must be handled by the client.
>>>>
>>>>
>>>> (http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-scopes-prototype)
>>>> I am still a little hesitant because it will not work for a
>>>> post-destroy method declared in xml fashion, but it's an acceptable
>>>> limitation I think.
>>>>
>>>> In all other cases, spring should call the methods for us.
>>>
>>>
>>>
>>> OK, here is what I've done:  I removed a "callLifecycleMethods" property
>>> introduced with my last commit an hour or so ago and
>>>
>>> - added "callPostConstruct" (default is false), unless a user enables it
>>> the
>>> factory won't call PostConstruct
>>>
>>> - added "callPreDestroy" - default is true, but it is only effective if
>>> the
>>> bean has a prototype scope. So Pre-Destroy will only be called by the
>>> factory if it is a prototype bean, but the user can still disable it if
>>> preferred by setting "callPreDestroy" to false
>>>
>>> That should work OK; if you have some concerns or more ideas on how to
>>> improve it let me know please;
>>
>>
>> Ok, I don't want to be nitpicknig but you asked me, then : I'm fine
>> with the default behavior in this solution. However, I'm a bit
>> concerned that a user can force post-construct to be called, but he
>> can't force predestroy to called (unless scope is protoype) .
>
>
> Well, I've thought about it and in fact my tests confirm that Spring calls
> preDestroy for Spring request scope beans and also for singletons once the
> test server goes down.
> Obviously if it is a prototype, and Spring allocates a new instance every
> time then we need to pre-destroy it.
>
> Also note that I've updated it a code a bit and if we have a case where
> pre-destroy has to be called then Custom factory will override a check
> method returning boolean and force it.
>
>
>
>> If you want to be exhaustive, I think there are 3 interesting cases:
>> - always call the methods (current behavior, not possible in your commit)
>
> This is what we moved away from. Why would we want to keep a code which
> results in duplicate post construct and pre-destroy calls ?
I mentioned it because you include a callPostConstruct option - to
restore old beahvior I suppose. When the option is true it should
always call preDestroy . But I don't understand this is the case.

>> - only call pre-destroy for prototype (future default behavior)
>
>
> You right in that it is only a default - if we have a case with the
> non-prototype beans requiring a post-destroy then a trivial override will do
> it :-). I guess we can't write a code which will work correctly for all type
> of scopes possibly supported by Spring
>
>> - never call them
>>
> this is nearly what we do now, by default, with the only exceptions being
> the prototypes but this can be disabled :-)
>
>
>> But I'm just wandering if these options will be used ... I'm sure you
>> have more important stuff to work on :)
>>
>
> What we do most of the time is fixing a lot of issues which kinf of minor
> but of course the sum of all the fixes makes a difference :-)
>
>
>>> I've also spotted that unless an endpoint is specifically configured,
>>> PreDestroy will be called twice. The contextual property,
>>> "org.apache.cxf.service.scope", set to "request" (a bit misnamed, do not
>>> remember why I named it this way) can be used to postpone calling
>>> PostDestroy until the response has been serialized, apparently it can
>>> help
>>> in dealing with some complex JAXB hierarchies, etc, but at the moment if
>>> this property is not set and PreDestroy is there then it will be called
>>> twice, fixing it too.
>>>
>>> Finally, added the ability to customize the names of init/destroy methods
>>> in
>>> the factory
>>>
>>> Thanks, Sergey
>>
>>
>> Thanks for this discussion and your responsiveness.
>
>
> No problems, thanks for your feedback
>
> Cheers, Sergey
>
>
>> Cheers ;)
>> Thibaut
>>
>>>
>>>>
>>>> Thibaut
>>>>
>>>>> Cheers, Sergey
>>>>>
>>>>>
>>>>>
>>>>> On 29/08/13 12:04, Sergey Beryozkin wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 29/08/13 11:33, Thibaut Robert wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Aug 28, 2013 at 5:24 PM, Sergey Beryozkin
>>>>>>> <sb...@gmail.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi
>>>>>>>>
>>>>>>>> On 28/08/13 10:44, Thibaut Robert wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I have some jax-rs service beans deployed via Spring. I use the
>>>>>>>>> jaxrs:server tag with the beanNames attribute to specify my bean.
>>>>>>>>> My
>>>>>>>>> beans are in a custom spring scope.
>>>>>>>>>
>>>>>>>>> Everything works fine, except that I notice that both Spring and
>>>>>>>>> cxf
>>>>>>>>> calls my @PostConstruct and @PreDestroy methods. I think this is a
>>>>>>>>> bit
>>>>>>>>> confusing. As cxf SpringResourceFactory delegate the resource
>>>>>>>>> lifecycle to spring, why is it calling itself the lifecycle methods
>>>>>>>>> ?
>>>>>>>>>
>>>>>>>>> In my case, the @Postconstruct is called twice at the first request
>>>>>>>>> (by spring then cxf). Then once per request (by cxf), whereas it is
>>>>>>>>> using an already existing instance. I would prefer cxf doesn't call
>>>>>>>>> the methods at all.
>>>>>>>>>
>>>>>>>> I think I added it in a 'copy-and-paste' kind of fashion, the
>>>>>>>> runtime
>>>>>>>> would
>>>>>>>> release a current service instance and if it is a per-request
>>>>>>>> instance
>>>>>>>> explicitly managed by the runtime then it makes sense, but I can see
>>>>>>>> now it
>>>>>>>> may cause side-effects, I'll make SpringResourceFactory calling
>>>>>>>> lifecycle
>>>>>>>> methods only if requested by the user, in meantime, the workaround
>>>>>>>> is
>>>>>>>> to
>>>>>>>> register a custom SpringResourceFactory which will ignore release
>>>>>>>> calls
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I am just wondering if there is a use case where calling the
>>>>>>> lifecycle
>>>>>>> method is usefull. Even a per request instance, if you put it in
>>>>>>> request scope, the methods will be called by spring. Maybe if you use
>>>>>>> prototype scope ? But in my view, the lifecycle has to be managed by
>>>>>>> the container owning the bean, which is always spring with this
>>>>>>> factory.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> You are right, I've played a bit and see Spring factory duplicating
>>>>>> what
>>>>>> Spring does too, so I will disable it by default, will keep an
>>>>>> optional
>>>>>> flag there just in case
>>>>>>
>>>>>>>
>>>>>>> For the moment I will either use your workaround, or declare my
>>>>>>> lifecycle methods in my spring xml file.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Sure, the latter option can be even simpler, at the moment it is not
>>>>>> easy to block the post construct call, will fix that too
>>>>>>
>>>>>> Thanks, Sergey
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> Thanks for kind support!
>>>>>>> Thibaut
>>>>>>>
>>>>>>>> Cheers, Sergey
>>>>>>>>
>>>>>>>>> Regards,
>>>>>>>>> Thibaut
>>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Sergey Beryozkin
>>>>>
>>>>> Talend Community Coders
>>>>> http://coders.talend.com/
>>>>>
>>>>> Blog: http://sberyozkin.blogspot.com
>>>
>>>
>>>
>