Showing posts with label aop. Show all posts
Showing posts with label aop. Show all posts

Friday, July 10, 2009

Hibernate session issue during Spring tests

I reckon this is something good to share as it took me a few hours to get the problem resolved.

We are using SpringJUnit4ClassRunner for our DAO tests, the tests passed when they were run in Eclipse, but not in Maven. One of the test classes failed with HibernateSystemException:

org.springframework.orm.hibernate3.HibernateSystemException: Illegal attempt to associate a collection with two open sessions; nested exception is org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

Google search gave me some clue about the problem had something to do with cascading style, transaction, and duplication but they didn't lead me anywhere. I broke at AbstractPersistentCollection.setCurrentSession to find out that the session/session factory (DAOs are instances of HibernateDaoSupport) assigned to one of the DAOs was different.

A second look at the test class which had:
@Autowired
BillingInvoiceDao $;
BillingOrderDao orderDao;
BillingItemDao itemDao;
MembershipDao membershipDao;

@Override
protected void setUpDataAccessObjects() {
membershipDao = DataAccessObjectHelper.getDataAccessObject(MembershipDao.class);
itemDao = DataAccessObjectHelper.getDataAccessObject(BillingItemDao.class);
orderDao = DataAccessObjectHelper.getDataAccessObject(BillingOrderDao.class);
}

I found out that BillingInvoiceDao was not a proxy instance but the other DAOs are. The log may explain something:
[07-11 09:19:30] DEBUG AutowiredAnnotationBeanPostProcessor [main]: Autowiring by type from bean name 'itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest' to bean named 'billingInvoiceDao'
[07-11 09:19:30] DEBUG DefaultListableBeanFactory [main]: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
[07-11 09:19:30] DEBUG DefaultListableBeanFactory [main]: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
[07-11 09:19:30] DEBUG AnnotationTransactionAttributeSource [main]: Adding transactional method [testCrud] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
[07-11 09:19:30] DEBUG AnnotationAwareAspectJAutoProxyCreator [main]: Creating implicit proxy for bean 'itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest' with 0 common interceptors and 1 specific interceptors
[07-11 09:19:30] DEBUG JdkDynamicAopProxy [main]: Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest@17afcff]
[07-11 09:19:30] DEBUG AnnotationTransactionAttributeSource [main]: Adding transactional method [testCrud] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
[07-11 09:19:30] DEBUG TransactionalTestExecutionListener [main]: Explicit transaction definition [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] found for test context [[TestContext@134b58c testClass = HibernateBillingInvoiceDaoTest, locations = array['classpath:spring/dataAccessTestContext.xml', 'classpath:spring/dataAccessTestContext.billing.xml'], testInstance = itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest@17afcff, testMethod = testCrud@HibernateBillingInvoiceDaoTest, testException = [null]]]
[07-11 09:19:30] DEBUG TransactionalTestExecutionListener [main]: Retrieved @TransactionConfiguration [@org.springframework.test.context.transaction.TransactionConfiguration(defaultRollback=true, transactionManager=mainTxManager)] for test class [class itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest]
[07-11 09:19:30] DEBUG TransactionalTestExecutionListener [main]: Retrieved TransactionConfigurationAttributes [[TransactionConfigurationAttributes@ddc524 transactionManagerName = 'mainTxManager', defaultRollback = true]] for class [class itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest]
[07-11 09:19:30] DEBUG DefaultListableBeanFactory [main]: Returning cached instance of singleton bean 'mainTxManager'
[07-11 09:19:30] DEBUG TransactionalTestExecutionListener [main]: Executing @BeforeTransaction method [public void net.aflexi.cdn.core.test.AbstractDaoTest.setUpBeforeTransaction() throws java.lang.Exception] for test context [[TestContext@134b58c testClass = HibernateBillingInvoiceDaoTest, locations = array['classpath:spring/dataAccessTestContext.xml', 'classpath:spring/dataAccessTestContext.billing.xml'], testInstance = itest.net.aflexi.cdn.billing.HibernateBillingInvoiceDaoTest@17afcff, testMethod = testCrud@HibernateBillingInvoiceDaoTest, testException = [null]]]
[07-11 09:19:30] DEBUG DefaultListableBeanFactory [main]: Returning cached instance of singleton bean 'membershipDao'

That transaction propagation happened after autowiring of beans. The fix of my problem is to @Autowired all DAOs (so that they are consistent) or assign them via the DataAccessObjectHelper as shown in the snippet.

Hope this helps.

Tuesday, September 16, 2008

Seperating visual effects from HTML using jQuery

I remember reading Matt Ryall's blog on 10 things every web developer should know a while back and I would like to highlight the clean code suggestion made there.

I'm migrating the existing Aflexi website to Drupal and at one point I came across an existing code which.. is not too ugly but hard to be integrated into its Menu feature. The code has a few divs that jQuery uses to create sliding effects, I could actually put them into the template page.tpl.php but using jQuery to inject them at the end of page is certainly a better practice.

