[jbossws-dev] Re: Improving JBossWS-CXF Client Side Integration
Richard Opalka
ropalka at redhat.com
Thu Jun 4 01:31:09 EDT 2009
Hi Daniel,
all the options mentioned below sound reasonable to me.
Richard
Daniel Kulp wrote:
> Richard,
>
> Modifying the generated code is not a doable solution. That would tie them
> to CXF which would then violate the JAX-WS spec and TCK and such. Thus,
> that's not an option.
>
> However, you could be on the right track. In our ServiceImpl, all the
> "getPort" calls forward into the protected "createPort" method (line 384 of
> ServiceImpl). We COULD put your call to the listener in there.
>
> The better option would be to push it even furthur into CXF and put it into
> the JaxWsProxyFactoryBean/ClientProxyFactoryBean.create() call. That way,
> if they end up using the spring "jaxws:client" call or use the factories
> directly themselves, the listeners would be invoked as well.
>
> Dan
>
>
>
> On Wed June 3 2009 2:11:22 am Richard Opalka wrote:
>
>> Hi Daniel,
>>
>> Yes, I know about solution 1) you suggested. However I don't like it.
>> It's hacky and could cause a lot of troubles to our customers.
>> Thus I'd like to go the way to modify CXF code base.
>>
>> Before I'll write my suggestion let me clarify that we don't need to
>> wrap your ServiceDelegate. We just need to register properties
>> on the proxy and that can be achieved using listener approach.
>> So here are my thoughts how it could be achieved in another way (no
>> delegation):
>>
>> ---
>> ad1)
>> ---
>> // CXF provides listener interface
>> package org.apache.cxf.jaxws;
>>
>> public interface ServiceListener
>> {
>> void onPortCreated(T proxy, Class<T> sei);
>> }
>> ---
>> ad2)
>> ---
>> // JBossWS provides listener implementation
>> package org.jboss.wsf.stack.cxf.client;
>>
>> public class ServiceListenerImpl implements ServiceListener
>> {
>> public void onPortCreated(T proxy, Class<T> sei)
>> {
>> // ... our integration code
>> }
>> }
>> ---
>> ad3)
>> ---
>> // JBossWS somehow registers the listener
>> ---
>> ad4)
>> ---
>> // finally replace the following code in
>> org.apache.cxf.jaxws.ServiceImpl.createPort(...)
>> protected <T> T createPort(QName portName, EndpointReferenceType epr,
>> Class<T> serviceEndpointInterface, WebServiceFeature... features)
>> {
>> // ...
>> return serviceEndpointInterface.cast(obj);
>> }
>> // with the following code:
>> protected <T> T createPort(QName portName, EndpointReferenceType epr,
>> Class<T> serviceEndpointInterface, WebServiceFeature... features)
>> {
>> // ...
>> T proxy = serviceEndpointInterface.cast(obj);
>> for (ServiceListener listener : listeners)
>> {
>> listener.onPortCreated(proxy, serviceEndpointInterface);
>> }
>> return proxy;
>> }
>>
>> If you like this approach then let's disscuss how ad3) could be
>> achieved, i.e. how to register the listener on the service.
>>
>> Cheers,
>>
>> Richard
>>
>> Daniel Kulp wrote:
>>
>>> Well, couple things spring to mind:
>>>
>>> Option 1: requires no changes to CXF, but requires some classloader magic
>>> on your side
>>> Write your own javax.xml.ws.spi.Provider that probably subclasses ours
>>> and overrides the method:
>>> @Override
>>> public ServiceDelegate createServiceDelegate(URL url, QName qname,
>>> Class cls) {
>>> Bus bus = BusFactory.getThreadDefaultBus();
>>> return new ServiceImpl(bus, url, qname, cls);
>>> }
>>>
>>> In your case, return a subclass of our ServiceImpl the does your
>>> additional stuff. That way, any cast we may do to ServiceImpl would
>>> still work (not sure if we do it anywhere, but just in case). That way,
>>> you won't really have an extra delegation layer. Just overrides.
>>> The TRICK is getting your provider to be used instead of ours. Thus,
>>> you may need to make sure your
>>> META-INF/services/javax.xml.ws.spi.Provider file is picked up before our
>>> (or use the system property to force yours).
>>>
>>>
>>> Option 2: make changes to CXF. Couple of ideas here. One could be in
>>> our createServiceDelegate method above, we do something like:
>>>
>>>
>>> Provider p = bus.getExtension(Provider.class);
>>> if (p != null) {
>>> return p.createServiceDelegate(....);
>>> }
>>> return new ServiceImpl(....);
>>>
>>> or similar. Thus, if a custom Provider is found on the Bus, we'll
>>> delegate to it. Heck, we could also put a static "Provider delegate;"
>>> field on our ProviderImpl that you could set to your provider prior to
>>> any calls.
>>>
>>> Or, we could look for a property someplace for the name of the
>>> "ServiceImpl" class to instantiate. If set, use reflection to create
>>> the ServiceImpl thing if set.
>>>
>>> Anyway, those are my immediate thoughts.
>>>
>>> Dan
>>>
>>> On Mon May 25 2009 9:21:35 am Richard Opalka wrote:
>>>
>>>> Hi CXF Team,
>>>>
>>>>
>>>> We've spent some time with CXF source code analysis but without
>>>> success. Related issue is: https://jira.jboss.org/jira/browse/JBWS-2521
>>>> We would like to remove one very ugly JBossWS CXF JAX-WS client proxy
>>>> integration hack related to service references (method
>>>> hackServiceDelegate()),
>>>> see:
>>>>
>>>> http://fpaste.org/paste/12892
>>>>
>>>> We're registering our custom ServiceDelegate handler (via reflection)
>>>> in original proxy
>>>> and we delegate each call to CXF original service delegate there, with
>>>> one exception.
>>>> We're propagating service ref properties for every port creation before
>>>> returning
>>>> from our custom service delegate (method propagateProps(T proxy,
>>>> Class<T> serviceEndpointInterface)),
>>>> see:
>>>>
>>>> http://fpaste.org/paste/12893
>>>>
>>>> Could you guys, with excellent CXF architecture knowledge, give us
>>>> some hints how
>>>> to improve our JBossWS CXF JAX-WS client integration and remove
>>>> aforementioned ugly hack?
>>>>
>>>> JBossWS Team
>>>>
>>>> PS: We're looking forward for your suggestions ;)
>>>>
>
>
--
Richard Opalka
JBoss Software Engineer
Mail: ropalka at redhat.com
Mobile: +420 731 186 942
More information about the jbossws-dev
mailing list