A Simple Multi-Threaded Java HTTP Proxy Server

No Gravatar

This post is to show an example of a simple multi-threaded Java HTTP Proxy Server. This sample is not fully functional for every application. It’s very simple and works fine for HTTP GET requests, but is not coded to properly handle HTTP POST requests (nor any other HTTP methods). This is strictly as an example to show how simple it is to proxy requests. This one simply records the url of all requests that are passed through it. Please let me know if you have any questions, and feel free to steal it and improve on it. Let me know what you come up with.

This first bit of code is the actual multithreaded server. It simply starts up the proxy server on a given port, takes in an HTTP request, and spawns off the request to a new thread passing the socket to the thread, and starts that thread on the request.


package proxy;

import java.net.*;
import java.io.*;

public class ProxyServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        boolean listening = true;

        int port = 10000;	//default
        try {
            port = Integer.parseInt(args[0]);
        } catch (Exception e) {
            //ignore me
        }

        try {
            serverSocket = new ServerSocket(port);
            System.out.println("Started on: " + port);
        } catch (IOException e) {
            System.err.println("Could not listen on port: " + args[0]);
            System.exit(-1);
        }

        while (listening) {
            new ProxyThread(serverSocket.accept()).start();
        }
        serverSocket.close();
    }
}


This is the real meat of the application. However, it’s still a fairly simple class. It’s a thread that starts up, then receives the incoming request from the client, resends the request to the real server that the client intended to send it to (while logging the request), then receives the response from the real server, and propogates that same response to the client. Fairly simple process.


package proxy;

import java.net.*;
import java.io.*;
import java.util.*;

public class ProxyThread extends Thread {
    private Socket socket = null;
    private static final int BUFFER_SIZE = 32768;
    public ProxyThread(Socket socket) {
        super("ProxyThread");
        this.socket = socket;
    }

