Java: make your DAO returning null-safe values with Spring AOP

Radek Anuszewski
4 min readMay 29, 2016

--

Aspect-oriented programming (AOP) helps us to remove code repetition and makes responsibility of objects clearer. This article covers usage of Special Case Design Pattern with Spring AOP.

Data Access Object

Data Access Objects are well-known and widely used. Also, in database access is common to use Base DAO known also as Generic DAO. So, without further ado, let’s see simple example of Base DAO (strongly based on provided link) which is meant for Hibernate ORM:

public interface BaseDAO<ENTITY> {
void save(ENTITY entity);

void update(ENTITY entity);

void delete(ENTITY entity);

ENTITY getById(Long id);
// other methods
}
public class BaseDAOImpl<ENTITY> implements BaseDAO<ENTITY> {
private final Class<ENTITY> type;
private final String typeStr;

@Inject
protected SessionFactory sessionFactory;

public BaseDAOImpl() {
type = (Class<ENTITY>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
typeStr = type.toString();
}

private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}

@Override
public final void save(ENTITY entity) {
getCurrentSession().save(entity);
}

@Override
public ENTITY getById(Long id) {
return (ENTITY) getCurrentSession().get(type, id);
}
// other, very similar implementation

And implementation for User entity, UserDAOImpl:

public interface UserDAO extends BaseDAO<User> {

}
public class UserDAOImpl extends BaseDAOImpl<User> implements UserDAO {

}

Interface and implementations are empty at this moment, because it has only simple operations which are inherited from Base DAO.

Make DAO returning null-safe value with Special Case design pattern

Method list() from Criteria interface returns empty list when when query returns no results, for example if User doesn’t have any orders. But uniqueResult() method from the same interface returns null it that situation. And it forces us to make code using that results responsible for null-checking.

Special Case design pattern

Special Case design pattern is provided for situations like that. For User entity, it could be class with name, surname and email as empty strings. Implementation is not important, important is way how we can return it from our UserDAO:

@Override
public User getById(final Long id) {
User user = super.getById(id);
if (user == null) {
return NullUser.getInstance();
}
else {
return user;
}
};

We had to reimplement getById() method just to add null-checking. But we can do it without changing existing code with Spring aspect.

Spring and Aspect-Oriented programming

What we really want to do is to call method, check if it returns null and make some actions related with it. It sounds very general, and it is not related in any way with fetching data from database and with User entity/its DAO. This is a moment when Spring AOP can help us with moving null-checking logic to separated file and with calling it every time when getById() method is called.

Declaring component for null-checking logic

First, we need to have a component with checking logic. We can use Component annotation from Spring. But I think we should avoid using things related with framework when we can use thing provided by language itself, so we can use also use Named annotation from javax.inject, and with it in this component we don’t have any dependencies from Spring. Here’s the code:

@Named
public final class PreventNullReturn {
public static Object replaceNullWithSpecialCase(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// proceed() runs advised function and returns its result
Object ret = proceedingJoinPoint.proceed();
if (isInvokedOnUserDAOInstance(proceedingJoinPoint) && ret == null) {
return NullUser.getInstance();
}
else {
return ret;
}
}

private static boolean isInvokedOnUserDAOInstance(final ProceedingJoinPoint proceedingJoinPoint) {
return proceedingJoinPoint.getThis() instanceof UserDAO;
}
}

ProceedingJoinPoint class has proceed() method, which calls advised method and returns advised method call result. In our case, we get User instance or null. Weird part is dispatching whether we should return SpecialCase or not. We should check if ret is null and also, if advise was called on UserDAOImpl. To do this, we need to use ProceedingJoinPoint.getThis() method inherited from JoinPoint, which returns object containing advised method and check if it implements UserDAO interface. Unfortunately — I tried to move aspects declaration to separated file, but it didn’t work. I asked question on StackOverflow about it: Spring AOP before and after method not working with XML configuration. Please answer if you know how to do it, I would be very grateful to you.

Declaring aspect in applicationContext.xml

Because I use XML based configuration, aspect also should be declared in applicationContext.xml file:

<aop:aspectj-autoproxy/>

<bean class="aspects.PreventNullReturn"
id="preventNullReturn"
></bean>

<aop:config>
<aop:aspect
ref="preventNullReturn"
>
<aop:pointcut
id="preventNull"
expression="execution(* *.getById(..))"
></aop:pointcut>
<aop:around
pointcut-ref="preventNull"
method="replaceNullWithSpecialCase"
></aop:around>
</aop:aspect>
</aop:config>

We should define pointcut with expression which calls advise, in our case it is any call of getById with any arguments. And we need to declare aop:around element with method bounded. Other are, for example, aop:after and aop:before, we use around because our advise should “cover” original call.

Conclusion

Aspect-oriented programming has many use-cases, it helps to prevent repeating yourself and to keep code clean and responsible only for things that should be responsible.

--

--

Radek Anuszewski

Software developer, frontend developer in AltConnect.pl, mostly playing with ReactJS, AngularJS and, recently, BackboneJS / MarionetteJS.