Uploaded image for project: 'OpenEJB'
  1. OpenEJB
  2. OPENEJB-1344

Port location is only overwritten if no wsdlLocation is set

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.1.2
    • None
    • webservices
    • None

    Description

      I am testing JAX-WS webservices with OpenEJB like in the webservice-security example (openejb.embedded.remotable enabled). This works fine, if I do not set a wsdlLocation attribute in the @Webservice annotation. Since I want a released wsdl to be kept stable, I generated one using jaxws-maven-plugin (which in turn uses JDK's standard tooling wsgen) and set it into the wsdlLocation attribute. According to the JAX-WS specification, I expected this would force the container to validate compatibility between the given wsdl and the webservice implementation.

      If I set a wsdlLocation, however, I get the following Exception when trying to run the test case:

      com.sun.xml.ws.streaming.XMLStreamReaderException: XML reader error: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
      at [row,col,system-id]: [1,0,"http://127.0.0.1:4204/HelloWorldWebserviceBean?wsdl"]
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:267)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:95)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.nextContent(XMLStreamReaderUtil.java:110)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.nextElementContent(XMLStreamReaderUtil.java:100)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.hasWSDLDefinitions(RuntimeWSDLParser.java:220)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:130)
      at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:265)
      at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:228)
      at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:176)
      at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:104)
      at javax.xml.ws.Service.<init>(Unknown Source)
      at javax.xml.ws.Service.create(Unknown Source)
      at de.ergodirekt.samples.cosa.k1.service.AbstractBusinessModuleWebserviceTest.getHelloWorldWebservicePort(AbstractBusinessModuleWebserviceTest.java:21)
      at de.ergodirekt.samples.cosa.k1.service.HelloWorldWebserviceBeanHelloTest.testHello(HelloWorldWebserviceBeanHelloTest.java:18)
      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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
      at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
      at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
      at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
      Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
      at [row,col,system-id]: [1,0,"http://127.0.0.1:4204/HelloWorldWebserviceBean?wsdl"]
      at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:661)
      at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2134)
      at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2040)
      at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1069)
      at com.sun.xml.ws.util.xml.XMLStreamReaderFilter.next(XMLStreamReaderFilter.java:92)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:76)
      ... 36 more

      After doing some debugging, I found that the Webservice is deployed using the bogus port location wsgen generated into the wsdl:
      <service name="HelloWorldWebservice">
      <port name="HelloWorldPort" binding="tns:HelloWorldPortBinding">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
      </port>
      </service>

      If I don't set wsdlLocation in the @Webservice annotation, the wsdl generated by OpenEJB contains the actual address the webservice is deployed at (localhost:4204/HelloWorldWebserviceBean?wsdl)

      Now it would be simple to just replace the "REPLACE_WITH_ACTUAL_URL" with the actual url, but the problem is, that I don't want to know the actual address at development or test time. I think the reason jaxws-maven-plugin does not even support setting an actual url is because the JAX-WS specification requires an implementation to always overwrite such a binding with its own deployment address (see JAX-WS 2.2 Chapter 5.2.5.3):
      "At publishing time, a JAX-WS implementation MUST patch the endpoint address in the root description document to match the actual address the endpoint is deployed at."

      During debugging, I found, that there is a method to do auto-assigment of webservice ports to their actual locations/addresses in OpenEJB, but this method is only called, when no location is provided yet (see org.apache.openejb.server.webservices.WsService line 235ff):

      // generate a location if one was not assigned
      String location = port.getLocation();
      if (location == null)

      { location = autoAssignWsLocation(bean, port, contextData, deploymentIdTemplate); }

      Is this really in accordance to the JAX-WS spec part quoted above? Shouldn't autoAssignWsLocation always be used, regardless if a location is already set in the port via wsdl? If I remove the location == null check, my test works as intended, a webservice is generated using the wsdl from wsdlLocation and the service is called correctly. Even if I accidentally change a method name in the implementation but not in the wsdl, a warning is printed to the console at deployment time and a WebserviceException is thrown, if I try to invoke this operation.

      Attachments

        Activity

          People

            Unassigned Unassigned
            thwaerte Thorsten Wärtel
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated: