cancel
Showing results for 
Search instead for 
Did you mean: 

How to consume a secure web service (SOAP webservice) in SAP Netweaver Cloud server?

Former Member
0 Kudos

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

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

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

Answers (3)

Answers (3)

former_member203148
Discoverer
0 Kudos

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..

Former Member
0 Kudos

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

Former Member
0 Kudos

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

Former Member
0 Kudos

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

Former Member
0 Kudos

Hi Hari,

could you tell the concrete URL + port you are using + provide the code snippet where the connection is done? I can try to reproduce this locally.

Thanks, Timo

Former Member
0 Kudos

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

Former Member
0 Kudos

Hi Timo,

Did you get a chance to look at this issue?

Thanks & regards,

Hari

Former Member
0 Kudos

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

Former Member
0 Kudos

Hi Timo,

Many thanks for the update 🙂

I will wait for your next update.

Best regards,

Hari

Former Member
0 Kudos

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

Former Member
0 Kudos

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

0 Kudos

Hi:

Did you check if the ByD system is behind the firewall? Also in your HttpClient can you try specifying a proxy host and see if it works?

Best regards

Venki

Former Member
0 Kudos

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

Former Member
0 Kudos

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

Former Member
0 Kudos

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


Sumi
Explorer
0 Kudos

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

Former Member
0 Kudos

Very interested to find out how this works when you are running. Have you made any progress?

Former Member
0 Kudos

Hi Gene,

I am little busy with other work. So couldnt spend time on this. Will resume this activity this weekend.

Will keep you posted!

Best regards,

Hari

Former Member
0 Kudos

Wonderful! I'm a .Net kind of guy and learning more and more about JAVA. Same areas I need to really pick up are learning how to talk to webservice systems and then pushing that out to the UI via SAPUI5. Getting there little by little so anything I can pick up on is great

Former Member
0 Kudos

Same here. First time coding something in JAVA directly in SAP NW platform If you are successful in achieving the above task in future then please let me know

Former Member
0 Kudos

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

Former Member
0 Kudos

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