So, in my template.php, I have:

$js[] =<<JAVASCRIPT
$('#nav').append('lots.of.divs'); // Here's the injection
$(document).ready(function() {
UiHelper.registerSlider('a.menu-1-1-2', '#sliderWso', '#pointerWso', 300);
...
});
JAVASCRIPT;
drupal_add_js(join("\n",$js), 'inline');


By the way, I make the divs a one liner using:

echo 'paste your html' | tr -d '\n'

Then, talking about injection, this is brought into my attention as well - jQuery-AOP.

- yc

Friday, October 19, 2007

Every character counts

I have been fixing up some funny Spring/Acegi<->LDAP issue in the past two days. What I was trying to achieve is some AOP using BeanNameAutoProxyCreator to intercept invocations to methods of a particular interface/class, so that it authenticates against an LDAP repository and validate if a user has one of the specified roles. Something wasn't really working at the DefaultLdapAuthoritiesPopulator -- the authorities/roles list was empty.

Now, it's solved, yes it is.. with shame.

I turned on an even detailed debug logging and that's when I started to realized my.. stupidity ;-)

conn=2 op=1 SRCH base="ou=groups,dc=my,dc=com,dc=customware" scope=2 deref=3

filter="(member=uid=clim,ou=people,dc=my,dc=com,dc=customware)"
conn=2 op=1 SRCH attr=cn
bdb_idl_fetch_key: [01872a84]
bdb_idl_fetch_key: @ou=groups,dc=my,dc=com,dc=customware
<= bdb_equality_candidates: (member) index_param failed (18) => access_allowed: search access to "ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted => access_allowed: search access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted dnMatch 0 "uid=clim,ou=people,dc=my,dc=com,dc=customware" "uid=clim,ou=people,dc=my,dc=com,dc=customware" => access_allowed: read access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "entry" requested
<= root access granted => access_allowed: read access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "cn" requested
<= root access granted => access_allowed: search access to "cn=managers,ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted dnMatch -1 "uid=clim,cn=people,dc=my,dc=com,dc=customware" "uid=clim,ou=people,dc=my,dc=com,dc=customware" send_ldap_result: err=0 matched="" text="" conn=2 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=

Did you see that? I will do it again:

dnMatch 0
"uid=clim,ou=people,dc=my,dc=com,dc=customware"
"uid=clim,ou=people,dc=my,dc=com,dc=customware"
...
dnMatch -1
"uid=clim,cn=people,dc=my,dc=com,dc=customware"
"uid=clim,ou=people,dc=my,dc=com,dc=customware"

cn=people and ou=people?!

dn: ou=people,dc=my,dc=com,dc=customware
...

dn: cn=managers,ou=groups,dc=my,dc=com,dc=customware
member: uid=clim,cn=people,dc=my,dc=com,dc=customware
...

dn: uid=clim,ou=people,dc=my,dc=com,dc=customware
...

WTF! Worse than failure hey! LDAP did not fail me at the time I was importing from the LDIF with invalid member attribute value. I could have saved a few hours to do something.. more significant than sitting in front of my Eclipse to figure out why wasn't DirContext.search() returning any results. In fact, I have learned a very good lesson.

- yc, rantinggggggggggg!

Sunday, June 3, 2007

Separation of Concerns

Aspect Oriented Programming (AOP), something which you might be familiar with if you are a Spring/Hibernate lover. It is definitely something new to me.

I spent some of my weekends looking for AOP articles and books. Graham O'Regan's article demonstrates how powerful AOP is and how it can be easily done using AspectWerkz. Naveen Balani's article shows you how Spring does it so that you do not need to add similar lines of code to obtain a Hibernate session to begin a transaction. Spring also

Just as you might not have an idea what AOP is:

It is a solution to the problem of creating clean and well-encapsulated without extraneous functionality.

Explained by Joseph and Nicholas in the book "Mastering AspectJ – Aspect-Oriented Programming in Java". You can find a sample chapter of the book from this link. The introduction explains how Object Oriented programming (OOP) came into play when procedural and functional programming turned ugly and how AOP fills in the blanks of OOP.

Some keywords of AOP are: Advice, Aspect, Cross-cutting concerns, Join points, Point-cut

I am not too sure how AOP can be applied to complicated frameworks such as webMethods. I certainly not a big fan of writing codes to deal with the core API to open and close connection for every transaction that I make. I got around this in my earliest webMethods related project by writing some Plain Old Java Objects (POJOs), Data Access Objects (DAOs) and Data Transfer Objects (DTOs). But they still took me quite some time and I would not know how complicated they could be if someone raised some new concerns.

I am new to Mule but I certainly love how lightweight it is and its support for regular POJOs and Spring embedment.

- yc, aspected