JAX-WS dynamic webservice url [duplicate] - web-services

I generated a web-service client using JBoss utils (JAX-WS compatible)
using Eclipse 'web service client from a wsdl'.
So, the only thing I provided was a url to a web-service WSDL.
Now, the web service provider tells me to change the "url of client endpoint application access" of the web-service.
What is it and how to change it?

IMO, the provider is telling you to change the service endpoint (i.e. where to reach the web service), not the client endpoint (I don't understand what this could be). To change the service endpoint, you basically have two options.
Use the Binding Provider to set the endpoint URL
The first option is to change the BindingProvider.ENDPOINT_ADDRESS_PROPERTY property value of the BindingProvider (every proxy implements javax.xml.ws.BindingProvider interface):
...
EchoService service = new EchoService();
Echo port = service.getEchoPort();
/* Set NEW Endpoint Location */
String endpointURL = "http://NEW_ENDPOINT_URL";
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
System.out.println("Server said: " + echo.echo(args[0]));
...
The drawback is that this only works when the original WSDL is still accessible. Not recommended.
Use the WSDL to get the endpoint URL
The second option is to get the endpoint URL from the WSDL.
...
URL newEndpoint = new URL("NEW_ENDPOINT_URL");
QName qname = new QName("http://ws.mycompany.tld","EchoService");
EchoService service = new EchoService(newEndpoint, qname);
Echo port = service.getEchoPort();
System.out.println("Server said: " + echo.echo(args[0]));
...

To add some clarification here, when you create your service, the service class uses the default 'wsdlLocation', which was inserted into it when the class was built from the wsdl. So if you have a service class called SomeService, and you create an instance like this:
SomeService someService = new SomeService();
If you look inside SomeService, you will see that the constructor looks like this:
public SomeService() {
super(__getWsdlLocation(), SOMESERVICE_QNAME);
}
So if you want it to point to another URL, you just use the constructor that takes a URL argument (there are 6 constructors for setting qname and features as well). For example, if you have set up a local TCP/IP monitor that is listening on port 9999, and you want to redirect to that URL:
URL newWsdlLocation = new URL("http://theServerName:9999/somePath");
SomeService someService = new SomeService(newWsdlLocation);
and that will call this constructor inside the service:
public SomeService(URL wsdlLocation) {
super(wsdlLocation, SOMESERVICE_QNAME);
}

I wouldn't go so far as #Femi to change the existing address property. You can add new services to the definitions section easily.
<wsdl:service name="serviceMethodName_2">
<wsdl:port binding="tns:serviceMethodNameSoapBinding" name="serviceMethodName">
<soap:address location="http://new_end_point_adress"/>
</wsdl:port>
</wsdl:service>
This doesn't require a recompile of the WSDL to Java and making updates isn't any more difficult than if you used the BindingProvider option (which didn't work for me btw).

To change the end address property edit your wsdl file
<wsdl:definitions.......
<wsdl:service name="serviceMethodName">
<wsdl:port binding="tns:serviceMethodNameSoapBinding" name="serviceMethodName">
<soap:address location="http://service_end_point_adress"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Related

Web Service on OpenShift

I have deployed a web service on OpenShift by annotating a class with #WebService and a public method with #WebMethod. Then, I deployed the class in a WildFly8 container and the server started the service. In order to be able to access the WSDL file I had to create a file "jboss-web.xml" inside the WEB-INF folder and change the context-root.
Now I am able to access the WSDL file, but not the service itself. The problem is in this line of the wsdl file:
<wsdl:service name="PlotterService">
<wsdl:port binding="tns:PlotterServiceSoapBinding" name="PlotterPort">
<soap:address location="http://127.8.173.1:8080/Plotter"/>
</wsdl:port>
</wsdl:service>
The address location is set to an internal IP and should be replaced with the URL of my application. How can I do that? The only file I am able to modify is the class that I annotated at the beginning.
I managed to solve this:
Openshift does not have Web services setup by default, so we need to modify the server configuration. To do this open .openshift/config/standalone.xml (this file may be hidden) in an editor and make the following additions:
If the webservices subsystem is not configured as below under the element, copy the following and replace the webservices subsystem to enable and configure Web Services:
<subsystem xmlns="urn:jboss:domain:webservices:1.1">
<modify-wsdl-address>true</modify-wsdl-address>
<wsdl-host>${env.OPENSHIFT_APP_DNS}</wsdl-host>
<wsdl-port>80</wsdl-port>
<endpoint-config name="Standard-Endpoint-Config"/>
<endpoint-config name="Recording-Endpoint-Config">
<pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
<handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
</pre-handler-chain>
</endpoint-config>
</subsystem>

WebServiceException when accessng webservice using Apache CXF generated classes

I am having problems accessing a web service using Apache CXF generated classes (wsdl2java).
Everything was working fine until the web service provider suddenly changed a rule on their firewall and hosed us. What they are saying is they no longer allow http traffic, we have to start using https. The funny thing is, up until now we thought we were using https. This is inherited, legacy code. But we are pretty much using word for word the ssl example on the Apache CXF web site.
Here's a chunk of the wsdl:
...
<wsdl:portType name="GetMessagesSoap">
<wsdl:operation name="GetInfo">
<wsdl:input message="tns:GetInfoSoapIn" />
<wsdl:output message="tns:GetInfoSoapOut" />
</wsdl:operation>
</wsdl:portType>
...
<wsdl:service name="GetMessages">
<wsdl:port name="GetMessagesSoap" binding="tns:GetMessagesSoap">
<soap:address location="http://127.0.0.1/GetMessages.asmx" />
</wsdl:port>
</wsdl:service>
Basically we generate all the Java classes using wsdl2java. Then in our Gateway class we do the following:
private GetMessagesSoap getInstance() {
GetMessages getMessages = new GetMessages(wsdlUrl);
GetMessagesSoap getMessagesSoap = getMessages.getMessagesSoap();
setupTransportLayerSecurity(getMessagesSoap);
}
private void setupTransportLayerSecurity(final Object port) {
HTTPConduit httpConduit =
(HTTPConduit) ClientProxy.getClient(port).getConduit();
TLSClientParameters tlsCP = new TLSClientParameters();
KeyStore keyStore = ...
KeyManager[] myKeyManagers = getKeyManagers(keyStore ...
tlsCP.setKeyManagers(myKeyManagers);
KeyStore trustStore = ...
TrustManager[] myTrustStoreKeyManagers = getTrustManagers(trustStore);
tlsCP.setTrustManagers(myTrustStoreKeyManagers);
tlsCP.setDisableCNCheck(true);
tlsCP.setSecureSocketProtocol("SSL");
httpConduit.setTlsClientParameters(tlsCP);
}
Then we call getInfo(). This is where the error occurs.
public void getInfo() {
GetMessagesSoap getMessagesSoap = getInstance();
InfoResponse response = getMessagesSoap.getInfo()
}
The error we get is rather generic:
javax.xml.ws.WebServiceException: Could not send Message.
The ws provider says it's failing because we're trying to come in using http. All this despite all the fancy SSL stuff we're doing in the setupTransportLayerSecurity() method.
My fundamental doubt in all this is, is that really the reason it's failing? I mean, obviously it started failing when the rule was removed from the firewall. But, what I don't understand is, if the url in the GetMessages service in the wsdl is http, even if I say to use SSL, how in the world is it ever going to use https?
We've put a sniffer on the network and sure enough it's only using http. But ... isn't this normal?? I am by no means a SOAP expert, obviously. Can someone shed some light on this problem?
CXF HttpConduit only uses the TlsClientParameters when the address url is start with https.
Can you change the WSDL file?
If not, you can change service url at the runtime.

webservice flow, proxy and soap address

I am very new to SOAP webservice. Want to know few things..
1. There is an URL (say, A) by which we can access the WSDL, then what the "soap:address" is used for. I have found a new IP address (say B) as "soap:address location" mentioned in WSDL but this URL is totally different from A. My question is why B address is needed - is this some internal IP address of a machine that resides behind A and completely unaccessible from client. What is the flow?
Since A is not public, so the host have given the access permission to my WAN IP so that I can access A. Now I can access the A url (getting a WSDL content) from simple Java code
URL oracle = new URL(A);
URLConnection yc = oracle.openConnection(proxy);
as I am behind a proxy firewall. But I can access by
URLConnection yc = oracle.openConnection();
From this can I conlude that Java by default tries to connect any URL bypassing machine's default proxy configuraion?
I have generated the client stub from WSDL URL and found that it is annotated with A
#WebServiceClient(name = "BDCDataExchange", targetNamespace = "some url", wsdlLocation = "A"
But when I am running the code it is giving
com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: java.net.ConnectException: Connection timed out: connect
at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(Unknown Source)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(Unknown Source)
As I can access A from my simple java code, does this exception means that I can not access the internal soap:address B?
But the same client code is working if I generate the client using local WSDL path like
wsimport A //not working while executing, above exception comes
wsimport <a local path where I saved the WSDL file> //it works when I run

GSOAP: Automatic Proxy configuration URL

How can I setup a GSOAP generated proxy client class to use an automatic HTTP proxy configuration URL?
I know I can configure the HTTP proxy address like this:
AnyWebServicePortBindingProxy _client;
_client.proxy_host = "192.168.0.x"; // A valid network address.
_client.proxy_port = 8080;
_client.proxy_userid = "user";
_client.proxy_passwd = "password";
But what to do if I want to point to an HTTP proxy script like "http://my_proxy/proxy_script.cfg"?
Thanks!
A proxy configuration script is actually a javascript code that returns the proxy server address based on his needs. This was meant to work with web browsers that implement the necessary logic to parse the FindProxyForURL response.
I don't think GSOAP is able to do the same thing without your interference.
You must check your proxy response by hand (in the beginning of the SOAP client, for example) resolve and update your gSOAP proxy configuration accordingly.

How to dynamic create service proxy with JAX-WS

I have common web service interface on each endpoint applications (server and client).
How can I create port on client side without connecting to server for "the same" wsdl?
I search something what present this pseudocode:
MagicProxyFactory proxy = MagicProxyFactory.newInstance(MyServiceInterface.class);
/* then bind service address like that
((BindingProvider)proxy).getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http address");
*/
MyServiceInterface port = (MyServiceInterface) proxy.getPort();
Steps include:
Create the Service instance using the Service.create method
for which you need to know wsdl location, service name, and name space URL of the service.
e.g.
URL wsdlLocation = new URL("http://example.org/my.wsdl");
QName serviceName = new QName("http://example.org/sample", "MyService");
Service s = Service.create(wsdlLocation, serviceName);
Get the service proxy (service port for connecting) using Service.getPort() method.
For this you need to know endpoint implemenattion class name.
e.g. MyService port = s.getPort(MyService.class);
you can now call methods through proxy.
Using Metro? You can't. You need the WSDL to create the proxy. Either bundle the WSDL with your client (preferred) or use a URL from where the WSDL can be downloaded during proxy creation.