Saturday, 27 September 2014

Apache HttpClient tutorial

Background

Assuming you know what REST or Restful APIs (GET, POST etc) are in this post we will cover how can we make these REST calls with Java program.  As the title of the post suggests the library that we are going to use is  - Apache HttpClient

To test the same REST calls we can use the CURL command line utility. You can learn how to do so from my previous posts on CURL

  1. Download and Install cURL on Windows 
  2. Using HTTP POST and GET using cURL

Dependency

We need to include the Apache HTTP client library in the code. I always use Ivy as a dependency manager for my java programming.

 My Ivy file looks like - 

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
    <info
        organisation="OpenSourceForGeeks"
        module="Demos"
        status="integration">
    </info>
    
    
    <dependencies>
        <dependency org="org.apache.httpcomponents" name="httpclient" rev="4.3.1"/>        
    </dependencies>
    
</ivy-module>


Note : Whenever you want to add any dependency in any dependency Manager like Maven, Ivy, gradle etc you can search the library in Maven Repository.

Code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;


/**
 * 
 * @author athakur
 *
 */
public class HttpClientDemo
{
    
    private static final String USER_AGENT = "Mozilla/5.0";
    private static final int TIMEOUT = 5000;
    
    public static void main(String args[])
    {
        
        HttpClient httpClient = new DefaultHttpClient();
        
        HttpClientDemo httpClientDemo = new HttpClientDemo();
        HttpParams httpParams = httpClient.getParams();
        httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIMEOUT);
        httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, TIMEOUT);
        
        String getResponse = httpClientDemo.performGetRequest(httpClient, "http://www.google.co.in");
        System.out.println("GET Response : " + getResponse);
        String postResponse = httpClientDemo.performPostRequest(httpClient, "http://www.google.co.in");
        System.out.println("GET Response : " + postResponse);
    }
    

    private String performGetRequest(HttpClient httpClient, String url)
    {
        HttpGet httprequest = new HttpGet(url);
        httprequest.addHeader("User-Agent", USER_AGENT);

        
        try {
            System.out.println("Performing GET request on + " + url);
            HttpResponse httpResponse = httpClient.execute(httprequest);
            System.out.println("Status code : " + httpResponse.getStatusLine().getStatusCode());
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));

            StringBuffer requestResult = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                requestResult.append(line);
            }
            
            return requestResult.toString();
      
        }
        catch (IOException e) {
            System.out.println("Exception occurred while performing GET request");
            e.printStackTrace();
            return null;
        }
        finally {
            httprequest.releaseConnection();
        }
    }
    
    private String performPostRequest(HttpClient httpClient, String url)
    {
        HttpPost httprequest = new HttpPost(url);
        httprequest.addHeader("User-Agent", USER_AGENT);
        
        List<NameValuePair> urlPostParameters = new ArrayList<NameValuePair>();
        urlPostParameters.add(new BasicNameValuePair("key", "value"));
     
        try {
            httprequest.setEntity(new UrlEncodedFormEntity(urlPostParameters));
        }
        catch (UnsupportedEncodingException e1) {
            // TODO Auto-generated catch block
            System.out.println("Encoding not supported");
            e1.printStackTrace();
            return null;
        }

        
        try {
            System.out.println("Performing POST request on + " + url);
            HttpResponse httpResponse = httpClient.execute(httprequest);
            System.out.println("Status code : " + httpResponse.getStatusLine().getStatusCode());
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));

            StringBuffer requestResult = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                requestResult.append(line);
            }
            
            return requestResult.toString();
      
        }
        catch (IOException e) {
            System.out.println("Exception occurred while performing POST request");
            e.printStackTrace();
            return null;
        }
        finally {
            httprequest.releaseConnection();
        }
    }
    
    
}

Output

Performing GET request on + http://www.google.co.in
Status code : 200
GET Response : <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-IN">...
Performing POST request on + http://www.google.co.in
Status code : 405
GET Response : <!DOCTYPE html><html lang=en>  .......

Note :  POST call will not return valid output (200 status code). We got 405 (method not allowed) for post request because POST is not a valid method type for URL http://www.google.com. It only accepts a GET request.

Setting Timeout

Just for the record - 

HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIMEOUT);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, TIMEOUT);


is alternate way to do

HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT);
 
With new APIs introduced in version 4.3 we can do

RequestConfig requestConfig = RequestConfig.custom()
  .setConnectTimeout(TIMEOUT)
  .setConnectionRequestTimeout(TIMEOUT)
  .setSocketTimeout(TIMEOUT).build();
CloseableHttpClient client =
  HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();

Understanding Timeouts - 

  • Connection Timeout – Time to establish the connection with the remote host.
  • Socket Timeout  – Time waiting for response of a request – after the connection is established.
  • Connection Manager Timeout  – Time to wait for a connection from the connection manager/pool .

Refer to following diagram to understand how REST APIs work -



Related Links


Sunday, 21 September 2014

How to install Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files

Problem

