Hi,
We have an application which needs to consume an external web service. To do
this we have generated the set of Java artifacts from the WSDL via Maven using
the wsdl2java goal provided by the cxf-codegen-plugin plugin.
In the application we want to set the endpoint to use for the web service call
at runtime (to cater for different web service endpoint URLs in test
environments) and so have written some code as follows to do this for us:
private <T> T createServiceObject(final Class<T> p_seiClass) throws
MalformedURLException {
final Service serviceFactory = Service.create(new URL(wsdlLocation),
new QName(targetNamespace, serviceName)); final T service =
serviceFactory.getPort(p_seiClass); ((BindingProvider)
service).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"endpoint");
return service; }
When the code runs it fails on the serviceFactory.getPort line with the
following exception:
javax.xml.ws.WebServiceException: class
ZZZ.YYYwebservice.v5.types.ProcessUIRequestResponse do not have a property of
the name ProcessUIRequestResult at
com.sun.xml.internal.ws.client.sei.ResponseBuilder$DocLit.<init>(ResponseBuilder.java:512)
at
com.sun.xml.internal.ws.client.sei.SEIMethodHandler.buildResponseBuilder(SEIMethodHandler.java:172)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.<init>(SyncMethodHandler.java:86)
at com.sun.xml.internal.ws.client.sei.SEIStub.<init>(SEIStub.java:83) at
com.sun.xml.internal.ws.client.WSServiceDelegate.createEndpointIFBaseProxy(WSServiceDelegate.java:641)
at
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:344)
at
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:326)
at
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:364)
at
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:368)
at javax.xml.ws.Service.getPort(Service.java:172) at
com.XXX.XXX.XXX.YYY.integration.facade.jaxws.ProcessUIRequestFacadeJaxws.createServiceObject(ProcessUIRequestFacadeJaxws.java:53)
at
com.XXX.XXX.XXX.YYY.integration.facade.jaxws.ProcessUIRequestFacadeJaxws.processUIRequest(ProcessUIRequestFacadeJaxws.java:39)
at
com.XXX.XXX.XXX.YYY.integration.facade.jaxws.ProcessUIRequestFacadeJaxwsTest.test(ProcessUIRequestFacadeJaxwsTest.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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: javax.xml.bind.JAXBException: ProcessUIRequestResult is not a valid
property on class ZZZ.YYYwebservice.v5.types.ProcessUIRequestResponse at
com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getElementPropertyAccessor(JAXBContextImpl.java:954)
at
com.sun.xml.internal.ws.client.sei.ResponseBuilder$DocLit.<init>(ResponseBuilder.java:501)
... 37 more
At the bottom I can see javax.xml.bind.JAXBException: ProcessUIRequestResult is
not a valid property on class
ZZZ.YYYwebservice.v5.types.ProcessUIRequestResponse which suggests that
something is wrong with the generated ProcessUIRequestResponse.java file.
I looked at that file and can't see anything obvious (ProcessUIRequestResult is
defined in the class and has a getter and setter).
So, my investigation progressed further to look at the SEI that was generated:
/** * This class was generated by Apache CXF 2.5.2
2013-09-26T13:05:17.389+01:00 Generated source version: 2.5.2 *
*/@WebService(targetNamespace = "http://zzz/yyywebservice/v5/types/", name =
"Types")@XmlSeeAlso({ zzz.yyyentityview.ObjectFactory.class,
zzz.yyyview.search.postcode.ObjectFactory.class,
zzz.yyyentityview.validation.ObjectFactory.class,
zzz.serializable_dictionary.ObjectFactory.class,
zzz.yyyview.search.app.ObjectFactory.class, zzz.yyybase.ObjectFactory.class,
zzz.yyybase.enums.ObjectFactory.class,
zzz.yyyview.uw.ObjectFactory.class, zzz.yyyview.app.ObjectFactory.class,
zzz.yyyview.search.bank.ObjectFactory.class,
zzz.yyyview.search.list.ObjectFactory.class,
zzz.yyyentityview.app.ObjectFactory.class,
zzz.yyyentityview.client.ObjectFactory.class, ObjectFactory.class })public
interface Types {
@WebResult(name = "ProcessUIRequestResult", targetNamespace = "")
@ResponseWrapper(localName = "ProcessUIRequestResponse", targetNamespace =
"http://zzz/yyywebservice/v5/types/", className =
"zzz.yyywebservice.v5.types.ProcessUIRequestResponse")
@RequestWrapper(localName = "ProcessUIRequest", targetNamespace =
"http://zzz/yyywebservice/v5/types/", className =
"zzz.yyywebservice.v5.types.ProcessUIRequest") @WebMethod(operationName =
"ProcessUIRequest", action = "http://zzz/yyywebservice/v5/ProcessUIRequest")
public zzz.yyybase.BaseVO processUIRequest( @WebParam(name =
"ProcessUIRequest", targetNamespace = "http://zzz/yyywebservice/v5/types/")
zzz.yyybase.BaseVO processUIRequest);
@WebResult(name = "GetActivityStatusEntityResult", targetNamespace = "")
@ResponseWrapper(localName = "GetActivityStatusEntityResponse", targetNamespace
= "http://zzz/yyywebservice/v5/types/", className =
"zzz.yyywebservice.v5.types.GetActivityStatusEntityResponse")
@RequestWrapper(localName = "GetActivityStatusEntity", targetNamespace =
"http://zzz/yyywebservice/v5/types/", className =
"zzz.yyywebservice.v5.types.GetActivityStatusEntity")
@WebMethod(operationName = "GetActivityStatusEntity", action =
"http://zzz/yyywebservice/v5/GetActivityStatusEntity") public
zzz.yyybase.ActivityStatusVOBase getActivityStatusEntity(
@WebParam(name = "ProcessUIRequest", targetNamespace =
"http://zzz/yyywebservice/v5/types/") zzz.yyybase.BaseVO processUIRequest);}
You can see that the targetNamespace of the @WebResult annotation is blank.
When I manually edit the class and add what I would expect the targetNamespace
to be (based on looking in the XSDs), I can sucessfully invoke the web service.
Having done some research into what the @WebResult tag represents, it is
related to the wsdl:part definition. Tracing through the WSDL and XSD
definitions from wsdl:port which is defined as follows (in one of the WSDL
files):
<wsdl:message name="ProcessUIRequestSoapIn"> <wsdl:part name="parameters"
element="tns:ProcessUIRequest"/> </wsdl:message> <wsdl:message
name="ProcessUIRequestSoapOut"> <wsdl:part name="parameters"
element="tns:ProcessUIRequestResponse"/> </wsdl:message>
This WSDL has the tns and targetNamespace defined as
"http://zzz/yyywebservice/v5/types/" (which is what I add to the @WebResult to
get the call working).
The definitions of ProcessUIRequest and ProcessUIRequestResponse are found in
an included schema as follows:
<xs:element name="ProcessUIRequest"> <xs:complexType> <xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="ProcessUIRequest"
type="q1:BaseVO" xmlns:q1="http://tcp/ssgbase/"/> </xs:sequence>
</xs:complexType> </xs:element> <xs:element name="ProcessUIRequestResponse">
<xs:complexType> <xs:sequence> <xs:element minOccurs="0"
maxOccurs="1" name="ProcessUIRequestResult" type="q2:BaseVO"
xmlns:q2="http://tcp/ssgbase/"/> </xs:sequence> </xs:complexType>
</xs:element>
This schema also has the the tns and targetNamespace defined as
"http://zzz/yyywebservice/v5/types/" .
>From what I can see, everything in the WSDL and XSD definitions look fine and
>I'm now at a bit of a dead end. Does anyone have pointers for where I can
>look next?
Regards,
Euan