Hi folks,
I've discovered something a bit weird while messing around with
provider services. It seems that the implementation class must
directly implement the interface Provider<T>, even if its parent class
already does so. If this isn't done, I get an
ArrayIndexOutOfBoundsException rather than an informative failure.
For example, if I have a parent class declared like so (direct copies
and pastes):
public class DummyPredictor2Provider implements Provider<StreamSource>
{
// Implementation details removed ...
}
but my cxf-servlet.xml hooks the endpoint up to a subclass that looks like this:
@WebServiceProvider( portName = "GecoPort", serviceName =
"GecoService", targetNamespace = "http://cathdb.info/FuncNet_0_1/",
wsdlLocation = "WEB-INF/wsdl/Services.wsdl" )
public class GecoProvider extends DummyPredictor2Provider
{
}
I get the following error on requesting the WSDL:
java.lang.ArrayIndexOutOfBoundsException: 0
org.apache.cxf.jaxws.JAXWSProviderMethodDispatcher.<init>(JAXWSProviderMethodDispatcher.java:39)
org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.initConfiguration(JaxWsServiceFactoryBean.java:400)
org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.setJaxWsImplementorInfo(JaxWsServiceFactoryBean.java:391)
org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.setServiceClass(JaxWsServiceFactoryBean.java:174)
org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.initializeServiceFactory(AbstractWSDLBasedEndpointFactory.java:227)
org.apache.cxf.frontend.ServerFactoryBean.initializeServiceFactory(ServerFactoryBean.java:156)
org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:99)
org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:116)
org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:168)
org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:336)
org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:251)
org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:201)
org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:394)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1242)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1208)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1172)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:427)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:249)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:155)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:246)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:291)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
org.apache.cxf.transport.servlet.CXFServlet.loadAdditionalConfig(CXFServlet.java:161)
org.apache.cxf.transport.servlet.CXFServlet.updateContext(CXFServlet.java:129)
org.apache.cxf.transport.servlet.CXFServlet.loadSpringBus(CXFServlet.java:101)
org.apache.cxf.transport.servlet.CXFServlet.loadBus(CXFServlet.java:70)
org.apache.cxf.transport.servlet.AbstractCXFServlet.init(AbstractCXFServlet.java:90)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Thread.java:619)
However, if I duplicate the implements clause in the subclass
declaration, like so:
@WebServiceProvider( portName = "GecoPort", serviceName =
"GecoService", targetNamespace = "http://cathdb.info/FuncNet_0_1/",
wsdlLocation = "WEB-INF/wsdl/Services.wsdl" )
public class GecoProvider extends DummyPredictor2Provider implements
Provider<StreamSource>
{
}
then it's all happy. So I have two questions:
1. Should I post this as a bug on JIRA with a demonstration? It seems
like a bug to me, as surely any class implicitly satisfies the
interfaces implemented by its ancestor classes.
2. If it is working as designed, shouldn't one of those classes in the
stacktrace be checking the array size? :-)
This is in CXF 2.1.2 in Tomcat 6.0.16 on Sun JVM 1.6.0_10-rc2-b32.
Cheers,
Andrew.