XFire

WebService (JSR181) with soap header as INOUT parameter

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.2.2
  • Fix Version/s: 1.2.5
  • Component/s: Core
  • Labels:
    None
  • Environment:
    Windows 2003, JBOSS 4.0.3SP1, XFire 1.2.2, String 2.0
  • Number of attachments :
    3

Description

I'm developing web service using XFire,Spring JSR181 implementation.
I need to use SOAP header in mode INOUT.
I've define the following operation in web service interface:
@WebMethod(operationName = "op")
@WebResult(name = "opRes")
public String op(@WebParam(name = "ws_header", header = true, mode = WebParam.Mode.INOUT)Holder<SessionInfoHeader> ws_header);

The implementation is simple it just prints some string.
(see attached ServiceAWS.java,ServiceAImpl.java)

The problem is that I have a following exception:

Please see attache the eclipse project XFireProblem.zip the war as it was deployed in JBoss.

I've used the client: com.jacada.ServiceAClient

the exception is:

java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.xfire.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:54)
at org.codehaus.xfire.service.binding.ServiceInvocationHandler.sendMessage(ServiceInvocationHandler.java:271)
at org.codehaus.xfire.service.binding.ServiceInvocationHandler$1.run(ServiceInvocationHandler.java:84)
at org.codehaus.xfire.service.binding.ServiceInvocationHandler.execute(ServiceInvocationHandler.java:132)
at org.codehaus.xfire.service.binding.ServiceInvocationHandler.invoke(ServiceInvocationHandler.java:107)
at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)
at org.codehaus.xfire.transport.DefaultEndpoint.onReceive(DefaultEndpoint.java:64)
at org.codehaus.xfire.transport.AbstractChannel.receive(AbstractChannel.java:38)
at org.codehaus.xfire.transport.http.XFireServletController.invoke(XFireServletController.java:301)
at org.codehaus.xfire.transport.http.XFireServletController.doService(XFireServletController.java:130)
at org.codehaus.xfire.transport.http.XFireServlet.doPost(XFireServlet.java:116)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:159)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Unknown Source)

java.lang.IllegalArgumentException: wrong number of arguments
(I will provide the stack trace later).

I saw in org.codehaus.xfire.service.binding.ServiceInvocationHandler class in
protected Object[] fillInHolders(MessageContext context,OperationInfo opInfo, MessageInfo inMsg, MessageInfo outMsg, MessagePartContainer headerMsg,
MessagePartContainer outHeaderMsg, List params) method calculation of the number of the parameters:

int outSize = 0;
if (outMsg != null)
{
outSize = outHeaderMsg.size() + outMsg.size();
if (outSize != 0) outSize--;
}
int total = inMsg.size() + headerMsg.size() + outSize;

In my case for method "op" which takes only one parameter (the header) the value of total is 2.
Later the allocated array
Object[] newParams = new Object[total];
used in Java reflection to find the method, BUT there's no method with 2 parameters, but only with one parameter.

So it seems that there's a bug here.

I don't understand why does outSize participates in calculation of total.

Would it be correct to make the line:

int total = inMsg.size() + headerMsg.size();

May the problem in some other place.

  1. ServiceInvocationHandler.java
    28/Nov/06 4:37 AM
    14 kB
    Victor Trakhtenberg

Activity

Hide
Victor Trakhtenberg added a comment -

Hello,

I have an idea for what may be the problem:
the fillInHolders() method does not take into consideration the fact that in case of JSR181 the parameter may be of mode INOUT, in this case it will be counted twice one for being IN parameter and one for being OUT parameter.

I have suggestion for a fix:
(Please let me know if the fis is OK and what next)
(the file attached ServiceInvocationHandler.java)

