Thursday, November 29, 2007

Passing and Returning Nulls

Several blog posts about handling null values caught my attention.

The pair of posts from Marty Alchin on "Returning None is Evil" and "Except the Unexpected" offer these opinions:
  • most methods can return null
  • Java has lots of APIs that silently return null (java.util.Map.get(Object key))
  • returned nulls are annoying and hard to debug
  • exceptions should be preferred when a non-null value isn't available
  • always consider when/how nulls should(n't) be used
Cedric Otaku in "It's okay to return null" chimes in with these valid points:
  • don't return exceptions unless something really is exceptional
  • use the Null Object pattern if you need it
Neither of those suggestions (exceptions or Null Object) really work out well for my taste. I really don't like these bad choices:
  1. Write clear and direct code -- that neither shows where nulls could be hiding nor handles them well when they occur
  2. Write lots of verbose if/then/else and try/catch blocks to deal with nulls everywhere
So what to do? Borrow a construct from somewhere else of course!

In the Scala programming language I was introduced to the Option class. I'm pretty sure that is comes from Haskell and other places, but I'm not really researching it.

An Option is like a list of zero or one elements; either a Some with a value, or a None.

Functions that return or receive "optional" things use an Option wrapper to both document that fact and promote cleaner code constructs. Here is an example.

Normal Java code with an override variable:

String overrideMessage;
final String defaultMessage="Howdy";

public String sayHello(String name) {
String s=null;
if (overrideMessage!=null)
s = overrideMessage;
else
s = defaultMessage;

return s+" "+name;
}

Yuck! Now let's uses Option to clean up that method:

Option<String> overrideMessage=none();
final String defaultMessage="Howdy";

public String sayHello(String name) {
return overrideMessage.or(defaultMessage)+" "+name;
}


Much nicer. The Java version can accept alternate values (with the or() method) but not code blocks to execute like the Scala version can (unless Java gets closures...). The Scala version can participate in list comprehensions and all sorts of other things, but I'm not not talking about those things now.

Here is the full version of my Option port to Java:

public class Options {

/**
* An Option can be either full (Some<T>) or empty (None).
* Instead of passing/returning nulls use an Option
*/
public abstract static class Option<T> {
public final boolean some;
public final boolean none;

private Option(boolean some) {
this.some = some;
this.none = !some;
}

abstract public T val();

public T or(T defaultResult) {
if (some)
return val();
else
return defaultResult;
}
}

/**
* Placeholder for empty
*/
public static class None<T> extends Option {
private None() {
super(false);
}
public T val() {
throw new NullPointerException("Can't dereference a None value");
}
}

/**
* A Holder for some value (never null)
*/
public static class Some<T> extends Option {
private final T val;
private Some(T val) {
super(true);
this.val = val;
}
public T val() {
return val;
}
}

/**
* Use this when not sure if value is present or null
*/
public static <T> Option<T> option(T value) {
if (value==null)
return none();
else
return some(value);
}

/**
* Use this to wrap a non-null value
*/
public static <T> Some<T> some(T value) {
return new Some<T>(value);
}

@SuppressWarnings("unchecked")
private final static None NONE=new None();

/**
* Use this when you don't have a value
*/
@SuppressWarnings("unchecked")
public static <T> Option<T> none() {
return NONE;
}
}

Tuesday, November 27, 2007

Using a lazy proxy to avoid Spring dependency cycles

Ever gotten a dependency cycle in your Spring configuration?

How about using the Hibernate Annotations and @Configurable together?
  1. Hibernate will instantiate a single instance of each Entity class and ask for the default key value.
  2. But when the first instance is instantiated @Configurable will try to Spring configure that instance.
  3. It that Entity depends on anything that leads back to Hibernate... Bang!
I like this quote from Rod Johnson: "Ouch: this is nastier." That about sums it up. Oh, and that quote is from 2004.

I created a LazyProxyFactoryBean to allow me the chance to not break the cycle, but at least lazy resolve it. Combining a Spring FactoryBean with a dynamic proxy does the trick. Hope this can help someone else out there.

Here is a failing example with cycles:

<bean id="serviceA" class="com.ServiceA">
<property name="serviceB" ref="serviceB"/>
</bean>

<bean id="serviceB" class="com.ServiceB">
<property name="serviceA" ref="serviceA"/>
</bean>


Here is a modified version with a lazy proxy inserted (notice that proxy property is a value, not a ref):

<bean id="serviceA" class="com.ServiceA">
<property name="serviceB" ref="serviceB"/>
</bean>

<bean id="serviceB" class="com.ServiceB">
<property name="serviceA" ref="serviceAProxy"/>
</bean>

<bean id="serviceAProxy" class="com.LazyProxyFactoryBean">
<property name="serviceA" value="serviceA"/>
</bean>


Finally, here is the source code:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;

public class LazyProxyFactoryBean implements FactoryBean, BeanFactoryAware {

private String beanName;
private BeanFactory beanFactory;
private Object proxyObject;
private Object realObject;

public LazyProxyFactoryBean() {
}

public Object getRealObject() throws Exception {
if (this.realObject == null)
this.realObject = this.beanFactory.getBean(this.beanName);

return this.realObject;
}

public Object getObject() throws Exception {
Class[] ifcs = getProxyInterfaces();
if (ifcs == null) {
throw new FactoryBeanNotInitializedException(
getClass().getName() + " does not support circular references");
}
if (this.proxyObject == null) {
this.proxyObject = Proxy.newProxyInstance(getClass().getClassLoader(), ifcs,
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(getRealObject(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
});
}
return this.proxyObject;
}

public Class getObjectType() {
return beanFactory.getType(beanName);
}

public boolean isSingleton() {
return false;
}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}

protected Class[] getProxyInterfaces() {
Class type = getObjectType();

if (type != null && type.isInterface()) {
return new Class[] {type};
} else if (type != null) {
return type.getInterfaces();
} else {
return null;
}
}

public void setBeanName(String beanName) {
this.beanName = beanName;
}
}

Notes from NetObjectives Lean Webinar

These are notes from a NetObjectives Webinar on "Using Lean Thinking to Align People, Process and Practices".

This was a really succinct presentation that still covered a lot of ground. If you register it is still available for free viewing!

Lean Software Development:
Focuses on the ability to add value quickly now, while improving the ability to add value quickly in the future.
Edwards Deming:
  • Plan-Do-Check-Act (PDSA)
  • System of Profound Knowledge
Gary Hamel. "Management Innovation" in Harvard Business Review. Feb 2006
Only after American carmakers had exhausted every other explanation for Toyota's success - an undervalued yen, a docile workforce, Japanese culture, superior automation - were they finally able to admit that Toyota's real advantage was its ability to harness the intellect of 'ordinary' employees.
Lean - A New Paradigm
Engaged, thinking people
Referenced "Software by Numbers" (better graphics...)

Tuesday, November 20, 2007

Just In: REST can't handle state!!

Or, maybe Jean-Jacques Dubray, Ph.D. doesn't understand hypermedia. :(

In his post on the states and transitions of a resource he claims that REST has no way to let a client know what state transitions are available for a given resource....

Um, what is hypermedia?
Distributed hypermedia provides a uniform means of accessing services through the embedding of action controls within the presentation of information retrieved from remote sites.
This quote is just the introduction to hypermedia and REST, but we already have an answer.

Action controls are embedded. Action controls are embedded.

Embedding the action controls means
  1. The client doesn't need to have generated (and hard-coded) client stubs.
  2. The server can change it's rules and expand available states as needed.
  3. The client does need to process a generically extensible content type.
That last point isn't free or trivial, but it enable the first two.

Perhaps more directly on point is this quote from 5.3.3 Data View:
The model application is therefore an engine that moves from one state to the next by examining and choosing from among the alternative state transitions in the current set of representations.
Jean-Jacques' answer to how to share types, constraints, correct states, and transitions is not suprisingly: a schema and a business interface. Let's take those four goals one at a time:
  • Types: definitely covered by IDL (until the systems changes then you need to tell everyone to re-compile...)
  • Constraints: Not even covered a little by todays SOA technologies. Until there is an OCL or Catalyis (or Z or ...) model that get's compiled with WSDL the best a schema and business interface will have for constraints is a few lines of prose... (in <!-- XML comments no less!! -->)
  • States: WSDL is not much help, maybe you can infer the states from the operation names? SSDL I think actually does cover this...
  • Transitions: Same as states; how do we deduce which operations are transitions?
I really can understand the challenge and barrier to hypermedia state control with generic clients. Machine processing and interoperability in this context is unfamiliar: an "engine ... choosing from among the alternate state transitions" is very declarative and make a historically imperative programmer (me!) feels out of control.

Static class diagrams (WSDL) and code-generation are so much more in my control and experience. If only they worked for distributed systems without so many negatives...

The complete ignorance of hypermedia and FUD in the blog posting compelled me to respond and put my $.02 in.

Monday, November 19, 2007

Glassbox 2.0 RC1 is available!

The 2.0 release candidate for Glassbox Troubleshooter has been released!

Glassbox is an open source Java monitor and troubleshooting application:
  • Easy to deploy to many app servers (deploy the war, click "Install", restart server)
  • Lightweight monitoring: only instruments key layers for efficiency
  • Extensible monitors (in XML or code) to domain-specific operations for better reporting
For more information I would recommend browsing the slides I presented at the Dallas JUG, or watching Ron Bodkin Google Tech Talk on Glassbox.

How am I related to this? I'm a committer for the project and have been most responsible for the automated installation support.