Clustering J2EE Applications

All mission critical applications need to be have high Availability and Scalability features built-in. Any incident or outage in such applications can have huge implications – like business loss or legal issues faced by the company. Clustering helps in application scalability (through load balancing) as well as high availability (through failover).


Clustering J2EE Applications
Never assume that stand-alone applications can be transmit transparently to a cluster structure.
Most of the leading application server vendors like IBM (Websphere) and Oracle (BEA Weblogic) support clustering their servers and provide for built-in load balancing among them.




It might seem that Clustering is a deployment or server related activity and we as normal Java developers might not be concerned with it. This is not true. There are various aspects which the Java developers need to take care while working on design, coding and testing for creating cluster aware, scalable J2EE applications.


Figure 1: Visualize Clustering



Application Design and Coding Considerations
Below are some basic points to consider while developing and maintaining applications – which will ultimately be deployed in a clustered environment in production.


User Session
HttpSession object is responsible for maintaining user session across requests. Session object is tracked by a unique session id.


To provide transparent failover in a cluster, application servers need to ‘replicate’ session state on multiple servers. As a result, based on the vendor implementation, session id might vary across client requests.

  • ‘session id’ should not be used in an application for operations synonymous to user id or should not be used to mark any transaction because it may not remain same throughout the user session. For such purposes, user id would be a more appropriate choice.
  • All objects stored in the session must be made Serializable. If any Java object, say Hashtable or any user defined object, is to be kept in session then that object must implement java.io.Serializable interface.
  • Object serialization and de-serialization are very costly in performance especially in the database persistent approach. In clustered environment, storing large or numerous objects in the session should be avoided.
  • Updating data in HttpSession – While updating any session attribute, use HttpSession.setAttribute() explicitly. This call will make sure that updated object is reflected in all session copies maintained on different servers by the application server.
  • Setting and getting values to-from HttpSession – Deprecated APIs getValue(), putValue(), removeValue() should not be used. Instead getArribute(), setAttribute() and removeAttribute() should be used.

Static Variables and Singletons

  • Do not use static variables for any logic/data that is at an application level. Simple reason being that a variable value will not be available to the JVMs in other machines and next client request can go to any server.
  • Avoid use of Singleton class that encapsulates logic for whole application (across JVMs in a cluster). In a single machine on one JVM singleton class will work. But in a cluster with multiple JVMs, having single instance will not be possible.

Data Caching

  • Application may have data cached in memory from secondary storage like database. It would be much faster to access reference data and data that doesn’t change frequently from memory.
  • Synchronize Cache – In a clustered environment, each JVM instance will maintain its own copy of the cache, which should be synchronized with others to provide consistent state in all server instances. Sometimes this kind of sync will bring worse performance than no caching at all.

File Access


Although not recommended by the J2EE specification, the external I/O operations are used for various purposes.

  • Since components will be deployed across machines in a cluster, file system must be accessible in a uniform way to all the machines.
  • To achieve this, either common network file system (like SAN) could be mounted or
  • Files could be replicated on all the machines in a cluster.
  • Instead of a file, maintain required information in the database.
  • Application logging – If application uses file to log messages then evaluate whether single file per cluster or separate file per server in cluster is required to be maintained.

Other Services

  • There are some functionalities and services which makes sense in stand-alone mode only. For example Timers/Schedulers and Email Notifications Services. These services are trigged by events instead of requests, and should only be executed only once. These services are hard to migrate to a cluster environment.
  • Some products have prepared for such services. For example, JBoss uses “clustered singleton facility” to coordinate all the instances to guarantee to execute these services once and only once. Spring Quartz (batch scheduler API) also provides clustering support.

Third Party Software


In an enterprise application usually other software/tools are used like Rule Engines, OR Mapper, third party cache manager, messaging software, logging component etc. Some of these third party software may not support clustering. This should be looked upon at design time before selecting these tools.


Application Testing Considerations


Test plans should be created to test application in cluster environment. Test cases should cover cluster objectives, which are load balancing, scalability and failover. To test cases, it might be required to create test stubs. Test cases should also cover any application specific and cluster sensitive services like file access, static data caching, and Singleton.


