Breaking into the Spring container with singletons
I was faced with a pesky security library at work. I had written my application with the help of Spring, but the security library was tightly coupled - and I really had viable option of rewriting it as it would break a lot of other applications depending on it. The only bit I could implement myself was the login module - which had to implement an interface with no constructor arguments. So I had to go out and figure out how to break into my Spring container from this login implementation and get a hold of some Hibernate DAOs to do the actual login procedure.
When configuring your spring container you can set the bean's factory method, and thus creating a singleton accessible both from Springs context and from the J2EE container. So I created a singleton class, and tried loading it up in the application context.
public class DatabaseFacade { private static DatabaseFacade instance = null; private HibernateSubscriptionRepository subscriptionRepository = null; public static DatabaseFacadeImpl getInstance() { if (instance == null) { instance = new DatabaseFacadeImpl(); } return instance; } public void setHibernateSubscriptionRepository(HibernateSubscriptionRepository repo) { subscriptionRepository = repo; } public HibernateSubscriptionRepository getHibernateSubscriptionRepository() { return subscriptionRepository; } }
And adding it to my dataAccessContext.xml:
<bean id="databaseFacade" class="somepackage.DatabaseFacade" factory-method="getInstance" lazy-init="false>
<constructor-arg ref="subscriptionRepository" />
However, this didn't quite work out since my subscriptionRepository reference is in reality annotation-driven. The reference doesn't return a HibernateSubscriptionRepository - but instead a proxy. So I got a nice little error message instead:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [no.tdn.njaas.HibernateSubscriptionRepository] for property 'hibernateSubscriptionRepository'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [no.tdn.njaas.HibernateSubscriptionRepository] for property 'hibernateSubscriptionRepository': no matching editors or conversion strategy found
To work around this I had to make my DatabaseFacade implement an interface. I renamed the implementation and created an interface with the setters and getters for the DAO.
public class DatabaseFacadeImpl implements DatabaseFacade {
The next snag is from the transaction handler. I'm using Springs built-in transaction handler - and that only sees beans managed by Spring. And my LoginModule of course, isn't. So I had to jump onto using pure AOP instead. Luckily Spring already has an implementation of a pointcut that will find @Transactional annotations and wrap transaction handling around it - so we're home free there. I'll just annotate the methods in my LoginModule that requires database access with @Transactional and it should work.
<bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf">
<property name="transactionManager" ref="transactionManager" />
</bean>
And then setting an extra JVM argument:
-javaagent:aspectjweaver.jar
And it works! Nicely done. I have now given my legacy LoginModule access to my application contexts Hibernate instance, with AOP transactions.
You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.








September 25th, 2009 at 8:53 am
I also found the following article in relation to breaking the singleton pattern.
http://yohanliyanage.blogspot.com/2009/09/breaking-singleton.html