n+1 rather 1+n

January 1, 2011

Hello,
I have been thinking to post this for quite some time. This one is about the famous “n+1” behavior/problem with the ORM tools. Initially when I had learnt about this one it took me a while to digest. I felt “1+n” is more easier to understand than “n+1” and it would be so for Beginner audience. That’s the reason behind this post.

In ORM world you often mark the relationships as “lazy” so that they are lazily loaded. First we will see what this means,

Consider the classic one-to-many Department(One) and Employee(Many) relationship.

From Department’s perspective this one is represented as the Collection of Employee objects within a Department as shown below.


/**
 * The Employee Entity.
 * Only OneToMany Bidirectional association is shown in the code.
 */
@Entity
public class Employee {
    @ManyToOne
private Department dept;
}

/**
 * Department Entity.
 */
@Entity
public class Department {
    @OneToMany(mappedBy="dept")
private Collection employees;
}

When we mark this relationship as lazy and query for the Departments, ORM shall fetch the Department objects satisfying the criteria. Due to the “lazy” attribute ORM will not initialize the Collection of Employees until they are requested.

For e.g Consider the following data set –

When we query the database to get all the departments, ORM will initialize the Department objects except the Employee Collection. This corresponds to 1 query namely

SELECT * FROM DEPARTMENT

Later whenever we access the Employee Collection contained within the Department object,ORM will again have to go the Database and fetch the employees for that department.

The query will be something like

SELECT * FROM EMPLOYEE WHERE DEPTID=?

This means for whatever the number of departments(Let’s say “n” department records),the ORM will need to fire above query those many times. i.e. n times. So to iterate all the Departments along with their Employees ORM will fire “1+n” database queries in total.

This can be overcome by using eager fetching which will result in only one JOIN query that would collectively fetch Departments along with their Employees.

Hope this helps someone confused about 1+n problem.

Cheers,
Amit

Advertisements

Intercepting HTTP Response using Servlet Filter

March 16, 2010

Hello,
Servlet Filters are used to intercept the HTTP Requests/HTTP Responses.
Filters generally contain some logic that can be applied across a URL pattern.
I have used filters generally to verify if user is logged in or if user has appropriate privilege to access the resource.
While addressing such requirements we end up writing a Filter that is better known as Request Filter because it
intercepts the HTTP request. So most of the time when I ask someone if they know how to implement a HTTP Response Filter, they look puzzled. Of course,I too have gone through this situation in past.

Below is the sample code for Filter(Request Filter)  –

package com.amit.web.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;

public class MyFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// place your code here
 // pass the request along the filter chain
chain.doFilter(request, response);
}

public void init(FilterConfig arg0) throws ServletException {}
public void destroy() {}
}

You would know that the line “chain.doFilter(request,response)“, is responsible for executing the next Filter or web resource in line.
Hence if I map MyFilter for servlet named MyServlet then any request for MyServlet would be intercepted by MyFilter. When it encounters “chain.doFilter(request,response)“,it would call the MyServlet’s service method.
Once MyServlet has finished its task, the call to “doFilter” would return and if there is no code/logic written after this line, HTTP Response goes back to the client.
This precisely is the location where we can write the code that would alter the HTTP Response.
This means if we need to write a HTTP Response filter i.e. intercepting HTTP Response, then we need to write the business logic after “chain.doFilter(request,response)” and we are intercepting the HTTP response before it reaches the destination.  The method doFilter that would serve as HTTP Response filter is shown below –

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
//PLACE YOUR CODE HERE THAT MODIFIES THE RESPONSE.
} 

Overall this is preety easy but usually goes unnoticed which is the reason I felt writing about this.

Another important point about Servlet Filters is –
Consider there are MyFilter1, MyFilter2 and MyFilter3 configured for any requests to Servlet MyServlet.
In this case MyFilter1, MyFilter2 and MyFilter3 will be executed in the order of configuration while intercepting the HTTP Requests.
While sending back the response they would be executed in the REVERSE order as shown in the diagram below.

Filter-Invocation-Sequence

Hope this helpes someone who is wondering how to implement HTTP Response Filters.Cheers !!
Amit


Webapp generated Excel Spreadsheet opens in same browser window – IE6

March 8, 2010

Hello,

While working on a web application that generates Excel spreadsheets , I faced the issue mentioned below.

Issue:

Sometimes the spreadsheet is opened up in a new MS-Excel application window and often opened in the same browser window.  This is used to happen for Internet Explorer 6.0. On IE7 it was not reproducible i.e. used to open up in the MS-Excel application all the time leaving browser intact.

Additional Information:

I had implemented this spreadsheet generation as below –

  1. Generate the spreadsheet using Apache POI.
  2. Set header content-type to “application/vnd.ms-excel“.
  3. In addition to content-type, I was also adding the header “Content-disposition” that assigns a filename to the content written on the response stream. Some excel files were named like “xyz/abc.xls“.
  4. Write the bytes on the Response stream.

Resolution:

We could figure out the behavior because when we ran the application and try to retrieve the report,

  1. For spreadsheets with filenames that did not contain “/” displayed the browser File Download dialog properly with “filename.xls”.
      ie6-saveas-noslash
  2. Whereas if the filename contained “/” in it then the File Download dialog shows
  • EITHER the URL that is used to retrieve the excel report from server. e.g. if you have a ReportServlet that serves the excel report then it would show “ReportServlet” instead of filename.
  • OR some random filename as shown below

ie6-filedownload

Once we fixed the filename generation logic to replace “/” with “-“(or any other valid character), reports started opening up in MS-Excel application than in same browser window.

Another thing to note here is that IE7 handles it internally by replacing “/” with “_” as shown below.

IE7-File Download Dialog

Note:

In addition to this while searching I found out the Microsoft knowledge-base which mentioned this issue can be resolved by doing some client side settings. This knowledge-base can be found at KB-162059.

Cheers !

Amit


Dependency Injection and Using Struts Actions as Spring Beans

March 1, 2010

Hello,

I had created this presentation earlier to mentor my team members about Spring Dependency Injection fundamentals and explaining approach to integrate Struts 1.3 Action classes and Spring framework. Approach I took was using “DelegatingActionProxy” for using Struts action classes as Spring beans.

Introduction to Spring DI and Using Struts Actions as Spring Beans

Introduction to Spring - First page

 

I should have posted it then itself but then sooner is better than never. Hope that you find this useful.

Cheers !

Amit


Using Java Enums to replace conditional (IF) statements.

February 16, 2010

Hello,
Recently I was using Java Enumerations for addressing some requirements and while doing that I realized that one can write a much better and maintainable code using Enums.
I got rid of lot of conditional statements using Enum attributes in my code. It looks clean and easily understandable.
Here is how I utilized Java Enums. Hope you find this useful.

Scenario:
Consider that we have a list of Strings that represents days of the week.
Now if we want to print out the index of the day instead of its name then we might do something like below ,

Note that System.out.println() is just a an example function used to illustrate the example. We can use retrieved variable in whatever the business logic may be.


Solution I:

This is the naive way of handling this scenario.


if(day.equals("Monday")) {
 System.out.println("Index is " + 1);
} else if(day.equals("Tuesday")) {
 System.out.println("Index is " + 2);
} ...

...

and so on

Solution II:
Somebody might want to create a Map<String,Integer) that contains String “day” as key and “index” as value and easily get the index using the code snippet below


Map<String,Integer> daysofweek = new HashMap<String,Integer>();
daysofweek.put("Monday",1);
daysofweek.put("Tuesday",2);
..
..
int index = map.get("Monday");
System.out.println("Index is" + index);

The second solution seems to be more elegant than the Solution I, which relies on lot of if/else conditional statements to fulfill the requirement.
Instead of using a Map we can do the same thing using an Enumeration in Java 5.

Solution III:
We construct an Enum as below that has an attribute “index”.


public class EnumTest {

 enum daysofweek {
  MONDAY(1),
  TUESDAY(2),
  WEDNESDAY(3); //Not all the days are shown here

  private int index;

  daysofweek(int index) {
   this.index = index;
  }

  public int getIndex() {
   return this.index;
  }
 }

 public static void main(String args[]) {
   //Assume that day is passed as a argument
   String day = args[0];
   System.out.println("Entered valye of day is - " + day);
   System.out.println("Index of the day is - " + daysofweek.valueOf(day.toUpperCase()).getIndex());
 }
}

This is very similar to using the MAP but I think this prove more advantageous when we have more properties OR attributes for each enumerated element (in this case day).
Additionally see the use of “valueOf()” function. We can easily convert the input value to corresponding Enumerated constant.

Let’s say that we want to designate each day to represent task done on that day.
For e.g: Monday is SchoolDay, Tuesday is StoryTimeDay, Wednesday is SwimmingDay etc.
The enumeration above can be easily extended to accomodate this and ready to use instead of conditional statement in your code to handle this.