/************** JACADA_CHANGE START ***********************/
private boolean isMessagePartExistByQName(List parts,QName name) {
if (parts == null || name == null) { return false; }
for (Iterator it = parts.iterator(); it.hasNext() {
MessagePartInfo part = (MessagePartInfo)it.next();
QName n = part.getName();
if (name.equals) { return true; }
}
return false;
}
// calculates the number of the different parameters.
// the reason is that the parameters in JSR181 may be: IN,OUT,INOUT
// in case of INOUT the parameter will appear both in "in" parameters container and "out" parameters container
// but it should be counted only once
private int calculateDifferentParametersNumber(MessagePartContainer in, MessagePartContainer out) {
int size = 0;
if (in == null && out == null) { return 0; }
if (in == null) { return out.size(); }
if (out == null) { return in.size(); }
// iterate on "out" parameters container and if the parameter does not appear in "in"
// container as well increment the counter
// (the "out" was chosen arbitrary due to the simmetry)
for (Iterator it = out.getMessageParts().iterator(); it.hasNext() {
MessagePartInfo outPart = (MessagePartInfo)it.next();
QName name = outPart.getName();
if( !isMessagePartExistByQName(in.getMessageParts(), name)) { size++; }
}
// add all the parameters in "in" containers
return size + in.size();
}

/**

  • Looks for holders, instantiates them, then inserts them into the parameters.
  • @return
    */
    protected Object[] fillInHolders(MessageContext context,
    OperationInfo opInfo,
    MessageInfo inMsg,
    MessageInfo outMsg,
    MessagePartContainer headerMsg,
    MessagePartContainer outHeaderMsg,
    List params) throws XFireFault
    {
    int paramSize = calculateDifferentParametersNumber(inMsg, outMsg);
    int headerSize = calculateDifferentParametersNumber(headerMsg, outHeaderMsg);
    int total = paramSize + headerSize;

// the outh param should not be counted
if (outMsg.size() > 0) { total--; }
/************** JACADA_CHANGE END ***********************/

Show
Victor Trakhtenberg added a comment - Hello, I have an idea for what may be the problem: the fillInHolders() method does not take into consideration the fact that in case of JSR181 the parameter may be of mode INOUT, in this case it will be counted twice one for being IN parameter and one for being OUT parameter. I have suggestion for a fix: (Please let me know if the fis is OK and what next) (the file attached ServiceInvocationHandler.java) /************** JACADA_CHANGE START ***********************/ private boolean isMessagePartExistByQName(List parts,QName name) { if (parts == null || name == null) { return false; } for (Iterator it = parts.iterator(); it.hasNext() { MessagePartInfo part = (MessagePartInfo)it.next(); QName n = part.getName(); if (name.equals) { return true; } } return false; } // calculates the number of the different parameters. // the reason is that the parameters in JSR181 may be: IN,OUT,INOUT // in case of INOUT the parameter will appear both in "in" parameters container and "out" parameters container // but it should be counted only once private int calculateDifferentParametersNumber(MessagePartContainer in, MessagePartContainer out) { int size = 0; if (in == null && out == null) { return 0; } if (in == null) { return out.size(); } if (out == null) { return in.size(); } // iterate on "out" parameters container and if the parameter does not appear in "in" // container as well increment the counter // (the "out" was chosen arbitrary due to the simmetry) for (Iterator it = out.getMessageParts().iterator(); it.hasNext() { MessagePartInfo outPart = (MessagePartInfo)it.next(); QName name = outPart.getName(); if( !isMessagePartExistByQName(in.getMessageParts(), name)) { size++; } } // add all the parameters in "in" containers return size + in.size(); } /**
  • Looks for holders, instantiates them, then inserts them into the parameters.
  • @return */ protected Object[] fillInHolders(MessageContext context, OperationInfo opInfo, MessageInfo inMsg, MessageInfo outMsg, MessagePartContainer headerMsg, MessagePartContainer outHeaderMsg, List params) throws XFireFault { int paramSize = calculateDifferentParametersNumber(inMsg, outMsg); int headerSize = calculateDifferentParametersNumber(headerMsg, outHeaderMsg); int total = paramSize + headerSize;
// the outh param should not be counted if (outMsg.size() > 0) { total--; } /************** JACADA_CHANGE END ***********************/
Hide
Tomasz Sztelak added a comment -

Fixed in svn

Show
Tomasz Sztelak added a comment - Fixed in svn
Hide
Bartolomeo Sorrentino added a comment -

I've downloaded the ServiceInvocationHandler.java in attach but it seems not work properly to marshal/unmarshal the INOUT parameter stored within header.

i've found a strange behaviour within method

private static XMLStreamReader getXMLStreamReader(AbstractMessage msg, MessagePartInfo header

the statement s
QName name = header.getName();
Element el = msg.getHeader().getChild(name.getLocalPart(), Namespace.getNamespace(name.getNamespaceURI()));

return always null also if the element exists

i've solved the problem adding the following method and call it instead of the code above

private static Element findElement( Element header, QName name ) {

Element result = header.getChild(name.getLocalPart(), Namespace.getNamespace(name.getNamespaceURI()));

if( null==result ) {

for( Element ee : (List<Element>)header.getChildren() ) {

if( ee.getName().equals(name.getLocalPart()) ) { result = ee; break; }
}
}

return result;
}

Show
Bartolomeo Sorrentino added a comment - I've downloaded the ServiceInvocationHandler.java in attach but it seems not work properly to marshal/unmarshal the INOUT parameter stored within header. i've found a strange behaviour within method private static XMLStreamReader getXMLStreamReader(AbstractMessage msg, MessagePartInfo header the statement s QName name = header.getName(); Element el = msg.getHeader().getChild(name.getLocalPart(), Namespace.getNamespace(name.getNamespaceURI())); return always null also if the element exists i've solved the problem adding the following method and call it instead of the code above private static Element findElement( Element header, QName name ) { Element result = header.getChild(name.getLocalPart(), Namespace.getNamespace(name.getNamespaceURI())); if( null==result ) { for( Element ee : (List<Element>)header.getChildren() ) { if( ee.getName().equals(name.getLocalPart()) ) { result = ee; break; } } } return result; }

People

Vote (1)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: