Re: The 140 character webapp challenge!

February 14th, 2009

This is my response to The 140 character webapp challenge!

Epilepsy

javascript:{r=0;setInterval(function(){document.body.style.background=(r++%2==0?'#'+r%7+r%9+r%8:'0')},50);void(0)}

114 bytes of inline javascript that you can paste to your browser’s URL.

It’s a very useful webapp* in case you want to cause epilepsy to yourself.

Via: http://f055.net/article/the-140-character-webapp-challenge/
Via: http://synodinos.net/2009/02/14/re-the-140-character-webapp-challenge/

* just kidding :)

Singleton ehcache CacheManager warning fix

February 12th, 2009

If you experience the following warning in your hibernate+ehcache application:

2008-11-20 13:02:42,937 WARN  (CacheManager.java:322) - 
  Creating a new instance of CacheManager using the diskStorePath 
  "D:\apache-tomcat-5.5.26\temp" which is already used by an 
  existing CacheManager.
The source of the configuration was classpath.
The diskStore path for this CacheManager will be set to 
  D:\apache-tomcat-5.5.26\temp\ehcache_auto_created_1227178962937.
To avoid this warning consider using the CacheManager factory 
  methods to create a singleton CacheManager or specifying a 
  separate ehcache configuration (ehcache.xml) for each 
  CacheManager instance.

then you need to set the following in your hibernate.cfg.xml file:

<property name="hibernate.cache.provider_class">
  net.sf.ehcache.hibernate.SingletonEhCacheProvider
</property>

Ehcache Hibernate documentation

The * stupidest things I’ve done in my programming job

February 7th, 2009

I’m not ashamed of those sins any more, so here you go :)

1. ORM

Stupidity
Building my own Object Relational Mapping framework.
Consequence
Project is a mess after 2 years of maintenance with hardcore hacks to bypass my own ORM and call custom SQL queries.
What should I have done
Use hibernate, iBATIS, Cayenne or something similar.

2. EAV

Stupidity
Using an Entity-Attribute-Value model database schema design.
Consequence
Non scalable solution and total impossibility to run any useful queries on the database level.
What should I have done
Use an ordinary normalized database schema design.

3. Database Access

Stupidity
Synchronize (serialize) database access using one shared connection.
Consequence
Zero scalability. Very slow response times when more than 10 users where using the application.
What should I have done
Don’t do that and use a connection pool such as c3p0 and use a “new” (reused) connection returned from the pool for every request/response cycle.

4. IDE

Stupidity
Avoided learning and using an Integrated development environment.
Consequence
Inability to build test and deploy the application quickly and generally do anything useful.
What should I have done
Get familiar with an IDE. NetBeans, eclipse etc.

5. Transactions

Stupidity
Not using them.
Consequence
Corrupt data in an application involving e-shop like functionality.
What should I have done
Use database transactions. When in MySQL use InnoDB.

6. Prepared Statements

Stupidity
Using Statements, string concatenation and naive character escaping to assemble my own “safe” queries.
Consequence
SQL Injections possible in my application. I managed to login using ‘or 1=1;delete from users;– and alter the database state in a very nasty way.
What should I have done
Use Prepared Statements which correctly assemble and escape the query properly depending on the JDBC driver used.

7. Business Logic

Stupidity
Doing it in the template (JSP).
Consequence
Messy non maintainable application.
What should I have done
Do it in an MVC style with servlets or with a Front Controller. Even better by using an existing open source MVC framework such as Struts, Spring MVC etc.

Of course, all the bad choices above have probably made me a better programmer.

Best way to integrate Google Analytics

November 6th, 2008

This is the best solution to integrate Google Analytics into your site. It uses ideas and code from the following 2 sites:
http://www.mattiasgeniar.be/webdevelopment/_gat-is-not-defined-google-analytics-error/
http://www.maifith.com/news/_gat-is-undefined-new-analytics-code

Here is the improved snippet:

<script type="text/javascript" src="http://www.google-analytics.com/ga.js"></script>
<script type="text/javascript">
    if (typeof(_gat)=='object')
        setTimeout(function(){
            _gat._getTracker("UA-1234567-8")._trackPageview()}, 1500);
</script>

Improvements:

  1. Does not use document.write
  2. Fixes the “_gat is not defined” issue
  3. Delayed GA access (1.5 second) so the page load time is not affected
  4. Very concise

Another improvement would be to cache ga.js locally to avoid the DNS lookup.

Logging website subsections with Apache

April 26th, 2008

This is a typical VirtualHost for example.com in Apache HTTP Server:

<VirtualHost xx.xxx.xx.xx:80>
    DocumentRoot /home/example.com/site
    ServerName example.com
    ErrorLog /home/example.com/logs/error.log
    CustomLog /home/example.com/logs/access.log "combined"