Modified Enum will look as below:


public class EnumTest {
 enum daysofweek {
  MONDAY(1,"Schoolday"),
  TUESDAY(2,"StoryTimeday"),
  WEDNESDAY(3,"Swimmingday"); //Not all the days are shown here

  private int index;
  private String activity;

  daysofweek(int index,String activity) {
    this.index = index;
    this.activity = activity;
  }

  public int getIndex() {
   return this.index;
  }

  public String activity() {
   return this.activity;
  }
 }

 public static void main(String args[]) {
  //Assume that day is passed as a argument
  String day = args[0];
  System.out.println("Entered valye of day is - " + day);
  System.out.println("Index of the day is - " + daysofweek.valueOf(day).getIndex());
  System.out.println("Activity for the day is - " + daysofweek.valueOf(day).activity());
 }
}

Do let me know your comments and suggestions about this one.

Cheers !!

Amit


Debugging Web-application deployed on Tomcat using Eclipse

January 15, 2010

Hello,
This small article will walk you through the steps needed to setup the Eclipse environment for debugging Web application deployed on Tomcat server. I have used Tomcat 6.0.18 and Eclipse Ganymede for this purpose.

  1. Add the following lines in {tomcat.home}/bin/catalina.bat. tomcat.home is your tomcat installation directory.
  2. set JPDA_ADDRESS=1044
    set JPDA_TRANSPORT=dt_socket
  3. Open Eclipse “Debug Configurations” window. Menu Navigation – Run > Debug Configurations…
  4. Add new “Remote Java Application” as below
  5. The “Port” should match to the JPDA_ADDRESS configured above in step #1.
  6. Click “Debug” to start debugging.
  7. Start the Tomcat server using command “catalina jpda run”. This starts Tomcat in debugging mode.
  8. If the “Breakpoint” is encountered while application is being executed, Eclipse will ask you if you want to switch to Debug perspective where you can debug the application using standard debug controls.
  9. There is one nice article on IBM developer works that explains Debugging. Here is one helpful resource to know more about debugging techniques IBM RAD Tutorial .

Hope this helps in setting up a Eclipse Debugger for debugging your applications.  Do let me know if you feel this article needs improvements and your suggestions.

Cheers !

Amit


build.xml: No WEB-INF/web.xml file was added. – Apache Ant 1.7.1

December 24, 2009

Hi,
Recently I faced an issue with Apache Ant version 1.7.1.

I was building a WAR file using the standard dynamic web project in Eclipse Ganymede. It had “src” and “WebContent” directories as per the structure.

When I ran the target “create-war”  which looked like this.


<target name="create-war" depends="clean-dist">
<mkdir dir="${basedir}/dist"/>
<war destfile="${basedir}/dist/myapp.war" casesensitive="true">
<classes dir="${classes}" includes="**/*">
</classes>

<fileset dir="${basedir}/WebContent" casesensitive="yes">
<exclude name="META-INF/**"></exclude>
<exclude name="WEB-INF/**"></exclude>
</fileset>
<lib dir="${lib}"/>
<webinf  dir="${basedir}/WebContent/WEB-INF" casesensitive="true" >
<include name="web.xml"/>
<include name="struts-config.xml"/>
<include name="tiles-defs.xml"/>
</webinf>
<metainf dir="${basedir}/WebContent/META-INF" casesensitive="true"/>
</war>
</target>

This gave me the following error:

Buildfile: build.xml
clean-dist:
create-war:

BUILD FAILED
build.xml:65: No WEB-INF/web.xml file was added.
If this is your intent, set needxml=’false’
Total time: 2 seconds

I had web.xml file in appropriate directory to be picked up by target named “war”. But still keep getting this error.
I tried to fiddle with the attribute mentioned in the error “needxml” without any luck.

Finally I realized that I did not have “dist” directory created in my directory structure. Once I did that “create-war” ran successfully.

I wrote this one because the error that ANT throws, is surprisingly misleading and do not direct us to the actual cause of build failure.
It might be possible that you get similar error message on different use cases as well. This might be just one of it which can be fixed by creating the missing directory.

-Amit

Hi,

Recently I faced an issue with Apache Ant version 1.7.1.

I was building a WAR file using the standard dynamic web project in Eclipse Ganymede. It had “src” and “WebContent” directories as per the structure.

When I ran the target “create-war”  which looked like this.