JCE has been integrated into the Java 2 SDK since the 1.4 release.

Below diagram shows a general overview of Java cryptographic architecture. What we are discussing in this post is related to JCE implementation provided by Sun/Oracle.




As per the Oracle documentation - 

Due to import control restrictions by the governments of a few countries, the jurisdiction policy files shipped with the JDK 5.0 from Sun Microsystems specify that "strong" but limited cryptography may be used.

 That mean JDK has a deliberate key size restriction by default. So you cannot perform an encryption with key more than 128 bits (16 bytes). If you do you will get an error something like -

Caused by: java.security.InvalidKeyException: Illegal key size or default parameters

If you get this Exception there is nothing wrong that you are doing. It's just the restriction on the encryption key that comes built into the JDK.

The reason for this is that some countries have restrictions on the permitted key strength used in encryption algorithms.

Again as per the documentation - 

An "unlimited strength" version of these files indicating no restrictions on cryptographic strengths is available for those living in eligible countries (which is most countries). But only the "strong" version can be imported into those countries whose governments mandate restrictions. The JCE framework will enforce the restrictions specified in the installed jurisdiction policy files.


Update -  Updates Since Java 8 and Java 9

There have been multiple updates since Java 8 and 9. Before you dive down into more details review this section based on the Java version you are using. I have shown how to resolve this issue with various Java versions in the video below. 




Java 9 and higher :


The Unlimited Strength Jurisdiction Policy Files are included with Java 9 and used by default (see Security Updates in the Java 9 Migration Guide).

If you get this error with Java 9, it might mean the policy configuration has been changed to a more restrictive policy (limited), see the instructions from the migration guide:

It states -

JCE Jurisdiction Policy File Default is Unlimited

If your application previously required the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files, then you no longer need to download or install them. They are included in the JDK and are activated by default.

If your country or usage requires a more restrictive policy, the limited Java cryptographic policy files are still available.

If you have requirements that are not met by either of the policy files provided by default, then you can customize these policy files to meet your needs.

See the crypto.policy Security property in the  <java-home>/conf/security/java.security file, or Cryptographic Strength Configuration in the Java Platform, Standard Edition Security Developer's Guide.

Java 8 Update 161 and higher

Starting with Java 8 Update 161, Java 8 defaults to the Unlimited Strength Jurisdiction Policy. If you receive this error, it could indicate the configuration has been changed to limited. See instructions in the next section on Java 8 Update 151, or the previous section on Java 9, for changing this back to unlimited.

Java 8 Update 151 and higher

Starting with Java 8 Update 151, the Unlimited Strength Jurisdiction Policy is included with Java 8 but not used by default. To enable it, you need to edit the java.security file in <java_home>/jre/lib/security (for JDK) or <java_home>/lib/security (for JRE). Uncomment (or include) the line

crypto.policy=unlimited
Make sure you edit the file using an editor run as administrator.

The policy change only takes effect after restarting the JVM (this is especially important for long-running server processes like Tomcat).

For backward compatibility, installing the policy files as documented in the next section will still work as well.


Before Java 8 Update 151 - Removing the maximum key size restriction

You can remove the maximum key restriction by replacing the existing JCE jars with unlimited strength policy jars.

 Download the zip file extract the jars and replace them in your JDK/JRE.

For this Copy local_policy.jar and US_export_policy.jar extracted from above zip file to the $JAVA_HOME/jre/lib/security 

Note: These jars will already be present there so you will have to overwrite them.

Then simply restart your java application and the Exception should be gone.

NOTE: If you are using Ubuntu and the webupd8 PPA, you can simply run -

  • apt-get install oracle-java8-unlimited-jce-policy

 An alternate way to maximum encryption key size problem

This way is really a workaround. In fact, this approach is the workaround to all problems and it's not straightforward. Yeah you must have guessed it by now - Reflection

You can override the restriction with Reflection as follows - 

try {
    Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
    field.setAccessible(true);
    field.set(null, java.lang.Boolean.FALSE);
   } catch (Exception ex) {
      ex.printStackTrace();
   }

Note 1: I do not recommend the Reflection approach as it's hacky. If you are using it keep it for testing only. Don't put it in production code :)

Note 2: As the change of replacing policy files is in JDK itself you will have to do it in all your servers. Also, you will have to ask all your clients to do so.

Finding the maximum possible key length

To find maximum key length allowed by an encryption algorithm you can use Cipher.getMaxAllowedKeyLength() method.  For example, for AES algorithm you can do - 

int maxKeyLength = Cipher.getMaxAllowedKeyLength("AES");


Related Links

How to exclude Outlook results from the Start Menu search in Windows 7

Background

If you are using Microsoft outlook as your Email client you would have noticed when you search from your Start button Outlook search results appear. Sometime it gets really irritating when we are searching for something specific and irrelevant outlook searches block the space. Outlook itself had very good search workflow integrated. My personal feeling is that we don't need it unless we are searching mails everyday from start menu. In this post we will see how we can remove outlook results from Windows 7 Start Menu search.

