on 03-05-2013 6:34 PM
Hello,
I have created a application in NW OnDemand. In that I want to call a web service which is created in ByDesign. This web service requires basic authentication. I implemented a JAVA client code to call the web service and provided user name and password using "BindingProvider" interface of JAVA. When I run my app in Local NW server, it is working fine. It sends the request to end point URL successfully and receives the response too.
However, when the same app is published in SAP NW Cloud Server and run in cloud, I am getting an error saying "HTTP transport error: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake".
I know this error is related to SSL connection. What I assume here is, despite giving an message level authentication details for the web service in JAVA implementation code, I also need to open an SSL connection in SAP NW Cloud server to reach my end point. How to do that?
So in a simple words, How to consume a SOAP based secure web service from a app running in SAP NW Cloud server?
Best regards,
Hari
Hi All,
Finally we found out the root cause behind this connectivity issue. It is due to a limitation in the trial landscape of HANA Cloud Platform (HCP). In order to connect any SAP cloud system (ByDesign or Cloud for Customer or HANA Cloud Integration etc) from HANA Cloud Server, a web dispatcher has to be configured explicitly. And this can be done by the HCP connectivity experts. You can open a ticket in SAP Support Portal to get the web dispatcher configured for a cloud system to which you want to connect from HANA Cloud Server.
Thanks to and Petar Petrov for taking all necessary steps to solve this MYTH!!!!!
Best regards,
Hari
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello,
one possible reason could be when you try to establish a SSL connection to HTTP port, instead to HTTPS port. Then the server rejects handshake.
Another problem is that the default trust manager in Java does not trust SAP certificates. Hence I use sometimes my own TrustManager which trusts all certificatates. Of course, it is stupid to apply that TrustManager to all your SSL connections, you can apply it when you trust any certificate from a given host, i.e. basically you trust that host completely.
X509TrustManager trustManager = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string)
throws CertificateException {}
public void checkServerTrusted(X509Certificate[] xcs, String string)
throws CertificateException {}
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws java.security.cert.CertificateException {}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws java.security.cert.CertificateException {}
};
I am using that trustManager when using an ERP backend and it works fine with standard Java webservices.
Maybe it is a good idea to write a blog describing how to consume secured web service using different frameworks - CXF, standard Java..
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Hari,
I also assume that the dummy trust manager from Samir will help you out. I googled a bit for similar exceptions and it seems to come from the missing trust of the server certificate. For a real solution, the public certificate of the CA that is used by the server certificate needs to be imported into the trust store of your application.
A sample coding to set a custom X509TrustManager in CXF is the following one:
Client proxy = ClientProxy.getClient(client);
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
TLSClientParameters tcp = new TLSClientParameters();
// disables CN check of server certificate
tcp.setDisableCNCheck(true);
// Creating Trust Manager
TrustManager[] trustAllCerts = new TrustManager[] { /* trustManager from Samir */ trustManager };
tcp.setTrustManagers(trustAllCerts);
conduit.setTlsClientParameters(tcp);
Hope this helps.
Regards, Timo
Hello All,
I am still unsuccessful in achieving this
BTW, I tried all your suggestions and found that, it is not a certificate issue. Because, I wrote a simple code to just open a secure URL connection with apache httpclient. i.e something like below.
HttpGet httpget = new HttpGet("https://google.com");
HttpResponse response1 = httpclient.execute(httpget);
It worked like a charm for many secure site I tried which needs authentication but not for SAP Business ByDesign system link.
Only for SAP ByD link I get remote host refused to connect error.
Any help is appreciated.
Thanks & best regards,
Hari
Hello All,
I found that, only SAP URLs are not accessible from NW cloud server. I tried opening the SAP service market place URL. It gave me the same error. "Connection Refused".
What could be the issue? Is this because all the systems are in SAP INTRANET? Do i need special settings to connect?
Thanks & best regards,
Hari
Hi Timo,
Thanks your time Here is the code snippet. Basically I am trying to open a http connection.
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
//Here, Ideally I want to use SAP ByDesign system link. But if I try with this link I get the same error message which I get for ByDesign system link.
HttpGet httpget = new HttpGet("http://service.sap.com/support");
System.out.println("executing request" + httpget.getRequestLine());
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
}
finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}
when this code is run local server, I get HTTP 401 Unauthorized error, as I didnt provide any credentials. But when run in NW/HANA Cloud server, then I get Connection Refused error.
Best regards,
Hari
Hi Hari,
sorry for the late reply, was out of office for some days.
As the Connection Refused occurs now with HTTP, it can't be related to the SSL handshake. Maybe there is a problem with blocked ports... I have created an intneral bug ticket for this for further analysis. We will update this blog once we know the reason and a solution.
Best regards,
Timo
Hi Hari,
the reason for getting different behaviour with local server and in the cloud is in the wrong proxy settings you use with httpclient in the cloud - try using the default VM proxy like this:
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(httpclient.getConnectionManager().getSchemeRegistry(),
ProxySelector.getDefault());
httpclient.setRoutePlanner(routePlanner);
Best Regards,
Vasil
Hi Hari,
please have a look to Vasil's reply above regarding the "Connection Refused" problem which is related to the proxy setting.
Once you apply his hint, you should be back to the SSLHandshakeException. For now, I propose that you use the workaround with the DummyTrustManager discussed further above which basically avoids to validate the SSL server certificate. Of course, this is not nice. But the good think is that we can provide you a sound solution very soon. We are very close to release a new feature which allows uploading key stores which then can be used in custom TrustManagers. We will provide an official documentation how to use this soon.
Best regards,
Timo
Hi Timo, Vasil,
Thanks a lot!!! I am able to establish a HTTP connection to SAP URLs by routing to default proxy.
However, I still have a problem here. I can't rely on HTTPClient.setRoutePlanner always. That's because, I am using JAX-WS libraries for the SOAP call. The HTTP connections are handled internally by the libraries. How to force the SOAP call made by JAX-WS to use that default proxy?
I tried using ProxySelector.getdefault(), System.setProperty(httpsHost, "PROXY Host Name"), etc. in my code. But none forces the SOAP call to the default proxy.
So how to set a default route which will be used by all HTTP connections in my app?
Thanks again for spending time to debug and provide me a solution That gave life for me
Best regards,
Hari
Hi Venki,
Specifying a proxy for HttpClient worked. But how to specify a proxy at application level? Because, I am using JAX-WS libraries to call the web service. So I don't know how the Http connection is handled by that framework.
So only way is to force all the HTTP connection made by the app to a proxy. How to do that?
Please look at my last reply below for more detail.
Best regards,
Hari
Hi Vasil, Timo,
Once again I am here with the same issue. Sorry for coming back late.
After Vasil had provided the above answer, it worked for the SAP URLs. But still it didn't work for any SAP OnDemand systems. I.e. When I try to establish a connection to my SAP Business ByDesign system, I got Connection Refused or Remote Host Closed Connection during Handshake error.
What I think could be a problem is, the target system is not at all reached first. The HANA Cloud server is not routing to the default VM proxy for this particular URL. Why is it so difficult to connect a SAP Business ByDesign system? What I am still missing?
Please help me to solve it. Your help is really appreciated!
Below is my Servlet code.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Trust All
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string)
throws CertificateException {}
public void checkServerTrusted(X509Certificate[] xcs, String string)
throws CertificateException {}
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws java.security.cert.CertificateException {}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws java.security.cert.CertificateException {}
};
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new X509TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ClientConnectionManager ccm = httpclient.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", ssf, 443));
httpclient = new DefaultHttpClient(ccm, httpclient.getParams());
//Set Route to Default PROXY
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(httpclient.getConnectionManager().getSchemeRegistry(),
ProxySelector.getDefault());
httpclient.setRoutePlanner(routePlanner);
//Target URL
HttpGet httpget = new HttpGet("https://my******.sapbydesign.com");
System.out.println("executing request" + httpget.getRequestLine());
HttpResponse response1 = httpclient.execute(httpget);
HttpEntity entity = response1.getEntity();
");
System.out.println(response1.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
httpclient.getConnectionManager().shutdown();
}
}
Best regards,
Hari
Hi hari,
Just wondering if you did get this to work eventually....seems like you did however i am having an issue as below.
1. I am also trying to consume a ByD SOAP Service, that is secured.
2. I am getting the exception as shown below.
SSL: peer not authenticated. it happens on getPeerCertificates method call....
3. I have tried all options and logs confirm that it seems to be doing everything right however a SSLHandshake fails. Clearly seems that the Hana server doesn't trust the ByD instnace as the SSL Cert is not availabe within it's keystore. so it seems to me anyway.
logs do suggest that it's using the proxy as well so it is routing via the HAHA proxy mechanism as well.
4. I have also tried to create own keystore and import the ByD SSL Cert into it and then import the keystore into the HANA Server. I can see it's available at the account level.
Also,
5. When i try to use this keystore to secure the message, it throws an exception that it can't find the keystore.
My questions:
1. Is HANA Cloud Trial vs non trial function differently? i am using the trial account ofcourse hence my thoughts.
2. I can't think of anything else missing here however
Very interested to find out how this works when you are running. Have you made any progress?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Hari,
which Java library do you use for your SOAP call?Can you add the relevant code where you do the call to this discussion?
To me, it looks like a problem with the SSL handshake, e.g. the relevant certificates are not available in your cloud app or not trusted. Have you configured trust in the local scenario somehow different as in the cloud scenario?
Best regards,
Timo
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Timo,
Thanks for your quick reply
I have used Apache CFX to generate the JAVA client code for my web service. I used BindingProvider Interface to provide the credentials for SOAP message level authentication. Below is the servlet code.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Target namespace of my WSDL
final QName SERVICE_NAME = new QName("http://sap.com/TEST_SOL", "service");
//My WSDL path is set here
URL wsdlURL = Service.WSDL_LOCATION;
Service ss = new Service(wsdlURL, SERVICE_NAME);
ZBY005816ManageWStestboIn port = ss.getBinding(); //Getting the port of details
//Setting User name and Password
//When the endpoint is reached, the below credentials are used. If i don't use the below code, I get "Http 401 Unauthorised" error in Local server.
BindingProvider provider = (BindingProvider) port;
provider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "MyUserName");
provider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "Password");
//Calling web service operations (in this case a BO query)
System.out.println("Invoking query...");
WSTEST.WStestboQuerySimpleByRequestMessageSync _query_wStestboQuerySimpleByRequestSync = null;
try {
//Calling the query operation
WSTEST.WStestboQuerySimpleByConfirmationMessageSync _query__return = port.query(_query_wStestboQuerySimpleByRequestSync);
System.out.println("query.result=" + _query__return);
//Posting the response
response.setContentType("text/html");
for (int i=0; i<_query__return.wStestbo.size(); i++){
response.getWriter().println("ID:"+" "+_query__return.wStestbo.get(i).id);
response.getWriter().println("Name:"+" "+_query__return.wStestbo.get(i).name);
}
}
To test the web service call in SAP NW Cloud server, I used a public WSDL(weather wsdl) and generated the JAVA client code using Apache CFX. I implemented the client in the same way as above. Except I didnt give user name and password. Because the WSDL endpoint doesnt need any authentication. In this case it works fine. The server is reaching the endpoint and getting the response successfully. Only when a WSDL end point needs authentication then this error happens.
The below links gives an overview of connectivity in NW cloud. But couldnt get any clue how to achieve this in my case.
https://help.netweaver.ondemand.com/help/frameset.htm?e4f1d97cbb571014a247d10f9f9a685d.html
https://help.netweaver.ondemand.com/help/frameset.htm?e592cf6cbb57101495d3c28507d20f1b.html --> this link says we need to set up the connectivity configurations in server (local/NW Cloud) to use an internet service. But I didnt setup any and still it worked for the weather application. It reached the endpoint and returned the response like charm.
Thanks & regards,
Hari
User | Count |
---|---|
94 | |
11 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.