    public void run() {
        //get input from user
        //send request to server
        //get response from server
        //send response to user

        try {
            DataOutputStream out =
		new DataOutputStream(socket.getOutputStream());
            BufferedReader in = new BufferedReader(
		new InputStreamReader(socket.getInputStream()));

            String inputLine, outputLine;
            int cnt = 0;
            String urlToCall = "";
            ///////////////////////////////////
            //begin get request from client
            while ((inputLine = in.readLine()) != null) {
                try {
                    StringTokenizer tok = new StringTokenizer(inputLine);
                    tok.nextToken();
                } catch (Exception e) {
                    break;
                }
                //parse the first line of the request to find the url
                if (cnt == 0) {
                    String[] tokens = inputLine.split(" ");
                    urlToCall = tokens[1];
                    //can redirect this to output log
                    System.out.println("Request for : " + urlToCall);
                }

                cnt++;
            }
            //end get request from client
            ///////////////////////////////////

            BufferedReader rd = null;
            try {
                //System.out.println("sending request
		//to real server for url: "
                //        + urlToCall);
                ///////////////////////////////////
                //begin send request to server, get response from server
                URL url = new URL(urlToCall);
                URLConnection conn = url.openConnection();
                conn.setDoInput(true);
                //not doing HTTP posts
                conn.setDoOutput(false);
                //System.out.println("Type is: "
			//+ conn.getContentType());
                //System.out.println("content length: "
			//+ conn.getContentLength());
                //System.out.println("allowed user interaction: "
			//+ conn.getAllowUserInteraction());
                //System.out.println("content encoding: "
			//+ conn.getContentEncoding());
                //System.out.println("content type: "
			//+ conn.getContentType());

                // Get the response
                InputStream is = null;
                HttpURLConnection huc = (HttpURLConnection)conn;
                if (conn.getContentLength() > 0) {
                    try {
                        is = conn.getInputStream();
                        rd = new BufferedReader(new InputStreamReader(is));
                    } catch (IOException ioe) {
                        System.out.println(
				"********* IO EXCEPTION **********: " + ioe);
                    }
                }
                //end send request to server, get response from server
                ///////////////////////////////////

                ///////////////////////////////////
                //begin send response to client
                byte by[] = new byte[ BUFFER_SIZE ];
                int index = is.read( by, 0, BUFFER_SIZE );
                while ( index != -1 )
                {
                  out.write( by, 0, index );
                  index = is.read( by, 0, BUFFER_SIZE );
                }
                out.flush();

                //end send response to client
                ///////////////////////////////////
            } catch (Exception e) {
                //can redirect this to error log
                System.err.println("Encountered exception: " + e);
                //encountered error - just send nothing back, so
                //processing can continue
                out.writeBytes("");
            }

            //close out all resources
            if (rd != null) {
                rd.close();
            }
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
            if (socket != null) {
                socket.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Hope you enjoy and learn a little from how simple it is in Java to perform network requests, as well as multi-threading to create a somewhat useful application that can be easily extended to be much more useful. Hope this helps.

A session size monitoring servlet

No Gravatar

This is a quick example of a servlet that will tell you the size of your session. This is helpful if you don’t have the tools built into your development suite to give you this information. I found this laying around that I had written a while back. It essentially is a simple servlet that grabs all the session attributes and writes out each to a ObjectOutputStream object. It then takes the size of the ByteArrayOutputStream object contained in the ObjectOutputStream object and displays that.


public class HttpSessionSizeServlet extends HttpServlet {
    private static Logger log = LogFactory.
	getLogger(HttpSessionSizeServlet.class);
    public void doGet(HttpServletRequest req,
		HttpServletResponse resp)
		throws ServletException, IOException {
        HttpSession session = req.getSession();
        if (session != null) {
            Enumeration e = session.getAttributeNames();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream s = new ObjectOutputStream(bos);

            while (e.hasMoreElements()) {
                Object o = session.getAttribute((String) e.nextElement());
                s.writeObject(o);
                s.flush();
            }
            log.info("size = " + bos.size());
        }
    }

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException {
        //do nothing
    }
}

Hope this helps.

Writing a custom generic exception handler in Struts

No Gravatar

Exception handling in Struts is a very simple concept to grasp, once you know the tool that Struts has put in place to handle it. This tool is the org.apache.struts.action.ExceptionHandler . The ExceptionHandler mechanism allows you to configure it in the struts-config.xml file and then Struts will automagically pass any exception type it’s configured to handle to it at runtime. Here’s a simple example of how easy it is to create one of these classes .


package myapp.exc;

import org.apache.struts.action.ExceptionHandler;
//other struts imports

public class MyExceptionHandler extends ExceptionHandler {
  public ActionForward execute( Exception ex,
                              ExceptionConfig exConfig,
                              ActionMapping mapping,
                              ActionForm formInstance,
                              HttpServletRequest request,
                              HttpServletResponse response
  ) throws ServletException {
    //send email to support that something happened w/ stack trace included
    //print stack trace to logs
    ex.printStackTrace();
    return mapping.findForward("login");
  }
}

This method takes in several parameters (including the request/response objects) and returns the forward to where you want to take the user. After setting your class up, all you’ve got to do now is configure it in the struts-config.xml file. You add it to the global-exceptions section. Here’s an example of how to do that for 2 different handlers for 2 different types of exceptions.



  

  

As you can see, you can easily use what Struts has provided to setup a flexible declarative exception handling model for your application.

Hope this helps.

Writing a custom role based access control framework that integrates with Struts

No Gravatar

This article will tell you a fairly simple way to put a custom access control framework in place for your J2EE application that will let you integrate it with the struts framework role based access control protection mechanisms. There are a few pieces to this solution:
1. A storage mechanism for the accesses (roles) per user
2. Writing these accesses into the HttpSession per user (generally in the form of an easily accessible object with helper functions on the session)
3. Override the processRoles method of the struts RequestProcessor class in order to recognize your custom roles
4. Add roles=”…” to your struts actions to protect them based on the configured roles

Ok, in order then, here we go.

For #1 – this is usually done via a relational database – whatever application database you’re using, you’ll generally store the accesses for a given user. However, you could store these in flat files, ldap, or some other mechanism if you wanted to – that’s up to you.

For #2 – here’s an object you can use to hold the roles.


public class UserAccesses {
    private String userName;
    private String[] roles;

    public UserAccesses(String userName, String[] roles) {
        this.userName = userName;
        this.roles = roles;
    }

    public boolean hasRole(String role) {
        if (roles.length > 0) {
            for (int i = 0; i < roles.length; i++) {
                if (role.equals(roles[i]))
                    return true;
            }
        }
        return false;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer(1024);
        sb.append(userName);
        sb.append(" has roles: ");
        for(int i=0; i

This object stores a string array of the role names per user. Now here's some code to write this object into the session. This code should be called when the user logs into the application.


    List allAccessesList = new ArrayList();
    //if the user has the write stories access from the db
    allAccessesList.add(Constants.WRITE_STORIES);
    //if the user has the read stories access from the db
    allAccessesList.add(Constants.READ_STORIES);
    //if the user has the delete stories access from the db
    allAccessesList.add(Constants.DELETE_STORIES);

    String[] allUserAccesses =
	(String[])allAccessesList.toArray(new String[0]);
    UserAccesses userAccessesObj =
	new UserAccesses (userId, allUserAccesses);
    HttpSession session = request.getSession();
    session.setAttribute(Constants.USER_SESSION_ACCESSES, userAccessesObj);

On to #3 - here you have to write a custom class that overrides the processRoles method of the RequestProcessor class in struts


public class RolesRequestProcessor extends RequestProcessor {
    private static final Logger log =
	LogFactory.getLog(RolesRequestProcessor.class);
    public RolesRequestProcessor() {
        super();
    }

    /**
     * @see org.apache.struts.action.RequestProcessor
     *		#processRoles(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse,
     *      org.apache.struts.action.ActionMapping)
     */
    protected boolean processRoles(HttpServletRequest request,
		HttpServletResponse response, ActionMapping mapping)
        	throws IOException, ServletException {

        //Obtain the list of roles from action config
        String roles[] = mapping.getRoleNames();
        if ((roles == null) || (roles.length < 1)) {
            log.debug("No role is required for running this operation.");
            return (true);
        }
        //verify user possesses role
        StringBuffer sb =
		new StringBuffer("Check for required roles ....... n");

        //checking in ldap roles
        for (int i = 0; i < roles.length; i++) {
            sb.append(roles[i]);
            sb.append(", ");

            if (request.isUserInRole(roles[i])) {
                sb.append("Found a matching role in the ldap roles: " + roles[i]);
                return (true);
            }
        }

        // checking in custom database roles
        // Check the current user against the list of required roles
        HttpSession session = request.getSession();
        UserAccesses userAccessesObj = (UserAccesses )
        	session.getAttribute(Constants.USER_SESSION_ACCESSES);
        if (userAccessesObj == null) {
            return false;
        }
        for (int i = 0; i < roles.length; i++) {
            if (userAccessesObj .hasRole(roles[i])) {
                sb.append("Found a matching role in the custom roles: " + roles[i]);
                return (true);
            }
        }
        //end custom roles check

        //invoke declarative exception handling
        sb.append("n");
        sb.append("User does not have the required role");
        log.debug(sb.toString() + " ");
        ActionForward forward = null;
        try {
            forward = processException(request, response,
                new my.application.AuthorizationViolationException(),
		null, mapping);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        // forward user to the authorization error page...
        if (forward != null) {
            log.info("Forward to authorization error page");
            processForwardConfig(request, response, forward);
        }
        return (false);
    }
}

Finally #4 - here you just add the roles attribute to your struts configuration in order to get struts to check for the specified role(s) (multiple roles, is just a comma-delimeted group) to allow a user to perform a given action.


    
        
    

This process has worked very well on my projects, and hopefully will on yours as well.

Hope this helps.

Transactions With Spring in Java

No Gravatar

This post will show you how to write the code to perform transaction handling in Java using the Spring framework. There are certainly many varied ways to handle this, but this is one that I’ve found works fairly well and tends to lead to a fairly clean code base.
The code below essentially forces the block of code all to occur within a transaction, and either causes the transaction to go through with a commit (assuming everything went well), or rolls it all back if anything failed. In this particular case, there are multiple stored procedures being called that all need to pass for the entire process to be valid. It’s true that this could all be handled in one procedure, but that could make the parameters very ugly. In this situation, I think it’s better to have multiple procedures called within one transaction in the java code.


public boolean saveUser(User user){
	boolean success = false;

	DefaultTransactionDefinition def = new DefaultTransactionDefinition();
	def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

	TransactionStatus status = transactionManager.getTransaction(def);
	Map results = null;

	try{
		LinkedHashMap inputTypesMap = new LinkedHashMap();
		inputTypesMap.put(Constants.USER_ID,new Integer(Types.INTEGER));
		inputTypesMap.put(Constants.FIRST_NAME,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.LAST_NAME,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.PHONE_NUMBER,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.EMAIL_ADDRESS,new Integer(Types.VARCHAR));
		LinkedHashMap outputTypesMap = new LinkedHashMap();
		AdminStoredProcedure prc =
			new AdminStoredProcedure(ds,Constants.USER_SAV_PROCEDURE_NAME,
				inputTypesMap,outputTypesMap,null);
		LinkedHashMap inputValuesMap = new LinkedHashMap();
                inputValuesMap.put(Constants.USER_ID, user.getUserId());
		inputValuesMap.put(Constants.FIRST_NAME,contact.getContactFirstName());
		inputValuesMap.put(Constants.LAST_NAME,contact.getContactLastName());
		inputValuesMap.put(Constants.PHONE_NUMBER,contact.getPhoneNumber());
		inputValuesMap.put(Constants.EMAIL_ADDRESS,contact.getEmailAddress());

		results = prc.execute(inputValuesMap);

		//another procedure call, hence the need for the transaction
		userService.deleteUserGroupAssociation(user.getUserId());
		int[] contactGroups = user.getContactGroups();
		for(int i=0; i

Hope this helps.

Using ResourceBundles to handle messages in Java – ApplicationResources.properties

No Gravatar

Java has a couple of concepts that are used as best practices in web applications that can be very useful even if you don’t intend to use them for their strict purpose. The first is a properties file and the second is internationalization (i18n – 18 letters between the i and the n).
Properties files are simple key=value files. They contain records that are in this format generally:


my.key=My Value

Internationalization is a concept that allows an application to move it’s labels of field names, descriptions, etc. to be encoded in properties files with a specific extension representing the language. These follow the 2-letter ISO 3166 country code extensions. These are very useful in web applications and allow you to extract messages at will using both manual methods as well as tag libraries.

An example of the manual method is shown below:


ResourceBundle messages = ResourceBundle.getBundle("ApplicationResources");
String adminId = messages.getString("adminuserid");
String adminPassword = messages.getString("adminpassword");

This bit of code will extract the value of the adminuserid property from the ApplicationResources.properties file and place it’s value in the adminId field, and the same with the adminPassword field.

An example of using the jstl fmt taglib in order to display a message is shown below:



This bit of code will extract the value of the label.userId property and render it on the screen.

Hope this helps.