2008/03/31

Java Constructor Invocation and Instance Variable Initialization

This is a tricky one:


abstract public class BasePayment {
public BasePayment(){
setFakeValue();
}
abstract public void setFakeValue();
}

public final class Payment extends BasePayment{
private String property = null;
public Payment(){
super();
System.out.println("after super(): " + this.getProperty());
}
public String getProperty() {
return property;
}
public void setFakeValue() {
System.out.println("Calling setFakeValue()");
this.property = "property";
System.out.println("After setFakeValue(), property: " + this.getProperty());
}

public static void main(String[] args) throws Exception{
Payment p = new Payment();
System.out.println("'new'ed a Payment, property value: " + p.getProperty());
}
}
What the println in the main() method will output? null? "property"?

It has something to do whether java will initialize the instance variable first, or will invoke the constructor of the super class first. The behaviour is fully documented (it better be!) at http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.7.1

And yes, the output is 'null'.

2007/12/11

Watch out for java SimpleDateFormat

Look at this code, what it will come out?

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test{
public static void main(String[] args){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dt = null;
try{
dt = sdf.parse("2000999878-3454555-35344");
System.out.println(sdf.format(dt));
}catch (Exception e){
System.out.println("error");
}
}
}

The result is:

247625706-07-03

Is this what you expected? You thought it would have thrown an exception of invalid format of text you passed in.

It's very common for a developer do date and time data conversion from text and vice versa in different format. Will it breach your boundary validation if you purely rely on this stupid SimpleDateFormat class?

