History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XFIRE-777
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Tomasz Sztelak
Reporter: Victor Trakhtenberg
Votes: 1
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
XFire

WebService (JSR181) with soap header as INOUT parameter

Created: 27/Nov/06 11:44 AM   Updated: 07/Feb/08 10:23 AM
Component/s: Core
Affects Version/s: 1.2.2
Fix Version/s: 1.2.5

Time Tracking:
Not Specified

File Attachments: 1. Java Source File ServiceInvocationHandler.java (14 kb)
2. File XFireProblem.war (3.52 Mb)
3. Zip Archive XFireProblem.zip (11 kb)

Environment: Windows 2003, JBOSS 4.0.3SP1, XFire 1.2.2, String 2.0


 Description  « Hide
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.



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Victor Trakhtenberg - 28/Nov/06 04:40 AM
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 ***********************/


Tomasz Sztelak - 05/Mar/07 05:16 AM
Fixed in svn

bartolomeo sorrentino - 07/Feb/08 10:23 AM
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;
}