</VirtualHost>

This CustomLog directive will produce something like this on the logfile:

64.229.111.27 - - [08/Aug/2007:16:12:54 +0300] GET /foo/index.html HTTP/1.1
64.229.111.27 - - [08/Aug/2007:16:12:54 +0300] GET /bar/index.html HTTP/1.1
64.229.111.27 - - [08/Aug/2007:16:12:54 +0300] GET /bar/about.html HTTP/1.1

Suppose that you wanted to log requests for /foo and /bar subsections in 2 separate files. That way you (or your client) may find it easier later on to analyze web traffic for the subsites individually.

What you can do is log conditionally using environment variables that you’ve set using SetEnvIf based on the request.

SetEnvIf Request_URI "/foo.*" subsite_foo
SetEnvIf Request_URI "/bar.*" subsite_bar
CustomLog /home/example.com/logs/access.foo.log combined env=subsite_foo
CustomLog /home/example.com/logs/access.bar.log combined env=subsite_bar

This works nice, but not when the urls for your individual subsites look like this:

http://example.com/?site=foo&page=5

http://example.com/?site=bar&page=8

That’s because the Request_URI does not contain the query string (whatever comes after the ? character).

The solution comes with a little bit of RewriteCond magic, which helps us set an environment variable using ${QUERY_STRING}:

RewriteEngine on
RewriteCond %{QUERY_STRING} .*site=foo.*
RewriteRule (.*) $1 [E=subsite_foo:1]
RewriteCond %{QUERY_STRING} .*site=bar.*
RewriteRule (.*) $1 [E=subsite_bar:1]
CustomLog /home/example.com/logs/access.foo.log combined env=subsite_foo
CustomLog /home/example.com/logs/access.bar.log combined env=subsite_bar

Happy logging…

Bad and Good (code snippets)

August 18th, 2007

What follows is usual modifications I apply to java code, when I code review. Most of the following changes have a stylistic nature, but some of them can impact performance. Bad code is in red and good code is in green. Feel free to comment.

Unnecessary if statement

if (foo>bar) {
  return true;
} else {
  return false;
}
return foo>bar;

Unnecessary nesting

if (foo) {
  if (bar) {
    // do something
  }
}
if (foo && bar) {
  // do something
}

A bit of redundancy here

if (foo!=null && foo.equals("bar")) {
  // do something
}
if ("bar".equals(foo)) {
  // do something
}

Looks ugly

String comment = request.getParameter("post");
if (comment==null) {
  comment = "n/a";
}
String comment = request.getParameter("post")!=null?
        request.getParameter("post"):
        "n/a";

This only holds if request.getParameter("post") is cheap.

Unnecessary variable allocation

Something something = new Something(foo);
return something;
return new Something(foo);

Too much variable scope

Something something = new Something();
if (foo) {
  something.prepare();
  request.setAttribute("something", something);
}
if (foo) {
  Something something = new Something();
  something.prepare();
  request.setAttribute("something", something);
}

Method exposes implementation

public ArrayList getSomething() {
  ...
}
public List getSomething() {
  ...
}

A bit slow

String foo = "something";
if (!foo.equals("")) {
  // do something
}
String foo = "something";
if (foo.length()>0) {
  // do something
}

Too many lines

List immutableList = new ArrayList();
immutableList.add(foo);
immutableList.add(bar);
immutableList.add(example);
Something something = new Something(immutableList);
Something something = new Something(
        Arrays.asList(new Object[] {foo, bar, example}));

Disabling foreign key generation in hbm2ddl

August 13th, 2007

When generating the database schema using the hbm2ddl tools, foreign keys are being created for every relation. You can enhance the schema by using the foreign-key attribute to specify your own name for a particular foreign key.

But, what happens when you don’t want a foreign key generated?

There is an undocumented behavior of the foreign-key attribute, and that is to specify foreign-key=”none”. hbm2ddl will not create an FK for a relation which has such an attribute. The hibernate documentation and the two bibles Hibernate in Action and Java Persistence with Hibernate state absolutely nothing about this feature. I found it after hardcore googling in the following hibernate changelog:

Changes in version 2.1.9 (xx.x.xxxx)
------------------------------------
* foreign-key="none" can be used to disable generation of a foreign key.

Later on, I found another blog mentioning this behavior: http://blog.xebia.com/2007/02/05/let-hibernate-connect-your-world/

The most logical question now is “why don’t you want an FK?”. That depends on the system you are building. Sometimes you might have a table in your application which will be CRUDed from another system, which you do not control. You may want to be able to keep references (ids) to entities which may be deleted. foreign-key=”none” together with not-found=”ignore” can solve these kind of problems.

