Saturday, August 18, 2007

weirdo NULL handling in SQL

Conisder following SQL statement
SELECT * FROM sometable WHERE num <> 1;
If you expected this to return rows where value of num is null, then you are wrong. Similarly
SELECT * FROM sometable WHERE LENGTH(my_col) < 20
above will not return rows with my_col having null values.

This is bcoz SQL don't consider null as a value and since null is not a value it cannot be compared with a value. This is the diffrence between Null and either 0 (zero) or an empty string (a string value with a length of zero, represented in SQL as '' ). While null indicates the absence of any value, the empty string and numerical zero both represent actual values. So be careful while you are writing "less than" or "not equal to" queries on nullable column.

Got some more time read this on wikipedia.

javax.net.ssl.SSLHandshakeException

If you see collowing exception, while accessing HTTPS URL from java code.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
Then most likely the URL you are accessing doesn't have certificate signed by a CA, and you need to install this certificate manually. Use keytool to import the certificate to a keystore (lets name this as mykeystore and you put this in /etc/keystoers dir) and then start your java application with following parameter -Djavax.net.ssl.trustStore=/etc/keystores/mykeystore.

Hibernate: Computed property value

Many times you want to have computed value from db as a property value of an entity. For simple computation, where you additional information from DB is not needed, you use java code which is fine. But if you need information from DB, it means additional queries. Hibernate provides a powerful feature known as as derived properties

For example consider there is are table called Order and OrderItem; an Order has multiple OrderItem(s) and OrderItem has a field called price. Now if you want orderPrice property in Order Entity such that
orderPrice = sum of all OrderItem.price*OrderItem.qty where OrderItem.orderId=<my order id>.
This can be done simply by defining a property in hbm file like this .

< property name="orderPrice"
formula="( SELECT SUM (OI.QTY*OI.PRICE) FROM ORDER_ITEM
OI OI.ORDER_ID = ID )"/>
These properties are by definition read-only, and the value is computed at load time. You declare the computation as a SQL expression, this translates to a SELECT clause subquery in the SQL query that loads an instance. Make sure you use SQL names (TABLE and column names) and not the Java names (Object and property names). also don't forget to put the formula inside "(" and ")".

Ant javac: Unknow source in stacktrace

I,Nidhi and Kush at mChek were debugging some code and got following exception

Exception in thread ... java.lang.ClassCastException
at SearchCustomerAction.search(Unknown Source)
Some googling helped and we found the reason. It was obvious that Java compiler didn't generate the debugging information. But why? I thought I had not provided any extra javac parameters, and by default javac should generates debugging information (it actually generates line number and source file information by default, local variable information is not generated by default). So wats wrong?

Actually we had used Ant for our build and javac Ant task by default doesn't generate debugging information. So the debug flag need to be turned "on" explicitly, something like this:
<!-- build.xml -->
<project name="someProjectName" default="build" basedir=".">
<target name="build">
<javac srcdir="." destdir="." debug="on"/>
</target>
</project>
For more information see javac and ant javac task.

Saturday, August 04, 2007

AJAX response: HTML, XML, JSON

Its fun to have the partially refreshing dynamically modifiable page using AJAX, both for application developer and for application user. But as a application developer parsing the partial response from server and dynamically modifying the DOM can become very complicated, parsing the response itself can be very tedious. Though the 'X' in AJAX stands for XML but your response need not be XML, it could be any text format, for our discussion we consider following three text response types

  • HTML/plaintext
  • XML
  • JSON
If you just need to modify one section of page and can use the response as is, then its no-brainer, you simply use HTML or plain text response. e.g. if you build expand collapse control where you want to display some information in a div/span you just get processed HTML from server and use it as follows in you onreadystatechange event handler:
var expandAreaDiv= document.getElementById("expandAreaDiv");
expandAreaDiv.innerHTML=text;
But life is not this simple always :-). As you application matures need arise to modify multiple section of the page with one response. One response and multiple modification means you can no longer use the response as is, you have to parse the response. By default we tend to use XML as the only option; after all 'X' in AJAX stands for XML :-)
Take a simple example, if you performed update of some entity using AJAX than probably you need to do following
if success
update the status field
show the success message
else
show the failure message
So bare minimum you need three separate informations from server in one response
boolean value indicating success/failure
String value containing the message response
String value containing the new Status
So you decide to have XML like this

<myResponse>
<isSuccess></isSuccess>
<newStatus></newStatus>
<message></message>
<myResponse>

