Article: Fetching strategy implementation in a J2EE application using AOP
A typical J2EE application using an O/R Mapping tool is faced with the task of fetching the required data using a minimal set of SQL queries, which is not always an easy task. By default the O/R Mapping tool loads data on demand unless otherwise instructed to. This behavior known as Lazy Loading ensures that dependents are only loaded as they are specifically requested and hence makes it possible to avoid unnecessary creation of objects. Because of the lazy loading, DB performance reduces when a large number of Select queries are executed, as all the required data for a business case are not fetched at once. This might prove a bottleneck for an application which needs to support a large number of requests.
In this article Manjunath R. Naganna introduces a strategy for overriding the default fetching pattern in the Repository/DAO class with a different fetching pattern based on the specific use case as defined with Aspect Oriented Programming. Aspect helps in deciding which fetching strategy needs to be used in a particular business use case. In this case, fetching strategy decision management is kept outside the lower level service or repository layer.
Read: Fetching strategy implementation in a J2EE application using AOP
The logic of deciding which query needs to be executed is a crosscutting concern that is retained in an Aspect. Aspect decides which fetching strategy needs to be injected in the repository before the service layer executes the API on the repository based on business use case. By this we can use the same service and repository layer APIs to satisfy different business use case requirements.
So what for is repository?
by
Sławomir Sobótka
There is also additional code that checks list details (size) but of course this clumsy design (returning from strategy list instead of object) is just to mask odd idea i guess.
Sounded good...
by
Branden Root
Is AOP used inappropriately here?
by
Wei Wei
Refactored Bloat
by
bruce b
- Code bloat - the only bloat is compared to the naive eager or lazy approaches. The use case specific code still exists in the AOP solution.
- Maintenance nightmare -Splitting the implementation of ORM fetching between inline code and aspect driven code is the real maintenance nightmare. The concerns implemented with AOP should be orthogonal to the use case driven service/repository code. This isn't the case here.
- Code duplication - The same duplication occurs in the sibling FetchingStrategy impl classes
Missing the role interface
by
Udi Dahan
www.udidahan.com/2007/04/23/fetching-strategy-d...
A year later is was rolled into the open source Rhino suite Ayende Rahien is leading as written about here:
ayende.com/Blog/archive/2008/03/27/Adaptive-Dom...
The main thing necessary for this to work is for there to be use-case-specific role interfaces for the domain which the service layer uses, rather than using the specific domain classes themselves.
This allows us to hook the fetching strategy on the use case, rather than on any implementation detail.
Hope that helps.
Re: Is AOP used inappropriately here?
by
Bill Poitras
Re: Missing the role interface
by
Manjunath Naganna
I have a question here regarding how do you hook-up the use-case specific role interface to the service layer at run-time?
As you see currently from my example code i am hooking it up using aspect. Can you give me a code snippet that explains it?
-Manjunath
Re: Refactored Bloat
by
Manjunath Naganna
If we start writing use case specific fetching api's we will have lot more code bloating then here since here aspect is handling of injecting the actual query that needs to be executed based on use case.
And if there is any common processing needs to be done after fetching domain object at repository level then this code needs to be present at all the use case specific fetching api's.
Maintenance Nightmare - Regarding this how come this becomes more maintenance nightmare than having multiple fetching use case specific api's at repository and lowel level service api's. You can check my sample code and evaluate it by adding new use case specific api needs changes at Business level service interface and aspect than changes to the lower level layers.
Code duplication - Here i don't see any code duplication since each FetchingStratergyImpl will have fine tuned queries specific to use case.
-Manjunath
Re: Missing the role interface
by
Udi Dahan
Employee e = ORM.Get<Employeee>(id);
e.Fire();
It calls:
IAmGoingToFireEmployee e = ORM.Get<IAmGoingToFireEmployee>(id);
e.Fire();
Then the ORM internally uses a service locator to find an implementation of IFetchingStrategy<IAmGoingToFireEmployee>. If found, the ORM uses it to find out which other objects to eagerly load.
Does that make sense?
Re: Missing the role interface
by
Manjunath Naganna
I still have a bit of confusion regarding missing role interface. I have gone through your talk Making Roles Explicit on InfoQ where you mention about role interface.
But as part of my example code i have Business Layer above Service layer to retrieve different set information of information to be displayed based on use case how do i notify my repository that i need to use particular fetching strategy. How do i pass this information from lower level service api's to repository.
For ex:-
Business Layer has a service which needs to run some Specification(Business Rule validation) on the retrieved entity
<Pseudo-Code>
BusinessLayer
void makeHimAValuableEmployee(int employeeId) {
Employee emp = lowerLevelServiceLayer.findEmplyee(employeeId);
ISpecification.isValuableEmployee(emp);
//Some more operations on domain object.
}
<Pseudo-Code>
Can you just go through my source code. Can your provide me a pseudo-code how would you have achieved it by making role explicit?
-Manjunath
</pseudo-code></pseudo-code>
Re: Missing the role interface
by
Udi Dahan
Apparently there are more architectural differences in our approaches than was originally visible. In your case, your business layer would call:
lowerLevelServiceLayer.MakeHimAValuableEmployee(employeeId);
And the lower level service would call:
IWantToMakeEmployeeValuable e = repository.Get<IWantToMakeEmployeeValuable>(employeeId);
e.MakeValuable();
Is that any clearer?
Re: Refactored Bloat
by
bruce b
As I'm writing this, I realize it's not a fetching strategy, so much as a fetching option. Options can usually be managed using low-tech means such as method parameters. The repository method could accept a parameter passed by the service method indicating which fetch mode to use when fetching an entity and its children. At this point mapping the option parameter to the HQL statement is a straightforward lookup that can be implemented in numerous ways. If a new use case arises requiring a new fetch mode, all you have to do is add a new name => HQL mapping to whatever lookup mechanism is in use.
If a need arises to execute common code after a fetch, then introducing AOP might be warranted, but only if it leads to less inline code boilerplate and duplication.
Educational Content
Writing Usable APIs in Practice
Giovanni Asproni May 19, 2013
Concurrency in Clojure
Stuart Halloway May 17, 2013




Hello stranger!
You need to Register an InfoQ account or Login to post comments. But there's so much more behind being registered.Get the most out of the InfoQ experience.
Tell us what you think