Hi CXF Folks,
see in lined comments below:
Daniel Kulp wrote:
On Wed June 3 2009 3:18:36 pm Jeff Genender wrote:
I actually prefer the injection/override of an implementation via a
property...
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.
Just because its "quite common" doesn't mean it works well. :-) For
example: the META-INF/services thing really does NOT work well in an OSGi
environment. The ServiceMix folks have to have separate "api" jars for
everything that uses the META-INF/services stuff that use a different lookup
mechanism.
Plus, the whole META-INF/services thing really depends on classpath ordering
and such which users never seem to get right. If CXF is first, it would use
CXF's and the JBoss customizations wouldn't trigger. If JBoss's is first,
they would.
This is exactly the reason why I don't like META-INF/services suggested
fix. We have many
complaining users on our forums about Stack XYZ doesn't work. Many times
its because
their IDE isn't configured properly. Users would need to take care also
about classpath ordering
if we would go this way.
That said, the listener thing Richard proposed has some additional benefits as
well when integrating into other containers such as ServiceMix or Camel.
Dan
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 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 ;)
--
Daniel Kulp
dk...@apache.org
http://www.dankulp.com/blog
--
Richard Opalka
JBoss Software Engineer
Mail: ropa...@redhat.com
Mobile: +420 731 186 942