This is quite common (see the XML parser, JACC, etc) and sounds like it could lend itself very well to what is trying to be done here.
Jeff On Jun 3, 2009, at 1:13 PM, 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 ofServiceImpl). 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 factoriesdirectly 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 towrap 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 magicon your sideWrite your own javax.xml.ws.spi.Provider that probably subclasses oursand overrides the method: @Overridepublic 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 youradditional 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 yourMETA-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 inour 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'lldelegate to it. Heck, we could also put a static "Provider delegate;" field on our ProviderImpl that you could set to your provider prior toany calls. Or, we could look for a property someplace for the name of the"ServiceImpl" class to instantiate. If set, use reflection to createthe 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-2521We would like to remove one very ugly JBossWS CXF JAX-WS client proxyintegration hack related to service references (method hackServiceDelegate()), see: http://fpaste.org/paste/12892We're registering our custom ServiceDelegate handler (via reflection)in original proxyand we delegate each call to CXF original service delegate there, withone exception.We're propagating service ref properties for every port creation beforereturning from our custom service delegate (method propagateProps(T proxy, Class<T> serviceEndpointInterface)), see: http://fpaste.org/paste/12893Could you guys, with excellent CXF architecture knowledge, give ussome 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 ;)-- Daniel Kulp [email protected] http://www.dankulp.com/blog
