cancel
Showing results for 
Search instead for 
Did you mean: 

WSDL Importer Problems

jon2
Champ in-the-making
Champ in-the-making
So, I'm trying to call a WebService using the activiti-cxf-examples, and find the implementation extremely fragile, and feel you should address this key functionality instead of propogating the JavaDelegate solution (http://www.bpm-guide.de/2010/12/09/how-to-call-a-webservice-from-bpmn/)

Summary of the problems include:
    1. will not run under a JRE, only a JDK
    2, will run if the provided org.apache.cxf.jaxws.JaxWsServerFactoryBean is used, but it will not run correctly if on uses javax.xml.ws.Endpoint to provide the Web Service
    3. In WSDLImporter.getRootTypes(),  the call to new DOMParser() in very questionable, as it ties one to the XercesImpl that pops up first in the classpath
Details follow in seperate messages.
9 REPLIES 9

jon2
Champ in-the-making
Champ in-the-making
using the Sun JRE 1.6.0, I get the nice stacktrace:

May 5, 2011 9:52:44 AM sun.reflect.NativeMethodAccessorImpl invoke0
SEVERE: EXCEPTION
java.lang.IncompatibleClassChangeError: Class com.ibm.wsdl.BindingInputImpl does not implement the requested interface javax.wsdl.extensions.ElementExtensible
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.addExtensibilityElements(ServiceWSDLBuilder.java:232)
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.buildBindingInput(ServiceWSDLBuilder.java:392)
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.buildBindingOperation(ServiceWSDLBuilder.java:361)
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.buildBinding(ServiceWSDLBuilder.java:342)
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.build(ServiceWSDLBuilder.java:196)
at org.apache.cxf.wsdl11.ServiceWSDLBuilder.build(ServiceWSDLBuilder.java:151)
at org.apache.cxf.transport.http.WSDLQueryHandler.writeResponse(WSDLQueryHandler.java:138)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:230)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:828)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:450)

jon2
Champ in-the-making
Champ in-the-making
Using the javax.xml.ws.Endpoint as the WebService server makes the implementation of the WSDLImporter crash for a couple of reasons:

1. it inserts a comment after the XML declaration, and the WSDLImporter expects an XML Element
2. The XSD is imported and not inlined

The published WSDL from javax.xml.ws.Endpoint looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!– Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. –>
<!– Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. –>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://webservice.impl.engine.activiti.org/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    targetNamespace="http://webservice.impl.engine.activiti.org/" name="Counter">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://webservice.impl.engine.activiti.org/"
                  schemaLocation="http://localhost:63081/counter?xsd=1"></xsd:import>
        </xsd:schema>
    </types>
    …

jon2
Champ in-the-making
Champ in-the-making
private Element getRootTypes() {
    try {
      DOMParser parser = new DOMParser();
      parser.parse(this.wsdlLocation);
      …
This should be handled using JAXP. like this:

       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
       dbf.setNamespaceAware(true);
       DocumentBuilder db = dbf.newDocumentBuilder();
       Document doc = db.parse(this.wsdlLocation);
       …

jon2
Champ in-the-making
Champ in-the-making
Looking at the code in WSDLImporter I just about puked (P.C. was disturbed) to see the used of a DOMParser - surely there must be a higher-level way of parsing a WSDL.

5 minutes on Google, and I see JSR-110 deals just with this case.

Another 30 minutes of hacking and I have a piece of code that works for the simple test case, but will fail when there are multiple schema imports, or a mixture of schema imports and inline type definitions.  I'll leave that for you fellows to fix, as it involves a bit of refactoring.

   private Element getRootTypes() {
      Element schemaElement = null;
      try {
         WSDLFactory wsdlFactory = WSDLFactory.newInstance();
         WSDLReader reader = wsdlFactory.newWSDLReader();
         Definition definition = reader.readWSDL(this.wsdlLocation);
         Types types = definition.getTypes();
         for (Object object : types.getExtensibilityElements()) {
            Schema schema = (Schema) object;
            if (schema.getImports().isEmpty()) {
               schemaElement = schema.getElement();
            } else {
               for (Object value : schema.getImports().values()) {
                  for (Object si : ((List)value)) {
                     schemaElement = ((SchemaImport)si).getReferencedSchema().getElement();
                  }
               }
            }

         }
      } catch (WSDLException e) {
         throw new ActivitiException(e.getMessage(), e);
      }
      return schemaElement;
   }

esteban_roblesl
Champ in-the-making
Champ in-the-making
Hi Jon,
We had a couple of discussions regarding WSDL imports when the project began and the truth is that there is not a simple solution.
We knew that you may expect problems and we were trying to avoid a full dependency to CXF import.
However, at the moment I think that the best would be to provide a completely Cxf dependent implementation. I'm working on it and I expect to commit it during this week.
Could you attach to http://jira.codehaus.org/browse/ACT-809 a zip file containing your wsdl and the resources that it imports? I want to make sure that this implementation supports all the use cases that you are facing at the moment.
Thanks
Esteban

jon2
Champ in-the-making
Champ in-the-making
A standards-based implementation would be ideal, such as JAX-WS Client Dispatch API.

I see the CXF Project includes a JAX-WS implementation so one could choose to use it if desired, or plug in another implementation, if you would PLEASE just code to the API.

jon2
Champ in-the-making
Champ in-the-making
No JIRA account, so I post here the ZIP.

Best to run the Web Service i na seperate process with only a JDK1.6 (no Apache CXF).

   public static void main(String[] args) {
      Counter counter = new CounterImpl();
      Endpoint.publish("http://localhost:63081/counter", counter);
   }

The WSDL will have a couple of comment lines at the top, and in the <types> Element the following:

<xsd:schema>
    <xsd:import namespace="http://webservice.impl.engine.activiti.org/"
                     schemaLocation="http://localhost:63081/counter?xsd=1'/>
</xsd:schema>

The implentation I posted is a good start, using the JSR-110 WSDL Parser, but I suspect the JAX-WS implementation would look much different.

Cheers!

esteban_roblesl
Champ in-the-making
Champ in-the-making
Thanks Jon,
I will commit the changes to make it work in this scenario today and post the revision number to double check everything works fine.
Cheers

esteban_roblesl
Champ in-the-making
Champ in-the-making
Commited with cs: 2746