You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by Erwin Streur <es...@epo.org> on 2008/05/30 15:36:13 UTC
IndexOutOfBoundsException at JavaServiceDesc.java:520
Hello Axis Development team,
I stumbled across a situation I think it is a defect, but it could also be
that the way we are using Axis is not correct. The problem manifested
itself as a IndexOutOfBoundsException (see attached stacktrace) which
popped up "miraculously" after some time. After some investigation I came
to the following findings.
We are using Axis 1.4. (for completeness Java 1.6.0_10-beta-b14 and Tomcat
5.0.28)
We used message style SOAP without defining namespaces in both the service
description and the request
Sniplet server-config.wsdd:
<service name="ActionHandler" provider="java:MSG" style="message"
use="literal">
<parameter name="allowedMethods"
value="preCreationCheck preSendCheck" />
<parameter name="className"
value="org.epo.cassius.server.servicesweb.dispatch.business.ActionHandlerDispatcher"
/>
</service>
The ActionHandler contains the methods :
public SOAPBodyElement[] preCreationCheck(SOAPBodyElement[] payload)
throws AxisFault
public SOAPBodyElement[] preSendCheck(SOAPBodyElement[] payload) throws
AxisFault
The message that I used looks like this
<soap-env:Envelope xmlns:soap-encoding="UTF-8" xmlns:soap-env="
http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>....some security data ...
</soap-env:Header>
<soap-env:Body>
<preSendCheck>
<parameters>
.... some data...
</parameters>
</preSendCheck>
</soap-env:Body>
</soap-env:Envelope>
Initially the request are processed correctly. But after the WSDL has been
generated because of a ActionHandler?wsdl request , the SOAP requests fail
with the reported stacktrace.
Because the stacktrace report the problem in
JavaServiceDesc.getOperationsByQName, I debug this file and noticed the
following:
- Because of having no namespace in the request the code does not find a
match based on the QName
- Before the WSDL generation it tries to resolve it using the localPart
and suceeds (style=Message and namespaceMappings=null, thus
DefaultNamespace=null)
if (name2OperationsMap != null) {
if ((isWrapped() ||
((style == Style.MESSAGE) &&
(getDefaultNamespace() == null)))) {
// Try ignoring the namespace....?
==> overloads = (ArrayList)
name2OperationsMap.get(qname.getLocalPart());
} else {
// TODO the above code is weird: a JavaServiceDesc can
be document or rpc and
// still define a WSDL operation using a wrapper style
mapping.
// The following code handles this case.
Object ops =
name2OperationsMap.get(qname.getLocalPart());
if (ops != null) {
overloads = new ArrayList((Collection) ops);
for (Iterator iter = overloads.iterator();
iter.hasNext();) {
OperationDesc operationDesc = (OperationDesc)
iter.next();
if (Style.WRAPPED != operationDesc.getStyle())
{
iter.remove();
}
}
}
}
}
- After the WSDL generation it executes the ELSE part, because now it has
entries in the namespaceMapping. Given the documentation I don't think
this is correct.
- The ops is assigned a list with 1 entry with the correct operation, but
it is removed from "overloads" list, because the
operationDesc.getStyle()=serviceDesc.getStyle=Style.MESSAGE
- The reason why if doesn't crash if the service contains only 1 operation
is because of the following piece of code. Question: If this is discarding
previously gathered information why is this quick fallthrough not done
earlier?
// Handle the case where a single Message-style operation wants
// to accept anything.
if ((style == Style.MESSAGE) && (messageServiceDefaultOp !=
null))
return new OperationDesc [] { messageServiceDefaultOp };
- If there are not candidates the code exits the method using the
following piece of code. This is a problem, because of the iter.remove()
it can be an empty list
if (overloads == null)
return null;
- Correctly the following statement reports the IndexOutOfBoundsException
in case of the empty list
getSyncedOperationsForName(implClass,
((OperationDesc)overloads.get(0)).getName());
A minimal fix should be " if (overloads==null||overloads.size()==0)".
Since I'm not familiar with the requirements on the usage of namespace, I
can not say whether removing the "(getDefaultNamespace()==null)" and
making sure that the JavaServiceDesc object does not get changed as the
result from the ?wsdl request are good code changes as well. For now I
have it working in our project by putting namespace on the
servicedefinition and the requests
Best regards / Mit freundlichen Gr��en / Sinc�res salutations
Erwin Streur
External Administrative Employee Examination/Cassius Group | Dir. 2.7.1.2
European Patent Office
Patentlaan 3-9 | 2288 EE Rijswijk | The Netherlands
Tel. +31 (0)70 340 9928
estreur@epo.org
http://www.epo.org