Does WSDL have the concept of an asynchronous web method?

By : tuseau
Source: Stackoverflow.com
Question!

I'm writing an API in WCF 4.6.1. The client(s) will not be written by me, and will not necessarily be in .NET (they could be in any language/platform).

There is a web method which does something that can take a long time, so I want to encourage the client to call it asynchronously. I know that the client can be written to treat the web method as async (threading, etc), but is there a way of "enforcing" the actual web service as an async operation? i.e. Does WSDL have a way to saying "this is an async method"?

By : tuseau


Answers

Does WSDL have a way to saying "this is an async method"?

No it doesn't. The communication between the client and the service is synchronous even if the client thread does not block while that call is taking place. This is to say the invocation is asynchronous not that the web service method is asynchronous.

If you provide good documentation to say that for a particular operation it's advisable to use a separate thread because the response is slow to be generated you should be OK. Clients need to be built and the integration with the web service tested. The developers will notice the slow response and they will decide if they need to make the call in a non blocking way. Even blocking might be a solution for them, you never know, what you consider slow other might have no issue with.

If you want to "force" clients to not block for the response you could use for example WS-Addressing (I'm assuming here that you are using WCF for a SOAP web service) where your client provides a callback endpoint that you can invoke when the response is ready. This complicates a bit the client since it needs to have a receiving endpoint now. But a client developer might prefer to chose how she invokes the service (in a blocking/non blocking way) as opposed to having to implement the WS-Addressing spec.

By : Bogdan


I would suggest the following general design pattern. It wastes an additional pointer, but will enforce the requirement that the const object will be able to only access const methods of the private object:

class ObjectImpl;

class const_Object {

public:

  const_Object(const ObjectImpl* object_impl)
    : _impl(object_impl);

  // Only const methods

private:      
  const ObjectImpl* _impl;
};

class Object : public const_Object
{
  Object(ObjectImpl* object_impl)
    : const_Object(object_impl), _impl(object_impl);

  // non-const methods go here.

private:      
  ObjectImpl* _impl;
};


Adding to Ian's answer, Any complex element that is named by root element will have factory method annotated with @XmlElementDecl().

You can resolve this, by moving the complex type declaration inline like below.

<xsd:schema xmlns= "http://www.foo.org/bar" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:annox="http://annox.dev.java.net" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    targetNamespace="http://www.foo.org/bar" jaxb:extensionBindingPrefixes="annox"
    jaxb:version="2.1" elementFormDefault="qualified">
    <xsd:element name="unit">
        <xsd:complexType>
            <xsd:annotation>
                <xsd:appinfo>
                    <annox:annotate>@javax.xml.bind.annotation.XmlRootElement(name="unit")
                    </annox:annotate>
                </xsd:appinfo>
            </xsd:annotation>
            <xsd:sequence>
                <xsd:any processContents="skip" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

ObjectFactory.class (no JAXBElement factory method generated here)

@XmlRegistry
public class ObjectFactory {


    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.foo.bar
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link Unit }
     * 
     */
    public Unit createUnit() {
        return new Unit();
    }

}

Test class:

@Test
public void testUnmarshalling() throws JAXBException, SAXException {
    JAXBContext context = JAXBContext.newInstance(Unit.class);

    Unmarshaller unmarshaller = context.createUnmarshaller();

    unmarshaller.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
            .newSchema(new StreamSource(getClass().getClassLoader().getResourceAsStream("common.xsd"))));

    Object unit = unmarshaller.unmarshal(getClass().getResourceAsStream("unit.xml"));

    System.out.println(">>> Class is: " + unit.getClass().getName());

    StringWriter writer = new StringWriter();
    context.createMarshaller().marshal(unit, writer);

    System.out.println(">>> XML is: " + writer.toString());

    //assertTrue(unit instanceof Unit);
}

Test xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.foo.org/bar">
    <text>Name</text>
</unit>

output :

>>> Class is: org.foo.bar.Unit
>>> XML is: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><unit xmlns="http://www.foo.org/bar"><text>Name</text></unit>
By : ulab


This video can help you solving your question :)
By: admin