Java Chatter and Random Nagging

Wednesday, January 30, 2008

Reduce your memory usage with Hibernate's evict

I was running low on memory when performing an operation for all Employee objects of my Company object. Since the operation performed changes on a big hashmap, deep inside my Employee object, I noticed that the operation on subsequent employees took more and more time, until the application finally ran out of memory.

I fixed this by fetching a hibernate iterator and evicting my Employee object when my operation was done.


Iterator userIterator = userRepository.getUserIterator(company);
while(userIterator.hasNext()){
   User user = userIterator.next();
   user.getEmployee().openYearForBookings(holidayYear);
   userRepository.flush();
   userRepository.evict(user);
}


Sorry for the flush, but when not flushing the session before the evict, I lost all changes made to the evicted object.

Tuesday, January 22, 2008

Ordering Spring Aspects

The order of application of Spring Aspects has kept me busy for a while. I think I finally figured them out, so let's share:

from the Spring manuals:
Spring AOP follows the same precedence rules as AspectJ to determine the order of advice execution. The highest precedence advice runs first "on the way in" (so given two pieces of before advice, the one with highest precedence runs first). "On the way out" from a join point, the highest precedence advice runs last (so given two pieces of after advice, the one with the highest precedence will run second).

When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is configured throught the Ordered interfacen, Order annotation or the configuration of order in xml. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.


As an example, using declarative transactions, suppose you have this:

<tx:annotation-driven transaction-manager="transactionManager" order="1"/>

I have a bean with transactional advice (propagation=REQUIRED)

<bean id="WorkYearApplicationService class="be.sunbeamsoftware.hammock.WorkYearApplicationService"/>

I have an aspect that is supposed to audit something in a database table, for a batch that will send e-mails later on.
The methods that need this are annotated with an @MailNotifiable.

<aop:pointcut id="supervisorActionPointCut"
expression="execution(* be.sunbeamsoftware.hammock.WorkYearApplicationService.*(..)) and @annotation(mailNotifiable) and args(employeeId, date, dayPart)" //>

<aop:aspect ref="actionAuditingAspect" order="3">
<aop:after-returning method="auditSupervisorActions"
pointcut-ref="supervisorActionPointCut"
arg-names="mailNotifiable, employeeId, date, dayPart" />
</aop:aspect>


This results in the following order of aspects :



Thus transactions are started first and committed last. This ordering is thanks to the lower order, thus higher precedence of the transaction aspect. It is also exactly what we want in this case.

Unfortunately (and the reason why this kept me busy), if you specify no order:

<tx:annotation-driven transaction-manager="transactionManager"/>

Then, by default the order of the declarative transactions is Integer.MAX_VALUE. This way, transactional advice is applied as the inner most aspect so our aspect for auditing something in the database after a call to WorkYearService, is not in the same transaction as the method of WorkYearService itself.

Explicitly setting the order property of the tx:annotation-driven will solve this. Just remember that the default transaction order in Spring is applying to the most inner level.

Sunday, January 20, 2008

Migrating to Spring 2.5

Just finished the migration from my pet project (which was Spring 2.0.6) to Spring 2.5.1
I must say, contrary to the claim on the SpringSource website, my migration did not went as smoothly as expected. I had more problems now then when migrating from Spring 1.0.2 to Spring 2 (of course my pet project wasn't that big back then).
Encountered problems and their fixes:
  1. Declarative transactions are not working (symptom "org.hibernate.HibernateException: createQuery is not valid without active transaction"). The fix is to remove the property <property name="current_session_context_class">thread</property>. Luckily I found this solution rather quickly.
  2. Problems with auto-wiring of Configurable beans. My solution was to switch from autowiring by type to by name. I filed an issue for this problem.
  3. <aop:spring-configured/> must be replaced by <context:spring-configured/> (symptom: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'aop:spring-configured')
    The declaration is as follows:

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">



That's it. If you want to excuse me now, I have to experiment with <context:component-scan>

Tuesday, January 15, 2008

Great Firefox plugin

Lately, I have been using a great download manager in firefox.
Really fast and the option to resume downloads is always great when surfing using an (in my case) unpredictable WLAN.
Just download :-) DownThemAll, here.