Custom Http Servlet Response Wrapper

One day, I had a requirement to change the response before it sent to the client. My application contains many servlet and jsp files so I needed some mechanism to change the response without updating each and every servlet and jsp. I found that this can be handled via custom http servlet response. In this post, I create sample wrapper and filter to give you a brief idea that how I have achieved this. In this sample wrapper, I convert response content to upper case but trust me, a lot can be done here.

Custom response wrapper class

Refer below sample response wrapper class which extends HttpServletResponseWrapper. It overrides getOutputStream() and getWriter()> methods of the super class. From getWriter() method I create PrintWriter object which wrap the instance variable stringWriter. I have declared stringWriter as an instance variable and I return the reference of the same so whatever is written by the servlet or jsp would be written to this stringWriter. Later we can examine/update the content of stringWriter.

package com.elitejavacoder.wrapper;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
*
* @author Atul Prajapati
*
*/
public class CustomResponseWrapper extends HttpServletResponseWrapper{
	private StringWriter stringWriter;
	private boolean isOutputStreamCalled;

	public CustomResponseWrapper(HttpServletResponse response) {
		super(response);
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		if (this.stringWriter != null) {
			throw new IllegalStateException("The getWriter() is already called.");
		}
		isOutputStreamCalled = true;
		return super.getOutputStream();
	}

	@Override
	public PrintWriter getWriter() throws IOException {
		if (isOutputStreamCalled) {
			throw new IllegalStateException("The getOutputStream() is already called.");
		}

		this.stringWriter = new StringWriter();

		return new PrintWriter(this.stringWriter);
	}

	public String getResponseContent() {
		if (this.stringWriter != null) {
			return this.stringWriter.toString();
		}
		return "";
	}
}

Sample filter class

Below is the sample filter which I have used to intercept the request so I can customize whatever content is written by the servlet or jsp. In this filter, I check the parameter “custom” which indicates that content should be customized or not. So we can apply the wrapper dynamically and check it’s effect runtime in browser. If the value of the “custom” parameter is true then the response would be converted to upper case otherwise the response wrapper would not be applied hence the response would be returned as it is.

package com.elitejavacoder.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.elitejavacoder.wrapper.CustomResponseWrapper;

/**
 * Servlet Filter implementation class SimpleFilter
 */
public class SimpleFilter implements Filter {

	public void init(FilterConfig filterConfig) throws ServletException {
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

		boolean custom = false;
		if (request instanceof HttpServletRequest && response instanceof HttpServletResponse && ((HttpServletRequest)request).getParameter("custom") != null) {
			custom = Boolean.parseBoolean(((HttpServletRequest)request).getParameter("custom"));
		}

		if (custom) {
			CustomResponseWrapper wrapper = new CustomResponseWrapper((HttpServletResponse)response);
			filterChain.doFilter(request, wrapper);

			String originalResponse = wrapper.getResponseContent();
			System.out.println("Original Response: " + originalResponse);

			// Let's convert response content to upper case
			response.getWriter().print(originalResponse.toUpperCase());
		}
		else {
			filterChain.doFilter(request, response);
		}
	}

	public void destroy() {
	}
}

I have posted a complete sample application along with the instructions to run it on github. It is available at https://github.com/atulprajapati/samples/tree/master/custom-http-servlet-response-wrapper. You can try it yourself. Your questions and comments are welcome.

Http Client form based authentication

In this post i will explain you how to do form based authentication in Http client. For this tutorial i have used http client 4.1.2 (i.e. httpcomponents).

Form based authentication can be done in three steps as described below.

  1. Access secure page on server. In response to this request you will receive login page with http status code 200. Note that you will receive JSESSIONID cookie with this response which is required for next request.
  2. Now create a post request for “/j_security_check”. Pass j_username and j_password along with this request. In response to this request you will receive blank response with http status code 302. Here htpp status code 302 indicates that login is successful. If you provide wrong username/password then you will receive login page with http status code 200.
  3. Now access secure page on server. In response to this request you will get requested page with http status code 200 because you are authenticated.

Sample code to do form based authentication in Java using http client.

