0

Hi I'm working on an old android project which use org.apache.httpclient class which now depreciated and will be remove from API 22. How do we make a migration to httpUrlConnection but still keep the original functionality? ALl my http POST is now not working with the error

    22 16:16:33.755 5553-6064/com.singPost D/SingPost: payload: <OverseasPostalInfoDetailsRequest xmlns="http://singpost.com/paw/ns"><Country>AFAFG</Country><Weight>100</Weight><DeliveryServiceName></DeliveryServiceName><ItemType></ItemType><PriceRange>999</PriceRange><DeliveryTimeRange>999</DeliveryTimeRange></OverseasPostalInfoDetailsRequest>
08-22 16:16:33.755 5553-6064/com.singPost D/SingPost: Utils-request: https://prdesb1.singpost.com/ma/FilterOverseasPostalInfo
08-22 16:16:35.667 5553-6064/com.singPost E/SingPost: IOException: javax.net.ssl.SSLHandshakeException: Handshake failed
08-22 16:16:35.691 5553-6008/com.singPost E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f67d844e5c0

here is my webservice API call:

public static String callWS(String url, String module, String method, String payload) throws UnsupportedEncodingException, ClientProtocolException, IOException, ParseException, Exception{
        HttpClient httpsClient;
        HttpPost httppost;

        HttpResponse response  = null;
        String ret = "";

        httpsClient = getHTTPSClient();

        String request = url;
        if(!module.equalsIgnoreCase("") && !method.equalsIgnoreCase("")){
            request += "/" +  module + "/" + method;
        }else if(!module.equalsIgnoreCase("")){
            request += "/" +  module;
        }else if(!method.equalsIgnoreCase("")){
            request += "/" +  method;
        }

        if(Constants.DEBUG_MODE){
            Log.d(Constants.TAG, Utils.class.getSimpleName() + "-request: " + request);
        }

        try {

        httppost = new HttpPost(request);
        httppost.setHeader("Content-Type", Constants.contentType);
        if(payload!=null && !payload.equalsIgnoreCase("")){
            httppost.setEntity(new StringEntity(payload, HTTP.UTF_8));
        }
        response = httpsClient.execute(httppost);
        System.out.println("??**"+response.toString());

        if (response != null) {
            ret = EntityUtils.toString(response.getEntity(), "UTF-8");
            System.out.println("Response: "+ret);
            System.out.println("#############################################");

        }
        }catch(SocketTimeoutException e){
            if(Constants.DEBUG_MODE){
                Log.d(Constants.TAG, "SocketTimeoutException: " + e.toString());
            }
        }catch(Exception e){
            //e.printStackTrace();
            if(Constants.DEBUG_MODE){
                Log.d(Constants.TAG, "Exception: " + e.toString());
            }
        }
        return ret;
    }

My getHTTPSClient()

public static DefaultHttpClient getHTTPSClient() {
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));

        HttpParams params = new BasicHttpParams();
        params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
        params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30));
        params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);

        HttpConnectionParams.setConnectionTimeout(params, Constants.DEFAULT_CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(params, Constants.DEFAULT_SOCKET_TIMEOUT);
        ConnManagerParams.setTimeout(params, Constants.DEFAULT_SOCKET_TIMEOUT);
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

        ClientConnectionManager cm = new SingleClientConnManager(params, schemeRegistry);
        DefaultHttpClient httpClient= new DefaultHttpClient(cm, params);
        return httpClient;
    }

And in activity(Fragment), I call like that

result = Utils.callWS(Constants.getSP_WS_URL(), Constants.MODULE_MA, Constants.METHOD_POST_FILTER_OVERSEAS_POSTAL_INFO, payload);

One possile endpoint:

https://prdesb1.singpost.com/ma/FilterOverseasPostalInfo

My checked payload which is correct:

<OverseasPostalInfoDetailsRequest xmlns="http://singpost.com/paw/ns"><Country>AFAFG</Country><Weight>100</Weight><DeliveryServiceName></DeliveryServiceName><ItemType></ItemType><PriceRange>999</PriceRange><DeliveryTimeRange>999</DeliveryTimeRange></OverseasPostalInfoDetailsRequest>

Anyone know possible of the error and how can we handle it? Thanks a lot

Lê Khánh Vinh
  • 2,591
  • 5
  • 31
  • 77

1 Answers1

1

you can try using Volley or similar libraries to get your task done. It's much simpler to use than the old approach. You'll mostly need to re-write the web service calls, but I can guarantee that it won't be as difficult as what you've already done! Here's a tutorial on how to use Volley. It's very easy to get started with.

Following is a simple example as given on their website on how to use Volley. https://developer.android.com/training/volley/requestqueue.html

RequestQueue mRequestQueue;

// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap

// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());

// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);

// Start the queue
mRequestQueue.start();

String url ="http://www.example.com";

// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
        new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Do something with the response
    }
},
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // Handle error
    }
});

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
Ruchira Randana
  • 4,021
  • 1
  • 27
  • 24
  • Thanks, Will dig into this. What is your preference between Volley and Retrofit? – Lê Khánh Vinh Aug 22 '16 at 10:51
  • Hi I have tried rebuild my API call using volley but still have same error. Can help me take a look. Many thanks http://stackoverflow.com/questions/39078888/volley-android-javax-net-ssl-sslhandshakeexception-handshake-failed – Lê Khánh Vinh Aug 22 '16 at 11:55
  • Hi, One possible issue may be due to issues with the SSL certificate configuration on your server. Can you try the same without https? Try using only http and not https. I used the online https://www.ssllabs.com/ssltest tool to see your site's SSL status. From its results, it seems okay. But there seems to be some security issues which you should address anyway. I recommend that you first try this without SSL and let me know. Thanks. – Ruchira Randana Aug 23 '16 at 08:27
  • Hi I have made a question on this:http://stackoverflow.com/questions/39078888/volley-android-javax-net-ssl-sslhandshakeexception-handshake-failed. Strange is only android 6+ API 23 have the error. API 22 and bellow dont have any issue. How do we try witout SSL? – Lê Khánh Vinh Aug 23 '16 at 08:35