Tuesday, January 22, 2008

GWT - UIServiceAsync timing

I've been working a lot with GWT (google web toolkit), and have been using the user interface 'client side' , tying in to the back end. (server side). This introduces a few problems, especially with database calls. GWT translates Java into Javascript for you, but it doesn't try to generate javascript for the code you keep hidden away on the server side (thank goodness, especially since GWT currently only supports Java 1.4!)
So how does it know when the calls to the server side are complete?


Using AsyncCallbacks. These have onSuccess and onFailure methods you write yourself, which tell your UI side what to do when your server side calls have finished.


I have found that the timing of these prove to be a pain. Your client side code, like the tide and time, waits for no man. It will merrily march on, after you have made a call to get some data from the database for instance, and not care whether or not it has completed to run the next line. So you can't really depend on the feedback from the server side on the next line, your data might very well be null.
..or the line after that. or the next one.

So how do you make sure that darn query's output can be properly shown to the user?


the answer lies in the onSuccess method.
You make a structure to contain whatever you need on the UI side, and draw itself (as empty for now, or with a 'loading, please wait' message) to the screen.
Then, pass that container to the Async call. In the onSuccess method, you tell it to write the output to that container and draw itself again.


This way the user will always see something, and you won't get null Pointer exceptions.

Wednesday, January 2, 2008

comparing objects with nulls

When trying to test an object to see if it's null or not (for good error handling purposes), it's good to know: a null object's .equal method doesn't measure up to a null. ie, you can't do this:



String s = null;
String r = null;

possiblySetMyString(r);

if(s.equals(null)){
System.out.println("string not set");
throw new RuntimeException();
}else{
System.out.println(s);
}

public void possiblySetMyString(String t){
s = t;
}



Nope! That won't work. you can't check if a string 'equals' null with the object's .equals method , because it's going to try to compare various String parameters to a null. Instead, replace the s.equals(null) with s==null.
Note: use == to check for primatives (int, char, bool, null etc), and use .equals to compare two objects. If you're comparing two different types, better convert before comparing.

Friday, November 30, 2007

Assignment does not give a copy.

In my naive assuption, I believed that the statement


myMethod Report(Report report){
Report copyofreport = report;
return copyofreport;
}


would give me a new object, an instance of the class Report.

It kind of worked, but introduced a subtle bug. I tried calling this method multiple times, thinking I could get an array of identical reports- but when I did something to my first report, all of the 'copies' I had made were similarly affected, even though I hadn't touched them.

What this actually did was make an array of references that all pointed to my original object, report. when I changed one, the references all reflected the same change.

solution: to make a new, identical object, there's a handy interface called cloneable. implement cloneable, override the method if necessary, and then call .clone().



// public class Report implements Cloneable;
ReportmyMethod Report(Report report){
Report copyofreport = report.clone();
return copyofreport;
}



Much better.
This only creates a 'shallow copy' though, so if there are any inner objects in the cloneable class, the objects will have the same reference. This really only matters if you're going to change the inner objects, but it's good to be aware of.

Wednesday, November 21, 2007

exceptions?

As a still relatively new Java programmer, I'm still having trouble deciding whether or not to throw Exceptions in parts of my code that can go wrong.
This site is a great reference for what to do and what to avoid.


http://today.java.net/pub/a/today/2006/04/06/exception-handling-antipatterns.html



The most useful part: Antipatterns: what you really *shouldn't* do, and why. Here's an excerpt:


catch (NoSuchMethodException e) {
LOG.error("Blah", e);
throw e;
}


"This is one of the most annoying error-handling antipatterns. Either log the exception, or throw it, but never do both. Logging and throwing results in multiple log messages for a single problem in the code, and makes life hell for the support engineer who is trying to dig through the logs."

So true!!

I gotta get a me whole book of antipatterns....

Tuesday, November 20, 2007

Dude, where's my method?

So I was creating a new method in a class. This method the same name, but different signature of an existing method, but it took in different arguments. I finished writing the method bodies, and went back to the class that called my new method.


Oddly, I got the error:

"The method getExchangeDelayPlot(ReportOptions) in the type ExchangeDelaysDAO is not applicable for the arguments (ReportRequest)".


Me: .".what are you talking about, stupid eclipse. I made the method getExchangeDelayPlot(ReportRequest), and saved it, and got no compiler errors. are you blind or something?"


Of course, my IDE was not blind. (isn't that always the case).

What I missed: Although I had added the method to the concrete class (ExchangeDelaysDAOImpl), I was trying to call the method its parent abstract class above this. I had forgotten to add the empty method signature of the new method to the abstract class.


Lesson 1: look carefully at the *type* in the error message.

Lesson 2: remember class hierarchies: remember to add method signatures to any abstract classes or interfaces you're trying to call your methods from.

Wednesday, November 14, 2007

The trouble with arrays

I've always had trouble with arrays. Either I forget to initialize 'em, or worry about hardcoding the upper limit of values they can take... they're a pain.

names = new String[100]; //why 100? it's a magic number! boo!


So I think it's time to work with dynamic arrays. In Java 5.0 and beyond there is a class called
ArrayList
, which is similar to an array, but has no upper limit (hardcoded, anyways). Plus it's dynamic.

but what if I want to sort my strings? I need them in alphabetical order sometimes.
alphabetical sorts are easy peasy with arrays:

java.util.Arrays.sort(array);

There is no ArrayList.sort() method. Luckily, it's a type of Collection, and Collections do have sort methods.


import java.util.ArrayList;
import java.util.Collections;
...
Collections.sort( myArrayList );

Ta-da!

Tuesday, November 13, 2007

Cannot make a static reference to the non-static method

ComponentMap cm = GenericRDSFactory.getRDSComponents(rr);


(where GenericRDSFactory is a different class): gives the error

"Cannot make a static reference to the non-static method":

The static keyword just means that the method or attribute belongs to that class.

The solution: instantiate the class first, then invoke the methods from the new object.

GenericRDSFactory factory = new GenericRDSFactory();

ComponentMap cm = factory.getRDSComponents(rr);