Wednesday, June 27, 2007

jwhich - Java classes can run but they can no longer hide

This bash command will search all .jar files in the current directory and all subdirectories for MyClass:
for f in `find . -name '*.jar'`; do jar tf $f | grep "MyClass" | xargs -n 1 echo "$f:"; done
Here is a complete shell script version that accepts a search argument, optionally followed by a start path. I keep this script at /usr/bin/jwhich on my box.
Sample output:
$ jwhich MyClass
./myapp/my/hard/to/find/subdirectory/mymissing.jar: com/Missing/MyClass.class
$
The script itself:
#!/bin/bash

whichclass=$1
path=$2

if [ -z $whichclass ]; then
echo "usage: $0 searchstring [path]"
echo "\tsearchstring - search for class names that contain this substring"
echo "\tpath (optional) - start at this path (default: current directory)"
echo "\nSearch for a Java Class, scanning all .jar files in the current directory and all subdirectories"
exit 1;
fi

if [ -z $path ]; then
path="."
fi

for f in `find $path -name '*.jar'`; do
jar tf $f | grep $whichclass | xargs -n 1 -r echo "$f:";
done


Thursday, June 21, 2007

A simple servlet Filter for JDBC Connections

Here is an example of a servlet Filter that could be used in a web application to check out a JDBC Connection from a connection pool, keep it open for the duration of a web request, and then insure that it gets closed at the end even if an exception occurs. The implementation is similar to the open-session-in-view pattern, but in this case it is more correctly described as open-connection-in-view. Note: Because connection pool initialization varies depending on the pool provider, the initialization of the pool DataSource is left as an exercise for the reader.
package jeoftp;

import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import javax.sql.DataSource;
import java.sql.Connection;

/**
 * ConnectionProviderFilter
 *
 * Provide JDBC Connections to downstream servlets and insure they
 * are cleaned up before the web request completes. Servlets can use
 * request.getAttribute(ConnectionProviderFilter.CONNECTION_ATTR)
 * to access the Connection.
 *
 * @author Jeoff Wilks
 */
public class ConnectionProviderFilter implements Filter {

  public static final String CONNECTION_ATTR = "jeoftp.ConnectionProviderFilter";

  //most connection pools provide a standard JDBC DataSource facade
  private DataSource connectionPool;

  public void init(FilterConfig filterConfig) {
    //TODO: initialize your connectionPool here
  }

  public void destroy() {
    //TODO: clean up connectionPool here
  }

  public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain) {

    Connection connection;

    try {
      //check out a connection for this web request
      connection = connectionPool.getConnection();

      //tie it to a request attribute so other servlets can grab it
      request.setAttribute(CONNECTION_ATTR, connection);

      //let other servlets do their work
      chain.doFilter(request, response);

    //optional: roll back transaction if an exception occurs
    } catch (Exception e) {
      connection.rollback();
      throw e;

    //mandatory: insure the connection is closed
    } finally {
      if (connection != null) {
        connection.close();
      }

    }      
  }
}