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 execption:
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've looked at that file and can't see anything obvious (ProcessUIRequestResult is defined in the class and has a getter and setter). The class is below:
package YYY.ZZZwebservice.v5.types;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import YYY.ZZZbase.BaseVO;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="ProcessUIRequestResult" type="{http://YYY/ZZZbase/}BaseVO" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"processUIRequestResult"
})
@XmlRootElement(name = "ProcessUIRequestResponse")
public class ProcessUIRequestResponse {
@XmlElement(name = "ProcessUIRequestResult")
protected BaseVO processUIRequestResult;
/**
* Gets the value of the processUIRequestResult property.
*
* @return
* possible object is
* {@link BaseVO }
*
*/
public BaseVO getProcessUIRequestResult() {
return processUIRequestResult;
}
/**
* Sets the value of the processUIRequestResult property.
*
* @param value
* allowed object is
* {@link BaseVO }
*
*/
public void setProcessUIRequestResult(BaseVO value) {
this.processUIRequestResult = value;
}
public ProcessUIRequestResponse withProcessUIRequestResult(BaseVO value) {
setProcessUIRequestResult(value);
return this;
}
}
Does anyone have any idea what the problem could be? I can't spot anything obvious and have not been able to find any information as to what the issue could be.
Thanks for your help in advance.
EDIT - UPDATE ON 20/09 BASED ON LORENZO'S ANSWER
Unfortunately the web service is a third party service and I don't have access to modify the XSDs. I used the server URL of the WSDL when generating the Java from it.
However, as a test I modified the generated ProcessUIRequestResponse.java to change the property to start with an uppercase letter to match the WSDL and the same error was thrown.
Does anyone have any ideas?
FURTHER EDIT on 26/09 TO PROVIDE UPDATES **
I've been doing more investigation into this and have found that it actually looks to be an issue with the way in which the service endpoint interface is generated. This is what is 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);
}
The problem is with the @WebResult annotation and the blank targetNamespace. 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.
I've looked in the XSDs for any missing namespace definitions or any other obvious errors but I can't spot anything. Does anyone have any pointers as to where the targetNamespace or @WebResult is generated from?
It can be a matter of how the wsdl2java is naming the package. If the targetNamespace (wsdl) is in camel case notation, your package needs to be camel case too. E.g.:
For targetNamespace="http://your.domain/WebAdminServices/WebSiteMgmt"
package domain.your.webAdminServices.webSiteMgmt; --> WORKS :)
package domain.your.webadminservices.websitemgmt; --> NOT WORKS :(
Hope it helps,
Luis