Friday, September 08, 2006

Calculating page request times for your web application

It has been 3 weeks since I started developing jobBoard, a web application for online recruitment/jobs database. Time now for some performance numbers!

How do you accurately measure the processing time it takes for each request on your web application? An example,

  • User clicks on a link on a page
  • Request goes through a couple of servlet filters, e.g acegi, sitemesh filters
  • The corresponding controllers/actions process the request, calls DAOs
  • DAOs/ORMs queries the native database system and returns results to controller
  • Controller gets results from DAOs and puts request attributes to JSP/Velocity etc. page template
  • Page served up by the web server.

There's a good article on servlet filters with an example just to do the above. However, I needed to present the process time on the requested web page but once the filter chain is executed, I can't put the execution time as a request attribute to be used by the page template. But here's a neat trick.

Put the 'before' time into the request attribute,

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

  long before = System.currentTimeMillis();
  request.setAttribute("before", before); // add here
  chain.doFilter(request, response); 
  long after = System.currentTimeMillis();

Then in my JSP page,

Request processed in <%= System.currentTimeMillis() - Long.valueOf(pageContext.getRequest().getAttribute("before").toString()) %> ms

The values are the same as when using the example TimeFilter as it is

Process Time.

Friday, September 01, 2006

Testing your Java Persistence API queries interactively

One of aspects of developing with ORMs is to test your JPA, EJB, Hibernate QL queries and get the results you wanted before hard coding it into your web application. For Hibernate, there's Hibernate tools but what about JPA? And within the Spring framework. Fortunately, the Spring framework provides a class (org.springframework.test.jpa.AbstractJpaTests;) to test your DAOs, which you can just adapt to make a sort of 'Query Tester'.

Here's what I did

public class JpaJobboardTests extends AbstractJpaTests {

  private JobDao jobDao;
  
  protected String[] getConfigLocations() {
    return new String[] {
      "applicationContext-jpa.xml"
    };
  }
        
    public void testQuery() {
        Query q = sharedEntityManager.createQuery(

                "SELECT DISTINCT j FROM Job j " +
                "JOIN j.industries i " +
                "JOIN j.employmentTypes e " +
                "JOIN j.qualification q " +
                "WHERE " +
                "q.id BETWEEN 2 AND 4" +
                " AND " +
                "i.id IN (4) " +
                " AND e.id IN (3)"

                );
        List jobs = q.getResultList();
        Iterator iterator = jobs.iterator();
        while (iterator.hasNext()) {
            Job job = (Job)iterator.next();
            System.out.println(job.getId() + " : " + job.getPosition());
            System.out.println(job.getIndustries());
            System.out.println(job.getEmploymentTypes());
            System.out.println(job.getQualification().getId());
        }
    }

    public void testGetAllJobs() {
        List jobs = this.jobDao.findAll();        
    }
    
    public JobDao getJobDao() {
        return jobDao;
    }
    
    public void setJobDao(JobDao jobDao) {
        this.jobDao = jobDao;
    }
    
}

Plug it into my favorite IDE, and run it. You can edit your queries and see the results interactively.

Sure, you could code a seperate application just to do this, with named queries stored in a seperate XML file, and changing the queries in the external file, and not the source codes and recompiling every time.

Thursday, August 31, 2006

Using the Display Tag with external sorting and paging

I was comparing between using using Value List Handler and the Display Tag Library to do sorting and paging of my web appliaction's result sets and decided on using the Display Tag Library for it's much simpler configuration and because of the latest release's external sorting and paging features. Created a helper class to get the parameters provided by the display tag to pass to the DAOs, otherwise the code in the controller/action gets a litlle messy. Here's pieces of what i did.

In the JSP

In the controller (I'm using Spring MVC)

In the DAO

Currently the banner does not show correct values. e.g if u have 10 as the page size, it should show 1-10 for first page, 11-20 for second page. But it always shows 1-10 for all the pages. However, this will probably be fixed in next release.

Friday, August 18, 2006

Spring 2.0 form tags

I like the Spring's form tags. It just does what it what I wanted. Registered a custom date editor in the controller and used Spring's select tag for the date selection instead of input to a text box.

<form:select path="birthDate.date">
  <c:foreach var="date" begin="1" end="31" step="1">
    <form:option value="${date}"></form:option>
  </c:foreach>
</form:select>

<form:select path="birthDate.month">
  <c:foreach var="month" begin="0" end="11" step="1">
    <form:option value="${month}" label="${1+ month}"></form:option>
  </c:foreach>
</form:select>

<form:select path="birthDate.year">
  <c:foreach var="year" begin="45" end="106" step="1">
    <form:option value="${year}" label="${1900 + year}"></form:option>
  </c:foreach>
</form:select>

  <spring:bind path="account.birthDate">
  <span class="error">${status.errorMessage}</span>
  </spring:bind>
Doing forms for date inputs used to be a pain with Struts.

Hibernate Tools and Java Persistence API?

I missed using Hibernate's table generation tools. Currently am working on a web application and wanted to try learning to use the Java Persistence API . I am using netbeans 5.5 beta as my IDE and as of now, the table generation from entity classes can only be used when using the Sun Application server and using JSF as the web framework. As a temporary solution, I used the JSF/JPA/DDL generation and switched to running Spring MVC+JPA on the same project.