package com.elitejavacoder.http.client;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
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.client.params.ClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpClientFormAuthentication {
    public static void main(String[] agrs) {
        String host = "yourhostname.com";
        int port = 8080;
        String protocol = "http";

        DefaultHttpClient client = new DefaultHttpClient();

        try {
            HttpHost httpHost = new HttpHost(host, port, protocol);
            client.getParams().setParameter(ClientPNames.DEFAULT_HOST, httpHost);

            HttpGet securedResource = new HttpGet("/secured/index.jsp");            
            HttpResponse httpResponse = client.execute(securedResource);
            HttpEntity responseEntity = httpResponse.getEntity();
            String strResponse = EntityUtils.toString(responseEntity);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Unauthenticated Request: " + statusCode);// Statue code should be 200
            System.out.println("Response for Unauthenticated Request: n" + strResponse); // Should be login page
            System.out.println("================================================================n");

            HttpPost authpost = new HttpPost("/j_security_check");
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            nameValuePairs.add(new BasicNameValuePair("j_username", "yourusername"));
            nameValuePairs.add(new BasicNameValuePair("j_password", "yourpassword"));
            authpost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            httpResponse = client.execute(authpost);
            responseEntity = httpResponse.getEntity();
            strResponse = EntityUtils.toString(responseEntity);
            statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Authenticattion Request: " + statusCode);// Status code should be 302
            System.out.println("Response for Authenticattion Request: n" + strResponse); // Should be blank string
            System.out.println("================================================================n");

            httpResponse = client.execute(securedResource);
            responseEntity = httpResponse.getEntity();
            strResponse = EntityUtils.toString(responseEntity);
            statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Authenticated Request: " + statusCode);// Status code should be 200
            System.out.println("Response for Authenticated Request: n" + strResponse);// Should be actual page
            System.out.println("================================================================n");
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

How to sort map by keys/values in Java

This post will explain you how to sort map by keys/values. I have created one Utility class for the same which you can use to sort map by keys or values.

Utility class to sort Map by keys and values

package com.elitejavacoder.util;

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class MapUtility {

    public static <K, V extends Comparable<V>> Map<K, V> sortOnValues(Map<K, V> unsortedMap) {
        Map<K, V> sortedMap = new TreeMap<K, V>(new MapValueComparator<K, V>(unsortedMap));
        sortedMap.putAll(unsortedMap);
        return sortedMap;
    }

    public static <K, V extends Comparable<V>> Map<K, V> sortOnKeys(Map<K, V> unsortedMap) {
        Map<K, V> sortedMap = new TreeMap<K, V>();
        sortedMap.putAll(unsortedMap);
        return sortedMap;
    }

}

class MapValueComparator<K, V extends Comparable<V>> implements Comparator<K> {
    Map<K, V> map;

    MapValueComparator(Map<K, V> map) {
        this.map = map;
    }

	public int compare(K key1, K key2) {
		V value1 = map.get(key1);
		V value2 = map.get(key2);

		return value1.compareTo(value2);
	}
}

Sort Map of java objects by keys and values

Map<String, String> unsortedMap = new HashMap<String, String>();  
unsortedMap.put("1", "Z");
unsortedMap.put("2", "C");
unsortedMap.put("7", "E");
unsortedMap.put("4", "A");
unsortedMap.put("6", "B");
unsortedMap.put("5", "N");
unsortedMap.put("3", "P");

System.out.println("Unsorted Map: " + unsortedMap);

Map<String, String> sortedMapByKeys = MapUtility.sortOnKeys(unsortedMap);
System.out.println("Sorted Map by Keys: " + sortedMapByKeys);

Map<String, String> sortedMapByValues = MapUtility.sortOnValues(unsortedMap);
System.out.println("Sorted Map by Values: " + sortedMapByValues);

Run above sample code which is using map utility to test map sorting on keys and values. You will get following output so we can see that map is sorted as expected.

Unsorted Map: {3=P, 2=C, 1=Z, 7=E, 6=B, 5=N, 4=A}
Sorted Map by Keys: {1=Z, 2=C, 3=P, 4=A, 5=N, 6=B, 7=E}
Sorted Map by Values: {4=A, 6=B, 2=C, 7=E, 5=N, 3=P, 1=Z}

Sort Map of user defined objects by keys and values

To test Map utility against user defined objects I have created Employee class which implements Comparable interface. I have overridden compareTo() method to compare Employee objects on name so Employee objects should be sorted on name. Employee class is as follow:

package com.elitejavacoder.util;

public class Employee implements Comparable&lt;Employee&gt; {
    long id;
    String name;

    Employee(long id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int compareTo(Employee obj) {
        return this.name.compareTo(obj.getName()); // Compare on name
    }
    
    @Override
    public String toString() {
        return this.name;
    }
}

// Sort map of user defined objects
Map<Long, Employee> unsortedMap = new HashMap<Long, Employee>();
unsortedMap.put(new Long(9), new Employee(9, "Ankur"));
unsortedMap.put(new Long(6), new Employee(6, "Sanket"));
unsortedMap.put(new Long(4), new Employee(4, "Devang"));
unsortedMap.put(new Long(7), new Employee(7, "Timir"));
unsortedMap.put(new Long(3), new Employee(3, "Jay"));
unsortedMap.put(new Long(1), new Employee(1, "Atul"));

System.out.println("Unsorted Map: " + unsortedMap);

Map<Long, Employee> sortedMapByKeys = MapUtility.sortOnKeys(unsortedMap);
System.out.println("Sorted Map by Keys: " + sortedMapByKeys);

Map<Long, Employee> sortedMapByValues = MapUtility.sortOnValues(unsortedMap);
System.out.println("Sorted Map by Values: " + sortedMapByValues);

Run above sample code which is using map utility to test map sorting on keys and values. You will get following output so we can see that map is sorted as expected.

Unsorted Map: {1=Atul, 3=Jay, 4=Devang, 6=Sanket, 7=Timir, 9=Ankur}
Sorted Map by Keys: {1=Atul, 3=Jay, 4=Devang, 6=Sanket, 7=Timir, 9=Ankur}
Sorted Map by Values: {9=Ankur, 1=Atul, 4=Devang, 3=Jay, 6=Sanket, 7=Timir}

Replace property values at the time of maven build

This post explains how to replace property values at the time of maven build.

Replace property value in resource files (non-java files) at the time of maven build

Create one resource file filter-test.txt in $PROJECT_HOME/src/main/resources with content as follow.

Hello ${resource.name}

Now add following lines in pom.xml file of your project.

 
<properties>
	<resource.name>RESOURCE</resource.name>
</properties>

<build>  
	<resources>
		<!-- Filter resource files -->
		<resource>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
		</resource>
	</resources>
	....
</build>

Build your project using following command.

mvn clean install

Check content of filter-test.txt file under $PROJECT_HOME/target/classes. It should be as follow.

Hello RESOURCE

Please note that at the time of build ${resource.name} in filter-test.txt file is replaced with “RESOURCE” which we have defined in pom.xml file as property.

Now you can overwrite property value defined in pom.xml file using command line argument at the time of build. Do build using following command.

mvn clean install -Dresource.name=Atul

Check content of the filter-test.txt file under $PROJECT_HOME/target/classes. It should be as follow.

Hello Atul

Replace property value in java files at the time of maven build

Create one FilterTest.java file under $PROJECT_HOME/src/main/java/com/elitejavacoder/test with content as follow.

package com.elitejavacoder.test;

public class FilterTest {

	private static String NAME = "${java.name}";

		public static void main(String[] args) {

		try {
			System.out.println("n Value of name : " + NAME);
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

Now add following lines in pom.xml file of your project.

<properties>
	<java.name>JAVA</java.name>
</properties>

<build>  
	<resources>
		<!-- Filter Java files -->
		<resource>
			<filtering>true</filtering>
			<directory>src/main/java</directory>
			<targetPath>../filtered-sources/java</targetPath>
			<includes>
				<include>**/*.java</include>
			</includes>
		</resource>
	</resources>

	<!-- change default source directory to filtered-sources/java -->
	<sourceDirectory>target/filtered-sources/java</sourceDirectory>
	....
</build>

Please note that in case of java files, we filter java files as resource files and copy them to filtered-sources/java. Then we change default maven source directory to point filtered java files directory using <sourceDirectory>.

Now do a build using following command.

mvn clean install

Run this class to check output. Please note that I have created executable jar so I will run this class using following command from $PROJECT_HOME/target. For information on how to create executable jar please refer this post.

java -jar replace-property-values-at-build-time-1.0.0-SNAPSHOT.jar

The output should be as follow.

Value of name : JAVA

Please note that at the time of maven build, ${java.name} in FilterTest.java is replaced with “JAVA” which we have defined in pom.xml file as property. You can check this in compiled class file as well using any decompiler.

Now you can overwrite this property value defined in pom.xml file using command line argument at the time of build. Do build using following command.

mvn clean install -Djava.name=Atul

Again run this class to check output using following command.

java -jar replace-property-values-at-build-time-1.0.0-SNAPSHOT.jar

The output should be as follow.

Value of name : Atul

I hope this post helps!

How to call Javascript function from Java

Sometime we are in need to call javascript function from Java to reuse the logic of javascript or for better maintainability we don’t want to duplicate that logic in Java. Following example show you how to call javascript function from java.

Following sample Javascript function (available in test.js file) we call from our Java application.

	function sayHello(name) {
		return "Hello " + name;
	}

Sample java code to call javascript function.

package com.elitejavacoder.javascript;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class CallJavascriptFromJava {

	public static void main(String[] args) {
		
		try {
			ScriptEngineManager manager = new ScriptEngineManager();
			ScriptEngine javascriptEngine = manager.getEngineByExtension("js");
			
			// Get script from JS File
			FileInputStream fileInputStream = new FileInputStream("F:developmentjavascripttest.js");
			if (fileInputStream != null) {
				BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
		
				javascriptEngine.eval(reader);
				Invocable invocableEngine = (Invocable)javascriptEngine;
				
				// Invoke javascript function named "sayHello" with parameter "Atul"
				Object object = invocableEngine.invokeFunction("sayHello", new String[]{"Atul"});
				System.out.println("Result: " + object);
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

Above code will print “Result: Hello Atul”.