All entries for July 2006
July 08, 2006
So after working for ELAB for the past year, the time has now come to part ways.
My next role will be as a consultant providing training/architecture+code reviews etc for the Spring framework, Spring Web Flow and possibly hibernate. I have done mentoring + training courses before, but the main focus of my previous jobs has always been to produce architectures/code, it will be interesting to see whether I “take” to the new balance (mainly mentoring, reviewing, little code).
We shall see ;)
Anyways, it has been fun, and working for a Uni is most definately a different experience from working in the “real world” ;) and I have thoroughly enjoyed it, and dare I say may return one day :)
And yes Chris, SBR2 is August 2006, and even 2007 compliant ;) As for webgroups and formsbuilder…. ;)
July 05, 2006
<bean name="myControllerTarget" class="uk....MyController"> </bean> <bean name="/mycontroller/myurl.htm" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>org.springframework.web.servlet.mvc.Controller</value> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> <value>myControllerTarget</value> </list> </property> </bean>
(Let’s not go into the whole “transactional controller” debate :))
Anyway, whilst being very verbose, this had the very valuable benefit of being extremely explicit. Which, as we will see, is extremely useful quality.
So I decided that I would use Spring’s new schema and ended up with:
<tx:advice id="readWriteTxAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="handleRequest"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* org.springframework.web.servlet.mvc.Controller.*(..))"/> <aop:advisor advice-ref="readWriteTxAdvice" pointcut-ref="serviceMethods"/> </aop:config>
and everything stopped working :( More specifically, when I programatically rolled back a transaction I would end up with an UnexpectedRollbackException :( After asking the exceptionally helpful people at the Spring forum (http://forum.springframework.org/showthread.php?t=26574), it turned out that I had somehow managed to end up with a nested transaction….the nested transaction was marked as rollback whilst the outer transaction was trying to be committed.
So, off I go exercising my brain trying to determine how on earth I was getting a nested transaction and I thought “hmmm, the pointcut is Controller., maybe this is being applied to implementations of Controller”. Given that the AbstractController has a “handleRequest” and “handleRequestInternal” method, I assumed *yes, ass out of u and me ;) that one transaction was being started when handleRequest was invoked and another when handleRequestInternal. This is wrong wrong wrong for two reasons; Controller.* doesn’t match (although I need to confirm this) methods on subclasses and secondly the transaction advice explicity only handles the “handleRequest” method, but why should I let little things like that stop me :)
So I thought, “well, the pointcut is obviously too inclusive, lets restrict it” and ended up with
<tx:advice id="readWriteTxAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="handleRequest"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* org.springframework.web.servlet.mvc.Controller.handle(..))"/> <aop:advisor advice-ref="readWriteTxAdvice" pointcut-ref="serviceMethods"/> </aop:config>
Thats better isn’t it. Deployed, and it worked.
Then it struck me…..the method on the Controller is called “handleRequest”, not “handle”.....as a result the pointcut would match absolutely nothing :)
So how the flipping heck is this thing working, because rollbacks were working, commits were working etc.?
The other point to this joyful account is that fact that the context in which the aop was defined was importing another context which had a controller defined (actually it was the Spring Web Flow controller). And after looking in their, it was immediately apparent that the flow controller was wrapped using the old style.
So actually what was happening was the controller was coming out of the included context already wrapped in a transactional proxy. The aop: stuff in the “parent” context was then wrapping it in another transaction.
By “fixing” the aop:pointcut I had ineffect disabled the aop:pointcut, hence there was only one transactional proxy..the one explicitly defined in the included flow.
The fix was easy when I understand the problem.
I managed to spend a good couple of hours identifying the problem and the “solution” not by understanding the problem, but understanding its behaviour. The “solution” was identified not because it fixed the problem, but because it appeared to work.
This is actually quite rare for me…I am usually so anal that I absolutely have to understand why it is breaking…it usually isn’t enough to simply know it works, I have to know why :)
Moral of the story…make sure you really understand the cause of the problem, and not just its characteristics…..and don’t believe everything I say about aop :)
July 04, 2006
Writing about web page http://www.amazon.com/gp/product/customer-reviews/159059584X/103-6827141-9792643
So the book I contributed to (I did the last two chapters on Spring Web Flow) seems to be doing well.
No idea about the number of sales (although I did receive my first commission cheque ;)), but all the reviews seem to like it.
Anyways, if you understand the title (Expert Spring MVC + Web Flow) then go and buy the book :) If you are really lucky and bring it to me in elab before the end of the week I might even sign it for you ;) :)