Port location is only overwritten if no wsdlLocation is set
-----------------------------------------------------------

                 Key: OPENEJB-1344
                 URL: https://issues.apache.org/jira/browse/OPENEJB-1344
             Project: OpenEJB
          Issue Type: Bug
          Components: webservices
    Affects Versions: 3.1.2
            Reporter: Thorsten Wärtel


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.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to