Brief Terminology


Scalabilty – Scalability refers to a system’s ability to support fast increasing numbers of users. One way to is to add resources (memory, CPU or hard disk) to a server. Clustering allows a group of servers to share the heavy tasks, and operate as a single server logically.
High Availability – Single server solution to scalability (adding more resources) is not a robust one because of its single point of failure. It is required that mission critical services are accessible with reasonable/predictable response times at any time. Clustering is a solution to achieve this kind of high availability by providing redundant servers in the cluster in case one server fails to provide service.
Load balancing – Load balancing is one of the key technologies behind clustering, which is a way to obtain high availability and better performance by dispatching incoming requests to different servers. In addition the load balancer should perform other important tasks such as “session stickiness” to have a user session live entirely on one server and “health check” to prevent dispatching requests to a failing server.
Fault Tolerance – Highly available data is not necessarily strictly correct data. A fault tolerant service always guarantees strictly correct behavior despite a certain number of faults.
Failover – Failover is a key technology behind clustering to achieve fault tolerance. By choosing another node in the cluster, the process will continue when the original node fails.


References:
• http://www.ibm.com/developerworks/websphere/library/techarticles/0606_zhou/0606_zhou.html


• http://onjava.com/pub/a/onjava/2004/07/14/clustering.html


Premature end of file when running junits

Problem:

Premature end of file error when running Junits

[junitreport] [Fatal Error] :-1:-1: Premature end of file.
[junitreport] The file /tmp/repository/Yogesh/task2652_story1984/modulesmgr/junit_report/out/xml/TEST-com.coresecurity.ctrlsvc.modules.ModulesImportAndBasicCRUDTest.xml is not a valid XML document. It is possibly corrupted.

Observations:
1) TESTS-testsuites.xml was coming out to be empty.
2) The resulting xml file was getting too large in size.

Solution:
Hibernate logging was enabled which was leading to large size of XML.
We disabled logging in config.xml as given below
Earlier it was true, we made it false








org.hibernate.dialect.MySQL5InnoDBDialect
false
update
true
5
20
300
50
3000



Equals and hashCode mystery resolved

Equals and hashCode mystery resolved

Hi,

Try executing the code in the attached files first by commenting the hashcode() method in Test1.java and then by uncommenting.

The output differs.

In first case the objects are equal based in the criteria defined in the overridden equals method but when u try to put these two “equal” objects in a hashtable it allows you inspite of the fact the keys (objects) are equal.

Here: both objects are equal but hashtable consider them different so allows two entries.

In second case when we have overridden the hashcode() method for objects of class Test1 uncommented then the hashtable doesn’t allow to put the equal objects twice.

Here: both objects are equal and hashtable consider them equal because of overridden hashtable method so allow only one entry

import java.util.Hashtable;
public class RunTest
{
public static void main (String args[])
{
Test1 test1= new Test1("start", 10);
Test1 test2= new Test1("start", 10);
Hashtable ht = new Hashtable();
System.out.println("test1.hashCode=" + test1.hashCode());
System.out.println("test2.hashCode=" + test2.hashCode());
System.out.println("test1.equals(test2) = " + test1.equals(test2));
if(test1.hashCode()!=test2.hashCode())
{
System.out.println("hashCodes are different --> means Objects are unequal");
if(test1.equals(test2))
{
System.out.println("Please note test1.equals(test2) returns " + test1.equals(test2));
System.out.println("Still it considers the objects to be unequal");
}
System.out.println("and adds it to hashTable");
}
else
{
System.out.println("hashCodes are same");
System.out.println("means");
System.out.println("Objects can be equal or unequal");
System.out.println("Now it'll check equals method");
System.out.println("test1.equals(test2) = " + test1.equals(test2));
if(test1.equals(test2))
{
System.out.println("Since equals method returns true, it'll not allow 2 equal elements to be added");
}
}
ht.put(test1,"first");
ht.put(test2,"second");
System.out.println("the size of ht is :" + ht.size());
}
}
public class Test1
{
String s;
int t ;
public Test1(String s, int t)
{
this.s= s;
this.t=t;
}

public boolean equals(Object obj)
{
if(this == obj)
{
return true;
}
if(!(obj instanceof Test1))
{
return false;
}
Test1 test = (Test1)obj;

return (s.equalsIgnoreCase(test.s) && t==test.t);
}

public int hashCode()
{
return (this.s.hashCode() + this.t);
}
}