Work around so far like:

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test{
public static void main(String[] args){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dt = null;
try{
dt = sdf.parse("2000999878-3454555-35344");
String s = sdf.format(dt);
if(!s.equals("2000999878-3454555-35344"))
System.out.println("Data format wrong!");
}catch (Exception e){
System.out.println("error");
}
}

Ugly codes, but works.

How many online Web systems relying on Java and J2EE have those codes?

2007/11/07

Manageable Spring Application - enable JMX in minutes

We are keeping talking about manageability of an application. Why is it so important? Because at any stage of the application lifecycle, you need a way to probe the some key aspects of the application's internal status and take appropriate actions to change the application's behaviors as a consequence. Without it, you just guess the application's runtime status and never able to steer it per your needs.

But hold on, it's easy to talk about manageability. And it's really a great idea in the air until you want put it in a concrete base in your application. It's so cumbersome, tedious and error prone to make an implementation. There are couples of option you could choose to inject the manageability in your application:

  1. Your own proprietary mechanism.
  2. Standard SNMP
  3. JMX

Forget about option 1, smart as you, don't want invent any wheel. Well, SNMP (Simple Network Management Protocol) sounds good: standardized, bunch of tools and applications and really structured, until you dig in the details of all the ugly OID (Obejct Identification) definitions, binary format, pure data driven approach. And difficulties of debugging. Plus extra cost for those usable commercial SNMP tools and editors.

Fortunately, we are in campus of Java, which is so far the only language and platform that put the serious crucial enterprise aspects intrinsically in the body, especially manageability in an offer as JMX. For the people working for .Net, either they just don't know what is the manageability, or struggling with various proprietary approaches or annoying SNMP stuffs.

Best of the best in Java application manageability is that we have the generous platform MBean Server as a gift from SUN in new version of JVM, which save your efforts looking for a MBean server; we have the JConsole as tool to directly craft your JMX management GUI frontend; and the offer from Spring's JMX supports. Combine them together, you can make any Java application JMX enabled in minutes.

Here is a simple example called MockServer. It's just a simple socket server for any mock testing purpose. With JMX, you can get the information and stop it in runtime.

Following is the partial code snippets, which is definitely the beautiful POJO. No any special MBean or MXBean stuffs in it, see!

/**
* A mock Socket server.
*/
public class MockServer implements Runnable{
private String name="";
private int port = 80;
private boolean bSSL = false;
private int sotimeout = 2*60*1000;//2 minutes

private ServerSocket listeningSocket = null;
private boolean bStop=false;
private long connCounts = 0; //Ongoing total connection counter.

public MockServer(String name, boolean isSSL, int port, int sotimeout){
this.name = name;
this.bSSL = isSSL;
this.port = port;
this.sotimeout = sotimeout;
}

public String getName(){
return name;
}

public int getPort(){
return port;
}

public boolean isSSL(){
return bSSL;
}

public int getSotimeout(){
return sotimeout;
}

public boolean isStopped(){
return bStop;
}

public void stop(){
bStop = true;
try {
listeningSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

protected void createListeningSocket() throws IOException {
ServerSocketFactory factory = (bSSL? SSLServerSocketFactory.getDefault():ServerSocketFactory.getDefault());
listeningSocket = (ServerSocket) factory.createServerSocket(port);
}

public void run(){
System.out.println("Server: "+getName()+" started.");
try {
createListeningSocket();
while (!isStopped()){
Socket worker = listeningSocket.accept();
//Spawn a thread to handle the request.
fork(worker);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (null!=listeningSocket){
try {
listeningSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("Server: "+getName()+" stopped.");
}

protected void fork(Socket worker){
Thread wt = new Thread(new Worker(worker));
wt.start();
}

public long getConnCounts(){
return connCounts;
}
protected synchronized void addCount(){
this.connCounts++;
}
protected synchronized void minusCount(){
this.connCounts--;
}

protected class Worker implements Runnable {
private Socket socket=null;

protected Worker(Socket socket){
this.socket = socket;
}

public void run() {
addCount();
byte[] buf = new byte[1024*10];//10K buffer
InputStream is;
OutputStream os;
try {
//Read request from socket input stream.
is = socket.getInputStream();
int size = is.read(buf);
is.close();
//Process the request.
byte[] resp = processRequest(buf, size);

//Write back the response to socket output stream.
os = socket.getOutputStream();
os.write(resp);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(null != socket){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
minusCount();
}
}
}

//Subclasses to override it.
protected byte[] processRequest(byte[] buf, int size){

return buf;//echo it.

}
}

/**
* A mock server services to manage the mock servers.
*/
public class MockServerService {
private Set<MockServer> servers = null;

public void setServers(Set<MockServer> servers){
this.servers = servers;
}

protected void init(){
if(null != servers){
for(MockServer server: servers){
new Thread(server).start();
}
}
System.out.println("Service initialized.");
}

public Set<MockServer> getServers(){
return servers;
}

public void stop(){
if(null != servers){
for(Server server: servers){
server.stop();
}
}
System.out.println("Service stopped.");
}
}

Then we need an application entry point and integrate with Spring.

public class MockServer {
public static void main(String[] args){
AbstractApplicationContext ctxt = new ClassPathXmlApplicationContext("context-mockserver.xml");
ctxt.registerShutdownHook();
MockServerService service = (MockServerService) ctxt.getBean("mockServerService");
service.init();
}
}

the context file for Sring defining the beans.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="mockProcessor0" class="MockServer" >
<constructor-arg index="0" value="Server1"/>
<constructor-arg index="1" value="false"/>
<constructor-arg index="2" value="80"/>
<constructor-arg index="3" value="120000"/>
</bean>
<bean id="mockProcessor1" class="MockServer" >
<constructor-arg index="0" value="Server2"/>
<constructor-arg index="1" value="false"/>
<constructor-arg index="2" value="90"/>
<constructor-arg index="3" value="120000"/>
</bean>
<bean id="mockProcessor2" class="MockServer" >
<constructor-arg index="0" value="Server3"/>
<constructor-arg index="1" value="false"/>
<constructor-arg index="2" value="100"/>
<constructor-arg index="3" value="120000"/>
</bean>

<bean id="mockServerService" class="MockServerService">
<property name="servers">
<set>
<ref local="mockProcessor0"/>
<ref local="mockProcessor1"/>
<ref local="mockProcessor2"/>
</set>
</property>
</bean>
</beans>

Until now, nothing to do with JMX. You can run it as a normal Spring application. You can use JConsole to connect with it locally, if you run the application in this command line:

java -cp . -D-Dcom.sun.management.jmxremote MockServer

This is the snapshot of JConsole MBeans tab. Besides the default threads, memory etc. JVM MXBeans, you can't do anything else to this application.

Now, let's just simply tweak the context file, then see what happens. Add this extra block just at the end of the context file.

...

<bean id="mockServerService" class="MockServerService">
<property name="servers">
<set>
<ref local="mockProcessor0"/>
<ref local="mockProcessor1"/>
<ref local="mockProcessor2"/>
</set>
</property>
</bean>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=MockProcessor0" value-ref="mockProcessor0"/>
<entry key="bean:name=MockProcessor1" value-ref="mockProcessor1"/>
<entry key="bean:name=MockProcessor2" value-ref="mockProcessor2"/>
<entry key="bean:name=MockServerService" value-ref="mockServerService"/>
</map>
</property>
</bean>
...

Here it is! The new JConsole MBeans tab populated with your beans. Now you can see the name of each bean and stop it just by invoking the corresponding stop() method of that bean. Done! You can manage your Spring application now!






In a nutshell, following this pattern, you can tweak any of your applications to be manageable in minutes:

  1. Define the management interfaces for your Object.
  2. Spring your application and expose the object as MBean you want control. Nevertheless, Spring is a extremely noninvasive container, don't be afraid. The things need you Springlize is just make a context file for beans, add less than 5 lines of code to create the application context and put the spring.jar in your classpath. Everything is so familiar to you in a POJO world.
  3. Enable the JVM JMX platform MBean server in command line with -Dcom.sun.management.jmxremote and run it.
  4. Launch the JConsole and connect to the application then control it in your hands.

2007/11/06

1.5 & 2 Factor Authentication

1.5 factors:

The Grid data solution:
http://www.brianmadden.com/blog/iForum07/Grid-Data-Security-introduces-really-cool-15-factor-authentication-for-Citrix

Passmark Security's (acquired by RSA):
http://www.rsa.com/node.aspx?id=3072

2 factors:
http://en.wikipedia.org/wiki/Two-factor_authentication

However, don't trust these too much because 2 factor authentication does not work:

http://blog.washingtonpost.com/securityfix/2006/07/citibank_phish_spoofs_2factor_1.html
http://www.schneier.com/blog/archives/2005/03/the_failure_of.html
http://www.vnunet.com/vnunet/news/2139253/two-factor-authentication
http://www.channelregister.co.uk/2005/03/15/2-factor_auth_is_pants/
http://www.cafeid.com/art-sitekey.shtml

Man-in-the-middle attack:

An attacker puts up a fake bank website and entices user to that website. User types in his password, and the attacker in turn uses it to access the bank's real website. Done right, the user will never realize that he isn't at the bank's website. Then the attacker either disconnects the user and makes any fraudulent transactions he wants, or passes along the user's banking transactions while making his own transactions at the same time.

Trojan-horse attack:

Attacker gets Trojan installed on user's computer. When user logs into his bank's website, the attacker piggybacks on that session via the Trojan to make any fraudulent transaction he wants.

To fight these type of attack:

The problem here is that the bank's website doesn't authenticate the message source. The attacker's computer sends the transaction request to the bank, and the bank trusted it blindly during and after the authentication process. The message source, i.e. both the hardware and the software sending the message, must include itself as part of the authentication token as well as in the following transaction requests.

In the trojan-horse attack, the trojan software is not the original software that generates the request. It will try to generate the exact same transaction request the original software will be generating, but ultimitally, it is still not the original software and cannot predict the behaviour of the original software in a full scale. As long as the original software is properly protected against reverse-engineering and have a way to generate some ever-changing additional piece of information that the server can use to validate it's authenticity, (better, this piece of information has something to do with the transaction request itself), it makes it more difficult for the trojan to generate his own transaction request for his own benefit.

In the man-in-the-middle attack, the hacker does not own the user's computer, he cannot overcome this obfuscate without physical involvement. Serial number of the CPU of user's computer? MAC of one of his network card? Some secret signature on user's hard-disk? The problem is that the cient and the server must, separately, has a way to obtain this piece of information independent of each other. This can be quite a difficult problem.

In case of http request, one way I can think of is to use the REMOTE_ADDR cgi variable. Server can get this from the http header, client can get this, by performing a lookup to sites like
http://www.whatismyip.org/ or some similar service provided by the bank.

The client can use REMOTE_ADDR to salt the authentication token as well as future requests. The server can decrypt it using the REMOTE_ADDR variable in the request. Thus, if the man-in-the-middle intercepted the communication and try to relay it to the server, the authentication will be invalid because the REMOTE_ADDR is different as in the original request.

In order to defeat this, the man-in-the-middle will need to not only intercept the communication to the bank, but also to intercept the client's request to get the REMOTE_ADDR and respond with the REMOTE_ADDR of the phishing website. This will require a network device very close to the user's computer, and is quite difficult for most phishing sites.

Another method the man-in-the-middle can try is to decrypt the communication and re-encrypt it with his own REMOTE_HOST environment setting. The way we can fight against this is to use a strong encryption algorithm that needs some good amount of time to be defeated. Thus, by the time the communication is decrypted and re-encrypted, the ever-changing part is already invalid and useless. RSA? SHA? RIPEND? http://www.keylength.com/

Do they work?

Unfortunately, the above solution also does not work. the attacker, being his first step, is to analyze the site/application he's going to phish, and because of the openess of the web page, any code generating the hardware/software identification token will be discovered sooner or later, and he'll incorporate them in the phishing website/trojan software. It'll be more difficult for him if it's a obfuscated standalone application and/or webpages with their source code protected (http://www.antssoft.com/htmlprotector/index.htm), but not at all impossible.

Spring Property Placeholder Configurer

A way to separate configuration parameters: http://almaer.com/blog/spring-propertyplaceholderconfigurer-a-nice-clean-way-to-share

2007/10/25

Singleton vs. Multiton & Synchronization

1. The classic java singleton synchronization problem

public class Singleton{
private static Singleton instance;

/** Prevents instantiating by other classes. */
private Singleton(){}

public static synchronized Singleton getInstance()
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
The synchronized keyword on the getInstance() method is the evil. In a multi-thread environment, every thread will be blocked by each other when trying to grab the singleton instance. This is the classic java singleton synchronization problem.

2. The traditional solution using a static variable

public class Singleton {
private final static Singleton instance = new Singleton();

/** Prevents instantiating by other classes. */
private Singleton() {}

public static Singleton getInstance() {
return instance;
}
}
The singleton instance is initialized during the class loading time. No synchronization is necessary on the getInstance level

3. The Classic synchronized Multiton

public class Multiton{
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();

private Multiton(){}

public static Multiton getInstance(Object key){
synchronized (instances) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null) {
// Lazily create instance and add it to the map
instance = new Multiton();
instances.put(key, instance);
}
return instance;
}
}
}
The Multiton pattern begins with the concept of the Singleton pattern and expands it into an object pool of keys to objects. Instead of having a single instance per runtime, the Multiton pattern ensures a single instance per key. It simplifies retrieval of shared objects in an application.

As we noticed from the above scriptlet, the access to the getInstance() method is synchronized to ensure the uniqueness of instance per key. This, again, is a performance bottleneck in multi-thread environment. The traditional 'static' solution for Singleton pattern can't be used here since the keys are passed into the Multiton on-the-fly. We have no way to predict how many keys will be passed into the Multiton during the runtime.

4. The double-checked locking solution

public class Multiton {
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();

public static Multiton getInstance(Object key) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null){
synchronized(instances){
if ((instance = instances.get(key)) == null){
instance = new Multiton();
instances.put(key, instance);
}
}
}
return instance;
}
}
Yes the double-checked locking does not work for Singleton (http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html), but it does work for our Multiton pattern. Reason? We have our intermediate HashMap object sits in between. Actually we can use the HashMap to solve the Singleton double-checked locking problem as well, if we don't already have the more elegant solution using a static variable.

5. An alternative solution: Using the Java 5 ConcurrentMap

public class Multiton {
private static final ConcurrentMap<Object, Multiton> instances = new ConcurrentHashMap<Object, Multiton>();

public static Multiton getInstance(Object key) {
// Our "per key" singleton
if (instances.get(key) == null){
// Lazily create instance and try to add it to the map
Multiton instance = new Multiton();
instances.putIfAbsent(key, instance);
}
return instances.get(key);
}
}
The Java 5 ConcurrentMap.putIfAbsent(), being an atomic operation, returns the previous value associated with the key instead of the new suggested value. This ensures the uniqueness of the Multiton instance inside the ConcurrentMap.

In this solution, before a key object has been associated with a Multiton object, if two or more threads are trying to retrieve the instance with the same key object, it's possible that multiple Multiton instance will be created inside the if() block. However, the ConcurrentMap ensures that a same Multiton instance is to be returned to the caller. Extra instances are eligible for Garbage Collection as soon as the method returns. You may not want to use this solution if the creation of the Multiton instance is an expensive operation, as in certain situation.

6. Afterwords

Synchronization and double-checked locking is such an interesting classic java topic, I'm so much wanting to participating in any sort of discussion, it'll always be interesting :)

2007/10/24

Java Performance - ALL Tips

Oh yes, this is a complete list of ALL Java perfomance tips. Thanks for www.javaperformancetuning.com

http://www.javaperformancetuning.com/tips/rawtips.shtml

Well well... why another J2EE blog? I benefited from other people's technical blogs, and guess what, it's a good idea to contribute some of my works too. Hope it's helpful and useful, to all of your folks.