JBoss EAP 6 : IndexOutOfBound with CXF

Latest response

Hello all,

I use JBoss-eap 6.3 and I have problem with CXF.

My application has to communicate with a customer server by using SOAP webservice.
The customer provided me the WSDL and I generated all the Stubs thanks to the wsconsumer.sh shell command.

I know the SOAP message I send is OK and the response too. But, when I get the response, CXF generates the folowing stack :

[PhaseInterceptorChain /foo/bar/web/e3b1eafa-be61-43de-80b8-64b188b1f620/checks ] - Interceptor for {http://www
.foo.com/bar/}field#{http://www.foo.com/bar/field has thrown exception, unwinding now: java.lang
.IndexOutOfBoundsException: Index: 8, Size: 8
at java.util.ArrayList.rangeCheck(ArrayList.java:638)
at java.util.ArrayList.get(ArrayList.java:414)
at org.apache.cxf.message.MessageContentsList.get(MessageContentsList.java:80)
at org.apache.cxf.jaxws.interceptors.HolderInInterceptor.handleMessage(HolderInInterceptor.java:69)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:845)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1624)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1513)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1318)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:136)
at com.sun.proxy.$Proxy316.ajouterRetirerTitre(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
...

I looked for solution since few days but all I tried didn't work.
It's maybe due to the SOAP I receive, but I can't change it...

Any ideas?

Thanks in advance.

Nicolas

Responses

It's may code error...

ArrayList is size = 8 then index is start 0 to 7
so code is like

for (int i = 0 ; i < list.size() ; i++) {
 Object obj = list.get(i);
 ...
}

if code like

for (int i = 1 ; i <= list.size() ;i++) {
 Object obj = list.get(i); // When i = 8,  raise Exception.
...
}

then cause IndexOutOfBoundsException

Unfortunately it's not as easy as this kind of basic error code...

The exception is generated by org.apache.cxf.jaxws.interceptors.HolderInInterceptor at line 69 :

if (holder != null) {
    holder.value = inObjects.get(part);
    inObjects.put(part, holder);
}

I tried to override this class and adding test to prevent the exception but it doesn't work too...

I solved the problem.
I assume the SOAP I get is not really "JSR compliant" but I think this solution, which is a little bit uggly, works.

  1. Defining a new HolderInInterceptor by copying the original and changing lines 46-53 :

Original lines :

if (part.getIndex() != 0 && part.getTypeClass() != null) {
    @SuppressWarnings("unchecked")
    Holder<Object> holder = (Holder<Object>) outHolders.get(part.getIndex() - 1 );
    if (holder != null) {
        holder.value = inObjects.get(part);
        inObjects.put(part, holder);
    }
}

New lines :

if (part.getIndex() != 0 && part.getTypeClass() != null) {
    part.setIndex(Math.max(0, part.getIndex() - 1));
    @SuppressWarnings("unchecked")
    Holder<Object> holder = (Holder<Object>) outHolders.get(part.getIndex());
    if (holder != null) {
        holder.value = inObjects.get(part);
        inObjects.put(part, holder);
    }
}
  1. Replacing the interceptor in the class whoch defines the endPoint:
JaxWsEndpointImpl jaxwsEndpoint = (JaxWsEndpointImpl) client.getEndpoint();
List<Interceptor<? extends Message>> interceptors = jaxwsEndpoint.getInInterceptors();
for (int interceptorIdx = 0; interceptorIdx < interceptors.size(); interceptorIdx++) {
    if (interceptors.get(interceptorIdx) instanceof org.apache.cxf.jaxws.interceptors.HolderInInterceptor) {
        log.info("Replacing CXF HolderInInterceptor by Custom HolderInInterceptor.");
        interceptors.set(interceptorIdx, new HolderInInterceptor());
    }
}

Currently it works fine...