How to wrap longer lines in SQL file…

A post by Aashu Aggarwal…

More i learn UNIX, more i feel its miraculous 🙂

1. There is a direct way to split the lines in unix. Command is “fold” It can directly split the huge lines into multiple

Syntax>> fold -200 input_file > output_file

This will split all the lines in input_file to lines less than equal to 200 characters. Like say if there is aline with 500 characters, that will be split into 3 lines with 200 character s in 2 lines and 100 in 1 line.

2. If i need to split a line around some character or word then below is the command Syntax >> perl -pe ‘s/(.{1,199}[,])/1n/g’ input_file > output_file

In this command will insert newline character after last comma in next 200 characters .{1,199} is telling to see after 200 character [,] is the character to split around. Multiple character can be given like [,:]. It will use both comma and colon to split.
1n will copy the result of first part is (.{1,199}[,]) and insert n after this s/input_pattern/output_pattern/g will replace all such entries in file

I was in love with JAVA, now i love UNIX also.. 🙂


Sendkeys

A VB Script to run outlook and send some specified keys to it.

To send Ctrl+n, use “^{n}” as given below, for Alt use %

Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "Outlook"
WScript.Sleep 2500 ' Give Notepad some time to load
WshShell.SendKeys "^{n}"
WScript.Sleep 1000
WshShell.SendKeys "Yogesh_Gandhi@infosys.com"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys " Hi Yogesh, I accept that I am a FOOL ...and you made a fool out of me today ... I don’t think God planted brains in my head!!!!...otherwise I would have checked out the code first! you are great. hats off for you. With Regards"
WshShell.SendKeys "%{s}"


Quick batch file to check OS version…

How to check the Operation System version
if OS is 32 bit or 64 bit

Quick batch file to check OS version…


@echo off

Set RegQry=HKLMHardwareDescriptionSystemCentralProcessor

REG.exe Query %RegQry% > checkOS.txt

Find /i “x86” StringCheck.txt

If %ERRORLEVEL% == 0 (

Echo “This is 32 Bit Operating system”

) ELSE (

Echo “This is 64 Bit Operating System”

)

pause


use OnClick with caution

JSP Code :

<a href="abc.jsp" onclick='’>LOGOUT

The above statement gets converted to Servlet CODE :


out.write("<a href="abc.jsp" onclick='");

session.invalidate();

out.write("'>LOGOUT");


Conclusion:

What ever scriplet you write in onclick, will get executed every time the JSP is called. Not only on onclick as can be wrongly assumed.


BUG in struts2

Actually I used

Now, I have specified type as button, so I expected that it will not go to action on click on the button.

But what happens is

when I click on button, it asks if I want to close the window,
Now, even I click NO, it still goes to action specified in form.

Solution : This is a BUG in struts2.

the HTML tag that is generated is something like:

<button type="submit” id=”test_0″ value=”Submit” class=”button positive save”>Submit

Please note that we have given type=button in s:submit tag, and the HTML generated still contains type=submit.

Can get some information from http://www.ericmmartin.com/struts-2-bug-submit-button-tag-rendering/


Internationalization tips for JSP

In order to display the complex script characters like Japanese, Chinese, etc in the browser window, the following changes need to be made at the beginning of each JSP file:

<%@ page language="java" 
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

Wherever input controls are present, the following additional steps need to be taken:
Add the following code before reading any parameters in the previous JSP file:

request.setCharacterEncoding("UTF-8"); // Set the request encoding

While sending output to a browser:

response.setContentType ("charset=UTF-8");