Test First (#2)

August 1st, 2007

You want to create a helper class to analyse an HttpServletRequest and provide you with helper methods which determine the type of request. You basically care about GET and POST request methods. More specifically you want to be able to tell whether a POST is Multipart (usually containing file uploads).

Without losing a second, you create the class and make it compile. Right now you only care about the API of the class, and how will it be used from the client side of view. The class is immutable.

import javax.servlet.http.HttpServletRequest;

public class HttpRequestAnalyser {

  private final boolean get;
  private final boolean post;
  private final boolean multipart;

  public HttpRequestAnalyser(HttpServletRequest request) {
    // do nothing of value (yet)
    this.get = false;
    this.post = false;
    this.multipart = false;
  }

  public boolean isGet() {
    return get;
  }

  public boolean isPost() {
    return post;
  }

  public boolean isMultipart() {
    return multipart;
  }

}

Press F9, it compiles (NetBeans).
No matter what kind of request we construct this class with, it will never give us a true answer on whether the method was GET, POST or POST-MULTIPART. That’s because the implementation is the absolute minimum we need in order to define our API and have something that compiles.

Press CTRL+SHIFT+U to create the following empty test.

import junit.framework.*;

public class HttpRequestAnalyserTest extends TestCase {
  
  public HttpRequestAnalyserTest(String testName) {
    super(testName);
  }

  public void setUp() {
  }

  public void testIsGet() {
  }

  public void testIsPost() {
  }

  public void testIsMultipart() {
  }
  
}

Press SHIFT+F6, the test passes because there are no assertions yet.

The point is to create good tests for our HttpRequestAnalyser class. The tests will fail, and then we’ll try to make them pass by doing real work in our class, which is the System Under Test.

In order to test our class we will need instances of HttpServletRequest. It’s not (easily) possible to create such instances, as this is an interface, and usually the servlet container generates concrete implementations. We don’t want to incorporate a servlet container in our tests. What we are going to do is mock an HttpServletRequest, as if it was coming over http from a client.

In order to mock such a request we could provide our own implementation, possibly in an inner static class, inside our test and we’d have to implement all methods.

Another way is to create a mock object which will implement HttpServletRequest and program it with canned answers for our class. There exist many frameworks out there for mocking and we’ll use mocquer.

We need to add the servlet-api.jar and the mocquer dependencies on our project’s test libraries.

In order to fake HTTP request data, we need to know how these look like. Firefox and many other http header monitor tools out there help us gather the following interesting parts of the requests:

GET method

GET /example.html HTTP/1.1
Host: www.domain.com

POST method

POST /example.html HTTP/1.1
Host: www.domain.com
Content-Type: application/x-www-form-urlencoded

POST method with file upload

POST /example.html HTTP/1.1
Host: www.domain.com
Content-Type: multipart/form-data; boundary=...

The test now becomes:

import javax.servlet.http.HttpServletRequest;
import junit.framework.*;
import org.jingle.mocquer.MockControl;

public class HttpRequestAnalyserTest extends TestCase {
  
  public HttpRequestAnalyserTest(String testName) {
    super(testName);
  }
  
  private MockControl requestControl;
  private HttpServletRequest request;
  
  public void setUp() {
    requestControl = MockControl.createControl(HttpServletRequest.class);
    request = (HttpServletRequest)requestControl.getMock();
  }
  
  public void testIsGet() {
    request.getMethod();
    requestControl.setReturnValue("GET");
    requestControl.replay();
    HttpRequestAnalyser analyser = new HttpRequestAnalyser(request);

    assertTrue(analyser.isGet());
    assertFalse(analyser.isPost());
    assertFalse(analyser.isMultipart());
  }
  
  public void testIsPost() {
    request.getMethod();
    requestControl.setReturnValue("POST");
    request.getHeader("Content-Type");
    requestControl.setReturnValue("application/x-www-form-urlencoded");
    requestControl.replay();
    HttpRequestAnalyser analyser = new HttpRequestAnalyser(request);

    assertFalse(analyser.isGet());
    assertTrue(analyser.isPost());
    assertFalse(analyser.isMultipart());
  }
  
  public void testIsMultipart() {
    request.getMethod();
    requestControl.setReturnValue("POST");
    request.getHeader("Content-Type");
    requestControl.setReturnValue("multipart/form-data; boundary=...");
    requestControl.replay();
    HttpRequestAnalyser analyser = new HttpRequestAnalyser(request);

    assertFalse(analyser.isGet());
    assertTrue(analyser.isPost());
    assertTrue(analyser.isMultipart());
  }
  
}

We’ve provided method call expectations, and canned answers on the mock. The tests fail.
We fill in the HttpRequestAnalyser constructor implementation which now becomes:

import javax.servlet.http.HttpServletRequest;

public class HttpRequestAnalyser {
  
  private final boolean get;
  private final boolean post;
  private final boolean multipart;
  
  public HttpRequestAnalyser(HttpServletRequest request) {
    this.get = request.getMethod().equals("GET");
    this.post = request.getMethod().equals("POST");
    this.multipart =
        request.getHeader("Content-Type").startsWith("multipart/");
  }
  
  public boolean isGet() {
    return get;
  }
  
  public boolean isPost() {
    return post;
  }
  
  public boolean isMultipart() {
    return multipart;
  }
  
}

Post and multipart tests pass. The get test fails, because we haven’t set an expectation for getHeader(“Content-Type”) to be called. That is because the GET Http method doesn’t have such a header.
The multipart check should only happen if the request has been recognised to be a post:

import javax.servlet.http.HttpServletRequest;

public class HttpRequestAnalyser {
  
  private final boolean get;
  private final boolean post;
  private final boolean multipart;
  
  public HttpRequestAnalyser(HttpServletRequest request) {
    this.get = request.getMethod().equals("GET");
    this.post = request.getMethod().equals("POST");
    this.multipart = post ?
      request.getHeader("Content-Type").startsWith("multipart/") :
      false;
  }
  
  public boolean isGet() {
    return get;
  }
  
  public boolean isPost() {
    return post;
  }
  
  public boolean isMultipart() {
    return multipart;
  }
  
}

Tests pass, and the class is ready to rock! Happy testing (before coding).

Good Javadoc use

July 29th, 2007

Javadoc is a tool that you have in your %JAVA_HOME%\bin (Windows) or $JAVA_HOME/bin (UNIX) directory. It is being used to extract API documentation from your Java source code, into HTML.

Most IDEs fully support Javadoc. They assist the developer in writing, displaying and generating the Javadoc documentation. Javadoc is part of the development lifecycle. Good and up-to-date Javadoc is a sign of a healthy project.

API Users

The worst thing an API user can do is to ignore Javadoc. Having an easily accessible, local copy of the Javadoc for the library you are working with (Spring, Hibernate, Lucene etc) is the only way to work efficiently. Vast amounts of time have been put into compiling quality documentation for these libraries. Not using it will only slow you down.

Development Teams

One of the worst Netbeans feature is that it allows you to collapse all comments and even set this as the default behavior when opening a source file. Team members, working in the same piece of code, can no longer see the documentation written by other developers.
I actually had a developer asking me about what one of my methods did. For a moment I was confused and asked him whether I had written poor documentation. He then told me that he didn’t know that there was any Javadoc for that method. I don’t (want to) know whether Javadoc hiding is a feature of Netbeans or is a plugin, but that was definitely one of the most ineffective behaviors I’ve seen in a development team.

API designers

Writing good Javadoc involves many things which are documented by SUN. The general idea is that you don’t want to expose the implementation of the method through the documentation. API users will not care how you do it, but only what (and maybe why) you do.
So the following comment is bad:

/** 
 * This method uses StringBuffer to merge the name with surname and return
 * the person's full name
 */
 public String getFullName() {

A better version is:

/** 
 * Returns the full name of the Person. Will return "Nick Cave" if
 * firstname is "Nick" and lastname is "Cave".
 *
 * @return      the full name of the Person
 */
 public String getFullName() {

Conclusion

We (Java developers) are very lucky that documentation is so tightly integrated with the language. Not using it though, takes all this goodness away.

FreeMarker exception handling

June 20th, 2007

FreeMarker is a very flexible templating engine for Java. Exception handling (while rendering the template) is a very important issue for a templating engine. As with JSP the default behaviour of FreeMarker is to completely cancel rendering and display an error page. When developing a webapp this might not be very helpful. Sometimes errors might need to be tolerated; at least for the development phase of the application development.

FreeMarker provides the TemplateExceptionHandler interface with some implementations but we’ll define our own in order to provide a more failsafe and usable behaviour.

public class MyTemplateExceptionHandler 
          implements TemplateExceptionHandler {

  public void handleTemplateException(TemplateException te, 
          Environment env, Writer out) {
    freemarkerlog.error("template error", te);
    try {
      out.write("<span style=\"cursor:help; color: red\" " +
                "title=\"" + ExceptionUtils.getMessage(te) + "\">" +
                "[e]" +
                "</span>\n");
    } catch (IOException ignored) { }
  }
  
}

Then, in the code where you configure FreeMarker you need:

config.setTemplateExceptionHandler(new MyTemplateExceptionHandler());

This is what you’ll see whenever there is an exception thrown while rendering the template:
FreeMarker exception handling
A nice little [e] with a tooltip containing the exception message.