I am trying to connect to a WS that requires me to pass a specific host name during connection. I am trying to achieve this using JAX-WS and Apache CXF but so far I've been unsuccessful.
I can access the endpoint using CURL
curl -v -H 'Host: myHost' http://.../endpoint.jws?wsdl
The issue here is that I need to provide the host
param whenever I try to access the WSDL.
This is what I've tried so far:
final URL wsdlLocation = URI.create("http://.../endpoint.jws?wsdl").toURL();
log.info("URL : {}", wsdlLocation.toString());
HttpURLConnection cnx = (HttpURLConnection) wsdlLocation.openConnection();
cnx.setRequestProperty("Host", "myHost");
PNMService pnmService = new PNMService(wsdlLocation);
pnmPortType = pnmService.getPNMPort();
And the PNMService
class:
@WebServiceClient(name = "PNMService", targetNamespace = "http://www.myhost.com/pnm/service", wsdlLocation = "${pnm.wsdl.url}")
public class PNMService extends Service {
private static final QName PNMSERVICE_QNAME = new QName("http://www.myhost.com/pnm/service", "PNMService");
PNMService (URL wsdlLocation) {
super(wsdlLocation, PNMSERVICE_QNAME);
}
/**
* @return returns PNMPortType
*/
@WebEndpoint(name = "PNMPort")
PNMPortType getPNMPort () {
return super.getPort(new QName("http://www.myhost.com/pnm/service", "PNMPort"), PNMPortType.class);
}
}
And every time the error is the same :
Caused by: java.io.IOException: Server returned HTTP response code: 503 for URL: http://.../endpoint.jws?wsdl
The same URL is accessible by the CURL command (and without the host name CURL also throws me the same 503 error).
I've tried everything described so far in all these questions (including the system property approach) :
And like the comments in those answers suggest, I have cxf-rt-frontend-jaxrs
cxf-rt-frontend-jaxws
and cxf-rt-transports-http
in my pom., and I can see CXF being invoked
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
But so far, I haven't had any luck. Can someone please help me figure out what I'm doing wrong here?
I finally got it working and the trick behind the solution is simple.
Creating the PNMServie
(i.e the WebServiceClient
) also attempts a connection with the WS. This would inevitably fail because of my header restrictions.
So all I had to do was create the WebServiceClient
without actually attempting the connection until I can set the headers.
JaxWsProxyFactoryBean bean = new JaxWsProxyFactoryBean();
bean.setServiceClass(PNMPortType.class);
bean.setAddress(wsdlUrl);
bean.setServiceName(new QName("http://.../service", "MyService"));
pnmPortType = (PNMPortType) bean.create();
Map<String, Object> requestHeaders = new HashMap<>();
requestHeaders.put("host", Collections.singletonList("MyHostHeader"));
BindingProvider bindingProvider = (BindingProvider) pnmPortType;
bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
In addition the restricted headers property needs to be set as described this answer here : https://stackoverflow.com/a/50653672/2427453