Mar 6, 2009

Java - Inner Classes - for SCJP

If anonymous class is created for interface, it extends Object class and implement that interface, if it is created for a class then it extends that class.
Earlier, Non-static inner classes were not allowed to have static fields at all. This rule is now modified and the new rule says that: 'The third paragraph of the section Members that can be marked static is amended to make an exception and allow inner classes to declare static FIINAL fields that are compile time constants as members.'
Ex.:
public class Outer{
class Inner
{
static final int k = 10;
}
}
(Top level classes mean, classes defined in package scope and STATIC inner classes of classes defined in package scope) Consider the anonymous inner class for catching action events:

ActionListener al = new ActionListener(){
public void actionPerformed(ActionEvent e)
{
}

};

Here, the anonymous class implicitly extends Object and implements the interface ActionListener. Explicit extends or implements clauses are not allowed for such classes. Other inner class (ie. non anonymous) can have them. Consider the following (although of no use) class:
public class TestClass
{
public TestClass(int i) { }

public void m1()
{

TestClass al = new TestClass(10)

{

public void actionPerformed(ActionEvent e)
{
}

};
}

}
This illustrates 4 points:
  1. Instance Methods can also have inner classes. (But they cannot have static inner classes).

  2. Inner class can extend the outer class.

  3. Anonymous inner class can be created for classes. (Not just for interfaces). They implicitly extend the class.(Here, TestClass)

  4. Anonymous inner class can have initialization parameter. (If the class they extend has a corresponding constrctor).

Non-static inner classes can contain final static fields (but not methods).
Anonymous classes cannot have explict constructors, since they have no names.
A static inner class is also known as A Top Level Nested class. So,there are two types of Top level classes. One, that is a standard class and other an inner class which is static.
Eg.
public class A //This is a standard Top Level class.
{
class X

{

static final int j = 10; //compiles fine!

}

public static class B //This is also a Top Level class (but nested!)

{
}

}
You can create objects of B with having objects of A. Eg. A.B b = new A.B();
Members in outer instances are directly accessible using simple names. There is no restriction that member variables in inner classes must be final.
Nested classes define distinct types from the enclosing class, and the instanceof operator does not take of the outer instance into consideration.

Every non static inner class object has a reference to it's out class object which can be accessed by doing OuterClass.this. So the expression B.this.c will refer to B's c, which is 'a'. Inside a non-static inner class, 'InnerClass.this' is equivalent to 'this'. so 'C.this.c' refers to C's c which is 'c'. The expression super.c will access the variable from A, the superclass of C which is 'd'.

Only classes declared as members of top-level classes can be declared static. Such a member is a top-level nested class if it is declared static, otherwise it is a non-static inner class.
Package member classes, local classes(ie. classes declared in methods) and anonymous classes cannot be declared static.

Mar 2, 2009

Prevent Duplicate Form Submission

Duplicate form submissions can occur in many ways :
  • Using Refresh button
  • Using the browser back button to traverse back and resubmit form
  • Using Browser history feature and re-submit form.
  • Malicious submissions to adversely impact the server or personal gains
  • Clicking more than once on a transaction that take longer than usual
Effect :

Think about a online shopping site, You are buying from a online shopping store. You hava submitted the form by clicking submit button screen comes with "Please wait...." and stays for a long you worried and press submit again what happens the first click submitted first shopping and second click requests for the same order again. And you have to pay for same item twice.

This is only the one case you may be pay twice, there are many others factors which can affects.

Solution :
  1. Disable submit button on first time it is clicked.
    This helps prevent duplicate form submission from user aggresion impatient. But not from the others mentioned above.
    E.g. <input type="submit" name="submit" onclick="this.disabled='true';/*your other function calling*/">

  2. Using Struts :
    1. By forwarding twice :

      The easy solution to this problem is to use HTTP redirect after the form submission. Suppose that the CustomerForm submission results in showing a page called Success.jsp. When HTTP redirect is used, the URL in the URL bar becomes /App1/Success.jsp instead of /App1/submitCustomerForm.do. When the page refreshed, it is the Success.jsp that is loaded again instead of App1/submitCustomerForm.do. Hence the form is not submitted again. To use the HTTP redirect feature, the forward is set as follows:

      <forward name=”success” path=”/Success.jsp” redirect=”true” />

      However there is one catch. With the above setting, the actual JSP name is shown in the URL. Whenever the JSP name appears in the URL bar, it is a candidate for ForwardAction. Hence change the above forward to be as follows:

      <forward name=”success” path=”/GotoSuccess.do” redirect=”true” />

      Where GotoSuccess.do is another action mapping using ForwardAction as follows:

      <action path=”/GotoSuccess” type=”org.apache.struts.actions.ForwardAction” parameter=”/Success.jsp” validate=”false” />

      Now, you have now addressed the duplicate submission due to accidental refreshing by the customer Problem : It does not prevent you from intentionally going back in the browser history and submitting the form again. Malicious users might attempt this if the form submissions benefit them or adversely impact the server.

    2. Synchronizer Token :

      Struts provide a token system which help solving this problem. Steps of implementation :

      1. add follwing line in the first(the page containing form you like to prevent from duplication) page or servlet,

      2. <% String token = TokenProcessor.getInstance().generateToken(request); session.setAttribute("org.apache.struts.action.TOKEN"
        , token); %>
      3. make a hidden field in the form as follow,

      4. <input type="hidden"
        name="<%=.TOKEN_KEY%>"
        value="<%=token%>"/>

      5. Now in the Action class you created, change code as follow,

      6. .... if(isTokenValid(request)){
        // your code if form submitted first time
        } else {
        // your code if form is duplicate.
        }
        saveToken(request);
        .....