Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

Monday, 26 May 2008

Java code to concatenate values from get__ methods of a class dynamically

Ended up discarding this code from a project, but this was a good
exercise to learn a little about Java reflection methods.

This was based on code from HashCodeBuilder in Apache commons-lang,
which can generate hashcodes via reflection - ie,
HashCodeBuilder.reflectionHashCode(this);


/**
* Given an object of type clazz, go through the fields in that
class and concatenate the
* values of all the fields, excluding the ones listed in excludedFields.
* This will only work on bean-type getter methods that 1. do not
have parameters
* and 2. return a String.
* This code does not do any lookup on inherited methods.
* @param object instance where we are getting field values from.
* @param clazz the Class of the object.
* @param builder StringBuilder object to contain our concatenated values.
* @param excludeMethods fields that are not to be included in our builder.
* @throws InvocationTargetException when an error occurs while
calling a method in our object.
*/
public static void concatenateFieldValues(Object object, Class
clazz, StringBuilder builder,
String[]
excludeMethods) throws InvocationTargetException
{

List excludedMethodList = excludeMethods != null ?
Arrays.asList(excludeMethods) : Collections.EMPTY_LIST;

Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods)
{
// only get values from public getter methods that are not
in exclusion list
if ((method.getName().indexOf("get") == 0)
&& !excludedMethodList.contains(method.getName())
&& (Modifier.isPublic(method.getModifiers()))
) {
try {

// this will only deal with bean-type get methods
without params
assert method.getParameterTypes().length == 0;

// TODO - shouldnt we explicitly check and throw
an exception here?
Object fieldValue = method.invoke(object);

if (fieldValue instanceof String) {

builder.append(StringUtils.remove(fieldValue.toString(), ' '));
}
} catch (InvocationTargetException e)
{
throw new InvocationTargetException(e, "Unable to
invoke the method: " + method.getName() +
" from
instance of: " + clazz.getName());
} catch (IllegalAccessException e) {
// this can't happen. Would get a Security exception instead
// throw a runtime exception in case the impossible happens.
throw new InternalError("Unexpected
IllegalAccessException");
}
}
}

}

Friday, 23 May 2008

Java generics - assigning a List<C> where type D implements interface D to a variable of List<D> - can't be done - AKA:Type Erasure ARRGH!

Java generics still confuse me.

A work colleague was asking me something about assigning typed lists
and it wasn't working the way
it would work if you were simply dealing with single variables.

Class C implements interface D.

Then we have a list of interface D.

Another class E has a method findAll() which returns a list of type C.

But we can't assign E.findAll() to a list of type D.


List<Comparable> listOne;

listOne.add("String");
listOne.add(new Long(1000));

BUT

listTwo = new ArrayList<Long>();

listTwo.add(new Long(33));

listOne = listTwo;

Error: "Incompatible types, Required List<java.lang.Comparable> Found:
List<java.util.List>"


Hmm... maybe we can cast the list?

listOne = (List<Comparable>) listTwo;

Error: Inconvertible types; cannot cast
'java.util.List<java.lang.Long>' to
'java.util.List<java.lang.Comparable>'

But why?

Saturday, 12 April 2008

How to run code when your Java program is being terminated? Use ShutdownHook!

The starting point for this was a problem I have at work, where we have a program that is using ScheduledExecutorService, and is meant to run continuously, but we also want to run some code when the program is terminated with Ctrl-C or a 'kill' command.

At first, I thought that a try-finally would give me what I wanted. A little bit of testing proved me wrong. The try-finally structure can handle exceptions, and ensure that code enclosed in finally is called, but only in the case where the process is running normally, and not terminated externally. The statement inside a finally{} will not execute if the JVM is terminated.

The ShutdownHook is what I needed, which was added in JDK 1.3.1.  The method to use is Runtime.addShutdownHook().  The shutdown hook is pretty much any code you put inside the Thread.run() that you pass to this method.

public class FinallyTest {
public static void main(String[] args) {

final int thisNumber = 9;
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("I am now calling my shutdown stuff. EVERYTIME!");
System.out.println("This number: " + thisNumber);
}
});

try {
System.out.println("FinallyTest.main");
boolean loopIt = true;
int i = 0;
System.out.println("Now entering infinite loop.");
while (loopIt) {
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

} finally {
System.out.println("Finally has been called!");
}
}
}





Running the program, and then killing it gives me (this is on OS X, on an iMac):

krangsquared$ java -cp . FinallyTest &
[1] 5735
krangsquared$ FinallyTest.main
Now entering infinite loop.

Okay, we now have a process Id. Let's kill it! 


krangsquared$ kill 5735

krangsquared$ I am now calling my shutdown stuff. EVERYTIME!
This number: 9

[1]+ Exit 143 /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Commands/java -cp . FinallyTest


The only catch to this is that this will not work if you terminate the program using "kill -9".  And I haven't checked this yet on Windows to see what happens if you kill it using TaskManager. (is there a "kill -9" equivalent on XP?)

Hope this helps someone out there! Or maybe someone who has a better idea or suggestion can make a comment. I need all the help I can get.  :)

Btw, I've found a blog post with a nicer way of doing this - instead of dumping a whole lot of stuff in a Thread.run() as an anonymous inner class (insert. closures. proposal. here.), have another Runnable inner class to contain all the shutdown code, then pass that in to the constructor of a new Thread that you pass to addShutdownHook().