Monthly Archives: August 2011

(Last) Week full of surprises

Last week was very surprising.

Nokia surprised me by actually delivering Symbian Anna for my N8 phone. Wow.

After that, I went on and bought myself a copy of Minecraft and wow, it works on my Linux laptop with integrated Intel 965 graphics! Wow! What’s even more, it works on my Linux desktop with radeon r730 based graphics card. WOW.

Notch and the rest of the Mojang AB crew are seriously hurting Java’s reputation as server-side only platform. What’s even more strange I’m yet to see a single GC pause even though I have clocked serious hours with minecraft.

Back to the Nokia actually delivering something. It’s rather sad. Had they released N8 with Anna (like a year ago) N8 would had been a killer. Now thanks to Elop it’s just outdated. All the cool apps are done for Android (and iPhone, even more sadly).

I would though like to know how did they recover from disasterious release of PR1.2 (the previous Symbian^3 update) to this Anna release; was it just that it was 9 months late? I mean, this update was released immediatedly for a variety of phones. Though, knowning Nokia there must still be a lot of users stuck with PR1.2 and throwing the phone around. But hey at least the Ovi Suite still sucks and seems to be the only way to upgrade software on the phone..

Advertisements

Asserting generic implementations in Java

A while back I ended up creating a simple interface like Predicate<T> as follows:

public interface Predicate<T> {
  boolean evaluate(T state);
}

Now when you create a bean that requires a predicate on some object, you’d code a setter for it:

package org.example.foos;

public class Foo {
  private Predicate<Bar> guardPredicate;

  public void operate(Bar bar) {
    if (!guardPredicate.evaluate(bar)) {
      throw new IllegalStateException();
    }

    // do stuff with bar
  }

  public void setGuardPredicate(Predicate<Bar> guardPredicate) {
    this.guardPredicate = guardPredicate;
  }
}

And embed this bean in your Spring ApplicationContext like:

<beans ...>
	<bean class="org.example.foos.Foo">
		<property name="guardPredicate">
			<bean class="org.example.foos.support.SomeBarPredicate" />
		</property>
	</bean>
</beans>

From the name of “SomeBarPredicate” you’d expect it to implement Predicate<org.example.foos.Bar>, but there’s no guarantee on that; an implementation of Predicate<java.lang.String> could be passed in as well. There’s no automatic runtime checking because of type erasure.

Class metadata to the rescue!

Whenever your class implements or extends a generic interface or class, this data is recoverable through Class.getGenericInterfaces() or Class.getGenericSuperclass().

Getting the information out is rather painful tough, and I’m not going to re-iterate the examples out there for this. For one, please see Reflecting generics by Ian Robertson.

Luckily Spring 3.0 has a utility class for this: GenericTypeResolver.

For our example, the setter should be rewritten as:

  public void setGuardPredicate(Predicate<Bar> guardPredicate) {

	Class<?> param = GenericTypeResolver.resolveTypeArgument(guardPredicate.getClass(), 
		Predicate.class);
	if (param != null // if null, it was unrecovarable, treat it as Class<Object>
		  && !param.isAssignableFrom(Bar.class)) {
		throw new IllegalArgumentException();
	}
	this.guardPredicate = guardPredicate;
  }

So lets test this with JUnit 4 and Spring testing utitilities:

package org.example.foos;

import static org.junit.Assert.fail;

import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;

public class FooTest {

	private Foo foo = new Foo();
	
	@Test
	public void testSetGuardPredicate() {
		setGuardPredicateScenario(new Predicate<Bar>() {
			public boolean evaluate(Bar state) {
				return state.toString().contains("Bar");
			}
		});
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testSetGuardPredicateWithWrongTyped() {
		setGuardPredicateScenario(new Predicate<String>() {
			public boolean evaluate(String state) {
				return state != null && !state.isEmpty();
			}
		});
	}
	
	@SuppressWarnings("rawtypes")
	@Test
	public void testSetGuardPredicateWithUntyped() {
		setGuardPredicateScenario(new Predicate() {
			public boolean evaluate(Object state) {
				return state != null;
			}
		});
	}
	
	private void setGuardPredicateScenario(Object predicate) {
		ReflectionTestUtils.invokeSetterMethod(foo, "guardPredicate", 
				predicate, Predicate.class);
		foo.operate(new Bar());
	}
}

Voila, tests pass. Be sure to test it without our assertions as well; look at “testSetGuardPredicateWithWrongTyped” result to see a not so nice ClassCastException:

java.lang.Exception: Unexpected exception, expected<java.lang.IllegalArgumentException> but was<java.lang.ClassCastException>
Caused by: java.lang.ClassCastException: org.example.foos.Bar cannot be cast to java.lang.String
	at org.example.foos.FooTest$2.evaluate(FooTest.java:1)
	at org.example.foos.Foo.operate(Foo.java:11)
	at org.example.foos.FooTest.setGuardPredicateScenario(FooTest.java:49)
	at org.example.foos.FooTest.testSetGuardPredicateWithWrongTyped(FooTest.java:27)

With assertions we catch that configuration problem in earlier refresh stage.