and in javascript you parse the response to get values into variables and then use it..
var response= req.responseXML.getElementsByTagName('myResponse');
var isSuccess = getNodeValue(response,'isSuccess');
var newStatus= getNodeValue(response,'newStatus');
var message= getNodeValue(response,'message');
function getNodeValue(obj,tag){
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
and as your XML becomes complex parsing becomes more complex and you start looking for some parsing tools. This is where i like JSON, which stands for JavaScript Object Notation. Your JSON response would look like this:
{
"isSuccess" = true,
"message" = "Successfully updated the Status",
"newStatus = "Active"
}

and here is you response parsing code in JS:
var response = eval( '('+req.responseText + ')' );
and voila you can acess response.isSuccess, response.newStatus, response.newStatus. All parsing is done for you just by eval().

Be careful that you take care of JSON special character " and control characters like CR NL in the generated response.
e.g. "message" = "Successfully
updated the Status",
will not work. JSON is not as readable as XML, but its more readable for computer :-) . Though I could not find any powerful JSON editor but this one is useful.

Finally, as far as security is concerned JSON by itself is just a data format (like XML) so it is secure, but the eval function is not, so if someone could inject malicious script into your JSON, that would get executed on to the client. So make sure you validate the data before you put into JSON response (this you should do anyway if you need your application to be secure).

Friday, August 03, 2007

html checkbox submitting unchecked value

If you have used checkbox you would know that the checkbox value get submitted with form only if checkbox is checked, this is required by w3 html spec . What if you want to know if a checkbox was already checked when page was rendered and now unchecked by user. Specially if you are using a framework like struts and want to set a value in ActionForm based on checkbox value. Try submitting the form using Java script


<form name=myForm action="something.do" >
<input type=checkbox name=mycheckbox value=test />
...
Your normal form code here
...
<div id="hiddenArea"/>
<input type=button name='submitMyForm' value='submitMyForm' onclick='submitMyForm()'>
</form>

function submitMyForm(){
var hiddenArea = document.getElementById("hiddenArea");
var myCbx = document.myForm.mycheckbox;
if(!mCbx.checked){
var hiddenStr = "<input type=hidden name=mycheckbox value=notest />";
hiddenArea.innerHTML =hiddenStr;
}
document.myForm.submit;
}

Array: new vs. java.lang.reflect.Array.newInstance

Since i was writing about array I thought this is also worth mentioning.
There are two ways of creating array
String str[] = new String[4];
String str[] = (String[]) java.lang.reflect.Array.newInstance(String, 4);

Both are same, you use second one where you can't use the first i.e. you don't know the type of array in advance.

Lets discuss Array Typecasting

You would think this code should work:
Object[] objs = new Object[2];
objs[0]="Hello";
objs[1]="World";
String[] strs = (Str[]) Objs;
// print the array..

Code compiles fine, but when you run it, you get java.lang.ClassCastException. And you start wondering why? String is subclass of Object so its not narrow conversion then why do i get ClassCastException. I tried to find answer on net but could not find, so below is just my own logic (disclaimer :-) )

String extends Object fine, but String[] doesn't extend Object[] both of them extend Object, in short they are not in hierarchy so you get ClassCastException. Lets look into more detail

Lets try System.out.println(strs.getClass()); which prints --> [Ljava.lang.String
and System.out.println(obj.getClass()); prints --> [Ljava.lang.Object
only common thing is [L, what is this?

Class Type that defines an Object consist of two things ClassType and ComponentType. For all array objects class name is same i.e. [L, but component types differs. Which implies Java Arrays are special type of classes whoes Class Type is represented by [L. If you had some way of setting the componentType, typecast would have worked. But it is pretty obvious that setComponentType can't be exposed.

Now finally I think we should discuss the solution to above problem. There are two solutions but none which could avoid an additional array creation.

Solution 1:
String[] strs = new String[objs.length];
System.arraycopy(objs,0,strs,0, objs.length);

Solution 2:
If you are using List you can use Object[] List.toArray(Object[])
//assuming you have done List list = Arrays.asList(objs); for our current example.
String[] strs = new String[2];
strs = (String[])list.toArray(strs);

Now if you look at solution 2 and wonder why typecasting worked here, it worked because ComponentType of the Array returned by toArray method has ComponentType same as the componentType of the Array passed to it. The argument is just used to get the comonentType
i.e. this would also work
strs = (String[])list.toArray(new String[0]);