I  hacked on the xfire source to get my particular problem fixed.

1)  I changed the readParameter() method of AegisBindingProvider.java to
recognise when Holders are involved (and then create value Type  to parse
the Holder value).

2) I changed Invocation.java to map the response Holder objects to the one's
passed in by the client.


This is not a very good solution, but worked in my case.

cheers,
Jamie

Here's the code (in AegisBindingProvider.java and Invocation.java) ...


public Object readParameter(MessagePartInfo p, XMLStreamReader xsr,
MessageContext context)
       throws XFireFault
   {
       QName name = xsr.getName();

       Type type = getTypeMapping(context.getService()).getType(name);

       if (type == null) type = (Type) p.getSchemaType();

       type = getReadType(xsr, context, type);

       MessageReader reader = new ElementReader(xsr);

       if (reader.isXsiNil())
       {
           reader.readToEnd();
           return null;
       }

       context.setProperty(CURRENT_MESSAGE_PART, p);


       Object o = null;

       // Start of code to make OUT params with Holder classes work...
       // Only bother to process Holders this way, the other object must be
the normal result object
       if ("javax.xml.ws.Holder".equals(type.getTypeClass().getName())) {
           Type valueType = null;
           try {

               // There's got to be a better way to configure this mapping
               // May be a mapping file? In aegis.xml??

               if ("code".equals(name.getLocalPart())) {
                   valueType = new StringType();
               }

               if ("cost".equals(name.getLocalPart())) {
                   valueType = new BigIntegerType();
               }

               if ("deliveryMethods".equals(name.getLocalPart())) {
                   valueType = new JaxbType(Class.forName("
com.softix.services.nlsr.ArrayOfDeliveryMethod"));
               }

               if ("categories".equals(name.getLocalPart())) {
                   valueType = new JaxbType(Class.forName("
com.softix.services.nlsr.ArrayOfCategory"));
               }

               // create the value
               if (valueType != null) {
                     // Magically create the Holder object
                   o = type.getTypeClass().newInstance();

                   // Set the value in the magically created Holder object
                   // Looks and smells like a Holder, but doesn't come when
called (by casting, maybe generics)
                   // Must use reflection

                   Field valueField = o.getClass().getField("value");
                   if (valueField != null) valueField.set(o,
valueType.readObject(reader, context));
               }
           }
           catch (Exception e) {
               e.printStackTrace();
           }

       }

       if (o == null) {
           o = type.readObject(reader, context);
       }

       return o;
   }





 Object[] invoke(OperationInfo op, Object[] params) throws Exception
   {
       try
       {
           OutMessage msg = new OutMessage(client.getUrl());
           msg.setBody(params);
           msg.setChannel(client.getOutChannel());

           // TODO this should probably be in a seperate handler.
           // We'll have to address this when we add REST support.
           Binding binding = client.getBinding();
           if (binding instanceof Soap11Binding)
               msg.setSoapVersion(Soap11.getInstance());
           else if (binding instanceof Soap12Binding)
               msg.setSoapVersion(Soap12.getInstance());

           context = new MessageContext();
           context.setService(client.getService());
           context.setXFire(client.getXFire());
           context.setBinding(binding);
           context.setProperty(Client.CLIENT_MODE, Boolean.TRUE);
           context.setClient(client);
           context.setProperty(CONTEXT_KEY, this);

           MessageExchange exchange = new MessageExchange(context);
           exchange.setOperation(op);
           exchange.setOutMessage(msg);
           context.setCurrentMessage(msg);

           HandlerPipeline outPipe = new HandlerPipeline(client.getXFire
().getOutPhases());
           outPipe.addHandlers(client.getXFire().getOutHandlers());
           outPipe.addHandlers(client.getOutHandlers());
           outPipe.addHandlers(client.getTransport().getOutHandlers());

           context.setOutPipeline(outPipe);

           ServiceInvocationHandler.writeHeaders(context, null);
           outPipe.invoke(context);
       }
       catch (Exception e1)
       {
           throw XFireFault.createFault(e1);
       }

       waitForResponse();

       if (fault != null)
       {
           Exception localFault = fault;
           fault = null;
           throw localFault;
       }

       Object[] localResponse = response;
       response = null;

       // Setting the OUT params...
       // Assume that the Holders passed in are in the same order
       // as the Holders that come out
       // Then sync them up, and transfer the values over.
       List responseHolders = new LinkedList();
       for (Object o : localResponse) {
           if (o instanceof Holder) {
               Holder h = (Holder) o;
               responseHolders.add(h);
           }
       }
       List paramHolders = new LinkedList();
       for (Object o : params) {
           if (o instanceof Holder) {
               paramHolders.add(o);
           }
       }
       if (paramHolders.size() == responseHolders.size()) {
           for (int i = 0; i < paramHolders.size(); i++) {
               Holder paramHolder = (Holder) paramHolders.get(i);
               Holder responseHolder = (Holder) responseHolders.get(i);
               paramHolder.value = responseHolder.value;
           }
       }

       return localResponse;
   }

On 12/21/06, Jamie Lister <[EMAIL PROTECTED]> wrote:

Hi,

 I'm quite new to this stuff :-)


I have an XFire client. I generate code using the Eclipse plugin with
default options (JAXB). I have been able to configure WS-addressing,
WS-Security and HTTPS as required by the .NET service I'm connecting to. The
WSDL is rpc, literal.

Everything works nicely, except for OUT parameters. I have quite a lot of
those and they always come back NULL in the javax.xml.ws.Holder.valuemember. I 
verified that the HttpClient certainly sees both the in and out
params. All the IN parameters are working fine.

I downloaded and compiled the Xfire source and followed the execution. I
found a couple of points:

1) The normal "result" parameter is org.codehaus.xfire.jaxb2.JaxbType,
whereas the OUT params are org.codehaus.xfire.aegis.type.basic.BeanType.
Will these BeanTypes know how to unmarshall the Xml in the correct way for a
Holder?

2) The "Invocation" object, doesn't appear to set the Holder parameters
passed in by the client code with the values from the unmarshalling (they
are null in any case, but still there should be a way to pass these values
back out).


What is the best way to get this working?
Do I need to make a javax.xml.ws.Holder aegis.xml mapping file? If so,
what would that look like?


Best regards,
Jamie Lister

Reply via email to