Have picked the following image from google search just to demonstrate how the results appear - 


Excluding Outlook results from Start Menu Search

  1. Click in Start button.
  2. Search for indexing options and click on it.

  3. Select Modify.
  4. Uncheck Microsoft outlook and press ok.


  5. Close the indexing options box.
  6. Outlook searches should no longer appear in Win 7 start menu searches.

Starting and Stopping process in Windows from command Line

Background

In Windows it's all UI. Most people just double click on the icons or shortcuts to run the programs. Click on the cross icon to close it. Though it makes life easier as a programmer we should also know how to do the same using command line. Specially if you are wiring a program to do such a thing. In Linux/Unix it's quite easy. To start a process simply add it to the PATH and call the process. For example simply open the console and type 'firefox'. That should launch firefox  for you. If you want to stop the process you can execute kill -9 processId. Lets see how can we do the same in Windows.

Prior to starting to lean command lets see how can we open the command line - 

One way is
  1. Press Ctrl + R . This should open the "Run" prompt for you.
  2. In this prompt type "cmd" (without quotes) and hit enter.


Or you can open it from start button .
  1. Click on start button.
  2. Search for cmd or command and you should see cmd.exe or command prompt. Both are same. Click on it.


Note if you want to perform some administrative action you need to start the command prompt as Administrator  . To do so -
  1. Click on start button
  2. Search for cmd or command. Right click on cmd.exe or command prompt  and select Run as Administrator.

Getting PID of a process

  1. To get PID of a process is Windows command is tasklist. (Like in Linux we have ps command) 
  2. You can also get it using wmic (Windows Management Instrumentation Command-line) utility (Get PID of specific process). You need to execute following command (explorer.exe is an example)-

    wmic process where "caption='explorer.exe'" get caption,processId


 

Starting a Process

Starting a process is quite easy. All you have to do is run the following in command line -

start commandName

For example lets say you want to start notepad you can simply type the following in cmd - 

start notepad

Stopping a Process

 One way to stop or terminate Windows process from command line is via the PID of the process. To get the PID use one of the way described in Getting PID of process section  above.
Then to stop a process use the command -

taskill /f /pid pidOfProcess

Complete process (stop and start) of a process is shown in below screenshot -


Important Note : /F option is taskkill denotes force kill. Your unsaved data might be lost!

Note : You can do all the above using Task manager [Ctrl + Shift + Esc] too (UI based). Above method is just a way to do it via command line. It will be specially useful when writing program to execute process like runtime.getruntime().exec() in java.

Saturday, 20 September 2014

Changing Android Launcher

Background

One of the most powerful feature of Android phone according to my opinion is the ability to customize the phone as per your requirements. When you boot up your phone the home screen that you see and the multiple apps screens you see when you click on the Apps shortcut icon (also called apps drawer) together form the launcher. Each Android phone has a default launcher but there are multiple 3rd party launcher Apps available of play store. When people generally talk about "stock Android" their context is about the features provided by the original Android OS (default ones). In this case it would be the default android launcher that comes with the OS provided by Google in the code.


In this post we will see how can we change the launchers in Android.

Launcher you may want to try out


Changing Android Launcher

There are two ways in which we can change the launcher.

  1. For download and install the launcher you want. If you have not tried any launchers before pick one from the above list.
  2. Next go to Apps (Settings -> Apps -> Navigate to All Apps). In this list find the Launcher App (the default one - as shown in the topmost screenshot). Tap on it.
  3. Tap on the Clear Default button. (If this button is greyed out take a look at Notes section below)This should clear your setting for default android launcher.
  4. Next time you click on Home button you will see all the available launchers to select from. You can select the one you have installed. 
  5. Again you will be prompted whether you want this launcher to be used Only once or Always. If you choose Only once you will be prompted to choose Launcher again next time you click on home button.

 

Alternate Way

Alternately there is an easier way to do this. There is Home category under Device section of Settings where you can directly choose your launcher. (If you do not see Home refer to Notes section below)



 

Notes

  1. If your Clear Default button is not clickable (greyed out)  then it means either you have already chosen a non default launcher or you have not installed any launcher (All you have is default one).
  2. If you do not see Home category in Device section of your settings that means you have not installed a Launcher or have never changes it before. Try installing the Launcher. If even now Home is not visible change the launcher using the 1st way (Clear Defaults) and then on you should be able to see the Home Category.
  3. Just for the record If you want your app to be recognized as a launcher it has to listen to tte android.intent.category.HOME intent. So basically when you click on Home button on main screen this intent is fired and all activities listening to this intent are shown. Sample manifest would be

    <activity
        android:name="org.openSourceForGeeks.MyActivity"
        android:label="My Android Launcher"
        android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen"
        android:launchMode="singleTask"
        android:stateNotNeeded="true"
        >
        <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.HOME" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>       
    </activity>


Screenshots of Aviate Launcher from my Moto E










Related Useful Links

t> UA-39527780-1 back to top