Igor's Blog

"... no matter what they tell you, it's always a people problem!"

Thursday, December 01, 2005

Dependency Injection OR Service Locator in Domain Objects
with Spring and Hibernate frameworks

The Problem

Currently, many java applications use Spring framework together with Hibernate. One of the advantages of that is that we can implement our domain and service objects as POJOs. Most of us are already convinced of all the benefits that such a type of architecture can have. In architecture like that, domain objects are managed by Hibernate and service objects are managed by Spring. Also, another advantage of using Spring specifically is Dependency Injections (DI) of services and resources.

The problem is how to retrieve/find/locate services or resources in domain objects since they are managed by Hibernate and not created through the bean factory of Spring framework?

Note: we should differentiate between domain, infrastructure and application services (Domain Driven Design book - http://domaindrivendesign.org/book). Using infrastructure or application services in domain objects is rather not appropriate. The problem I am most concerned with here is in the case when we need to invoke domain services inside of domain objects.

Can we avoid the problem?

Probably! The only way to avoid this problem is not to deal with any services/resources in domain objects. We can do this if we coordinate all domain-service cooperation from a service layer. In this case, we don’t need to bother with dependency injections, service locators, etc. This makes a lot of sense when we invoke services in an asynchronous fashion and especially in SOA /EAI types of architectures.

However, there are some disadvantages:
- We deprive ourselves from some of the benefits and power of OOP/OOD.
- Sometimes, service behavior fits very nicely into the domain model when we have a rich domain model rather than an anemic one http://www.martinfowler.com/bliki/AnemicDomainModel.html and http://wrschneider.blogspot.com/2005/01/avoiding-anemic-domain-models-with.html


Why do we get to the problem?

When I start a project I always try to have very well separated service layer from domain objects (usually enforced with different compilation modules for domain objects and service layer). However, in practice (at least until now) it always turns out that at some point I will need to use some kind of service or resource in my domain objects (the simplest example is Time Service. A Time Service is usually needed to give synchronized time when the application is deployed / clustered to more than one server. Also, if you need to play with the current time in your tests, this is a perfect solution. Usually when you deal with some kind of payment/billing systems, you will definitely need something like the above). There can be numerous examples of domain objects using some kind of service. Usually, most of the applications that have more complex domains use some kind of services or resources in domain objects.

Common solution to the problem

In the past when faced with this sort of situations we have usually used some form of Service Locator within domain objects in order to retrieve/locate services or resources.

However, these days we routinely use Dependency Injection with some form of Inversion of Control lightweight container (Spring for example) to wire up practically everything else in an app - and we would like to use a consistent approach if at all possible. Unfortunately, our domain objects are constructed by Hibernate and not Spring.

The most common solution (and the only one that I have seen in practice for now) is to use Spring framework DI to inject services into the service layer and to wire up practically everything else in your app beside domain objects. The domain objects, on the other side use Spring-based service locators to find further services/collaborators they need to do their job.

This could be workable approach since both the DI and service location mechanisms use the same underlying infrastructure (Spring bean factory), so they can share the same configuration files etc. Also, this common solution to the problem has been kind of described in the javadocs for Spring’s BeanFactoryBootstrap class with the statement “one singleton to rule them all”. In other words, allow singleton access to the bean factory or application context that holds all of the service layer objects.

However, as I stated above, I would like to use a consistent approach if at all possible for retrieving services. Not to mention all problems that comes with using Service Locator pattern. I guess using Service Locator with DI injections is a little better than the old style Service Locator but at the end, this is still a singleton. At least there is only ONE singleton in the entire app instead of one for each service object.

Example implementation of the common solution with Service Locator and DI

Before I continue further, let me show brief example of Service Locator using Spring DI. ServiceManager is an implementation of Service Locator pattern in this example. Its conceptual implementation comes from the statements “one singleton to rule them all” and “another level of indirection can solve any problem in OO design” (I don’t fully agree with this statements but it is hard to argue against them). The ServiceManager class has reference to all services that are needed by domain objects. All services are injected by Spring and ServiceManager is singleton instantiated by Spring creation factory on application startup. Something like this:




public class ServiceManager {
private static ServiceManager ourInstance;
private IReferenceDataService referenceDataService;
private ITimeService timeService;
…………
//other service declarations
public ServiceManager() {
ourInstance = this;
}
public static IReferenceDataService getReferenceDataService() {
return getInstance().referenceDataService;
}
//setter for Spring injection
public void setReferenceDataService(IReferenceDataService referenceDataService) {
this.referenceDataService = referenceDataService;
}
……
//other service setters/getters
protected static final ServiceManager getInstance() {
return ourInstance;
}
}




and the Spring mapping:



<bean id="serviceManager" class="service.impl.ServiceManager">
<property name="referenceDataService">
<ref local="referenceDataService"/>
</property>
<property name="timeService">
<ref local="timeService"/>
</property>
<property name="securityService">
<ref local="securityService"/>
</property>
.......
<!-- other service declarations -->
</bean>


Many people do consider that this is perfectly fine solution and there are not any problems with it. If you are some of these people, probably the rest would not be of such an interest for you.

Issues with using Service Locator with DI

I have encountered several problems with such an implementation:

1. We end up with more than one way to retrieve a service, mock or stub.
In some not domain objects, we get a service through Spring injections, in others we get it through static call to ServiceManager class. I feel this approach could bring a little confusion. This inconsistent approach of retrieving services could be a problem but I guess it could be argued that this is more of a question of “Enabling Attitude”: http://martinfowler.com/bliki/EnablingAttitude.html rather than a problem with using Service Locator together with DI. However, I found out that this could be an actual problem in many practical situations. At the end, remembering when to use what is still an indicator for a “code smell”.

2. Another major problem is that ServiceManager is very hard to be tested, mocked or stubbed.
The example implementation could enable us to mock specific services provided by the ServiceLocator through sub classing the ServiceLocator class and providing methods for overriding of a particular service.




public class ServiceManagerStub extends ServiceManager {
public static void overrideTimeService(ITimeService timeService) {
getInstance().setTimeService(timeService);
}
public static void overrideSecurityService(ISecurityService securityService) {
getInstance().setSecurityService(securityService);
}
.................
//other service overridings
}

Before we congratulate ourselves with successfully solving infrastructural issues that already has been solved by a DI lightweight container, which by the way we already use, I will try to point out some new problems that are introduced with this solutions.

The problem comes from the fact that we still use static class methods to retrieve services. So when we set up a mock service in a single test (ServiceManagerStub.overrideTimeService(getMockedTimeService()), we have to remember to reset it in the tearDown method. Again “we should remember”. Of course many times this is not done since running a single test class in an IDE would not cause a problem. Then we run all test from the build. At some point, we have a situation when a test which passes in an IDE fails in the build. The reason is that this test could be about 10-20 test classes after the one where we set up the mocked service. Some of the objects in this particular test use ServiceManager class to retrieve the same service that we mocked previously and we forget to reset it. Of course, we don’t have even a clue that a mocked service is invoked instead of a real one and we can not even think that 10-20 tests before our test, someone else have set a mocked implementation of the service we need.
Anyway, to make the story short, if somebody has used this kind of ServiceLocator, he/she should be familiar with this type of problems.

3. Issues with dynamic class loading.
Any implementation of ServiceLocator that uses calls to static class methods will have problem with releasing the static reference from the memory potentially with every dynamic class loading in a J2EE application server on hot redeploying. I have definitely had a lot of class loader issues with WebSphere 5. (Not with Jetty BTW)

4. One of the consequence of using ServiceLocator is that we hard-wire it.
This makes reusing of the domain objects that have hard coded dependence on the ServiceLocator often impossible due to dependencies on the particular application’s initialization and service infrastructure. In some of the cases, we were trying to reuse our domain objects in another application that will deal mostly with integration and will not use our current service infrastructure.

5. Another more general problems
- ServiceLocator cut against interfaces, by forcing you to know about specific class.
- Using ServiceLocator in the beginning could not be a big problem. However, it could turn out that ServiceLocator class is access simultaneously by many threats and it is a performance bottleneck. In cases like that we can't switch to using a pool of such objects for any of the callers that have hard-coded dependency on ServiceLocator class. Velocity and Struts frameworks, for example, have found that this initial assumption can end up being wrong and restrictive.

I guess that we can find a solution to all problems related to ServiceLocator and most of them depend on how it is implemented but should we have to deal with all these problems on the first place when we already have an implemented solution in form of DI.

Alternative Solutions


1. Passing a service as a parameter in the method call.
Passing a service as a parameter would remove the problem of dealing with dependency injection, service locators, etc and could be an elegant solution in some cases. However, in most of the situations, especially when we have rich domain object model this would not be a workable solution.

I suspect that following this approach for a more complicated domain would result in behavior moving itself inexorably out of the domain and into our service layer - leaving us with the ubiquitous anemic domain model. Usually, my goal is for the service layer to be very thin - in the majority of cases each service would just find the domain object(s) it needs and then call a method on the domain - all the behavior would be part of the domain.

Also, when the object behavior is not controlled by ‘Transactional Script” ( http://martinfowler.com/eaaCatalog/transactionScript.html ) but rather than the flow of control emerges from object behavior in rich domain model, we usually have situation when one object delegate to another object, which call a third object and so on. In situations like that, we would need to simply propagate the service in every method in the chain if this service happens to be needed in the last one, for example. Something like this anti-pattern description: http://www.picocontainer.org/Propagating+Dependency .

2. Using Hibernate to set the services/resources
This is probably the most compelling solutions since Hibernate anyway mange our domain objects. There are a couple of ways to do this. A god solution using Spring Sandbox classes is described here:
http://jroller.com/language/taranis/20050204?language=nl

Another solution is to use the currently available hibernate interceptors:
http://forum.springframework.org/archive/index.php/t-10547.html

Example of using AuditInterceptor to inject TimeService in domain objects can look like that:

<bean id="time-service" class="service.TimeService"/>
<bean id="audit-interceptor" class="persistence.AuditInterceptor">
<property name="timeService">
<ref bean="time-service"/>
</property>
</bean>

<bean id="hibernate-session-factory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="jdbc-data-source"/>
</property>
<property name="entityInterceptor">
<ref local=" audit-interceptor"/>
</property>
<property name="mappingResources">
<list>
<value>
/somepackage/SomeDomainObject.hbm.xml
</value>
... ... ... ... ...
</list>
</property>
</bean>

The problem with using hibernate interceptors is that they will be fired up only when the domain object is either saved or retrieved from the database. Of course by the point you need to save a domain objects, you don’t need the service any more. So, if you need to inject services or resources in objects that are only retrieved from a database (never create new objects and then persist them) this approach will be very elegant solution.

However, when we create a new domain object, this interceptor is not going to be fired and we won’t have the resources or services injected in the newly created object.
Needles to say, that this is the most common scenario in practice. We will definitely have many places where we need to create a new object, perform some business operation on it and then persist it to a database. In situation like that we need to have/inject/retrieve any services/resources before we push it to Hibernate through session.save() for example. As some of the people from Spring framework suggest (http://opensource2.atlassian.com/projects/spring/browse/SPR-431) we can use Spring via the ApplicationContext to create the domain object instance, populate it into our system via a lookup-method (to keep coupling low), and then push it into Hibernate.

3. Using Srping Bean factory to create your domain objects
In order to inject a service during creation of a domain object, we can use the Spring factories BeanNameAutoProxyCreator and ProxyFactoryBean:
http://www.springframework.org/docs/reference/aop.html#aop-pfb
And some opinion about the difference between ProxyFactoryBean and BeanNameAutoProxyCreator http://erik.jteam.nl/?p=8
As the name suggests (although they use AOP) they are still factories. This means that you can’t create an object just with “new”, but you have to use some kind of factory (in this case Spring bean factory). The other problem is that in order to use these Spring bean factories or Spring AOP for that matter, the lifecycle of a domain objects should be managed by the Spring container. If this is not a concern for you, then these bean factories together with Spring AOP will do the job.

So, if we don’t have problem with Spring container managing the life cycle of our domain objects, we have the ability to intercept the creation of a domain object despite the fact that the creation of this object is managed by Hibernate as well.

One problem with this approach is that we have to create all of our domain objects via
factory and our domain objects will become dependent on Spring framework. Since I usually try to keep all business logic in pure POJO, having domain objects dependent on Spring is somewhat problematic. Another problem will be unit testing our domain objects. We should initialize Spring application context before running any test. This can slow a great deal our unit tests and we can loose one of the biggest benefits of unit testing – very fast feedbacks. Not to mention that the task of refactoring the creation of all domain object from using “new” to using factory is almost impossible to be done in respects of agile iterative approach.

Also, many people don’t think that this is very efficient solution either. Some of the arguments are about performance issues of Spring AOP implementation: http://www.theserverside.com/news/thread.tss?thread_id=30681 .

So, if the biggest problem in this approach is the dependency on Spring bean factory, then we can work around it through using directly AOP in order to inject services in our domain objects.

4. Using AOP (AspectJ) to inject services/resources in domain objects during their instantiation.
Finding resources or services (Dependency Location/ Look Up) should not be a concern of a domain object to deal with. One of the basic principles of OOP is that one object should have only one responsibility and should do it well. Looking up for resources or services is clearly a cross-cutting problem. This should be a very good candidate for AOP. We can use AspectJ in order to inject services/resources in DO both when they are loaded and when new ones are constructed.

One issue with this approach is that the use of Spring DI for everything else and AspectJ for DO is not a consistent approach. Still, in my opinion it is better that a static call in DO to class method in Service Locator object. Also, you can integrate very easily AspectJ with Spring:
http://static.springframework.org/spring/docs/1.2.x/reference/aspectj.html#d0e4554

It looks like finally we have some feasible solution to the problem. Not so fast! According to my experience in dealing with customer enterprise applications and also according to many other opinions on AOP (one of them: http://beust.com/weblog/archives/000180.html) most of developer community (as well as IT as a whole) remains very skeptical about a direct adoption of AOP. The idea of using open source aspect oriented compiler could be very problematic on many enterprise projects.

As a whole, I think that this is the least popular solution and the hardest one to sell it out to other developers, architects and especially to customers.

5. Using Hibernate to set the services/resources when retrieving DO and setting them directly when a new DO is instantiated.
We can inject services/locators as with Hibernate interceptors when we retrieve objects from a database. When we create a new object, we can have the needed services/resources as a constructor parameter or just to set a property to the newly created DO.

Again we have at least two places that will deal with injecting services/resources – Hibernate interceptors as well as every place in the code where we create a new DO, which needs services. This probably will make us use a factory for creating DO, which brings us back to the solution with Spring bean factory managing our domain objects. Very informative discussion about this approach could be found here:
http://forum.springframework.org/showthread.php?t=12221

Conclusion

This is the first time I feel that there is some inconsistency of using Spring framework for DI. To me, all this seems to beg the question - If Spring framework doesn’t provide effective way for DI in the domain model - and we want the majority of behavior to be in our domain model – then how we have to deal with this problem?

Anyway I still think that Spring framework is a great framework. In my opinion using AOP directly with AspectJ is the best approach for DI in the domain model. However, since AOP is not even close to wide spread adoption, probably the alternative solution to AOP in java5 – annotations could have the potential to solve the problem in less powerful but still elegant way (http://weblogs.java.net/blog/crazybob/archive/2004/09/where_is_aop.html).

What approach are you using in your projects?
|| Igor, Thursday, December 01, 2005

25 Comments:

Good stuff. I've been thinking about this sort of thing ever since I started using Spring but I don't have a clear resolution yet. I'm inclined to use Service Locators or parameters but I haven't really pushed this far enough to have a really strong opinion on this yet.
Blogger Jason Yip, at December 02, 2005 2:30 AM  
For example, having common Root superclass (referring to Fowler's pattern...) which performs autowiring in its constructor.

However, for this thing to work properly, you need some dirty things, e.g. static fields referring to Spring bean factory. So it would be somewhat similar to "ServiceManager" but having all dirty things hidden inside superclass.

Also, some bytecode instrumentation for constructors comes in mind...
Anonymous snekoval, at December 07, 2005 6:54 AM  
thank you for sharing this informative blog.. this blog really helpful for everyone.. explanation are clear so easy to understand...

core java training institute in chennai | core java training topics | core java training in chennai | core java training online
Blogger Rajapriya R, at March 14, 2017 11:15 PM  
ok hay đấy

Phối chó bull pháp

Phối giống chó Corgi

Phối chó Pug

Dịch vụ phối giống chó Poodle

Dịch vụ phối giống chó bull pháp
Blogger Chiến SEOCAM, at June 07, 2019 3:43 AM  
ok thank

giảo cổ lam giảm cân

giảo cổ lam giảm béo

giảo cổ lam giá bao nhiêu

giảo cổ lam ở đâu tốt nhất
Blogger Chiến SEOCAM, at June 08, 2019 4:15 AM  
Lâu rồi tôi mới thấy một bài viết hay như vậy

máy khuếch tán tinh dầu

máy khuếch tán tinh dầu giá rẻ

máy phun tinh dầu

máy khuếch tán tinh dầu tphcm

máy phun sương tinh dầu
Blogger Chiến SEOCAM, at June 09, 2019 9:58 PM  
ok

giảo cổ lam 5 lá

giảo cổ lam 7 lá

giảo cổ lam khô

giảo cổ lam 9 lá
Blogger Chiến SEOCAM, at June 11, 2019 4:37 AM  
Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing clearly, but it’s no need to do it, because you have explained the concepts very well. It was crystal clear, keep sharing..
Java Training in Chennai
Java Training in Coimbatore
Java Training in Bangalore
Blogger Madhu Balan, at August 22, 2019 9:45 AM  
Nice Blog....thanks for sharing..
Spring Training in Chennai
Spring framework Training in Chennai
Spring course in Chennai
Spring Training in Velachery
Spring Training in Tambaram
Hibernate Training in Chennai
javascript training in chennai
QTP Training in Chennai
Mobile Testing Training in Chennai
SAS Training in Chennai
Blogger roshnidevan, at August 23, 2019 4:17 AM  
Awesome Blog!!! Thanks for it, it is more useful for us.
IOS Training in Chennai
ios training institute in chennai
iOS Training
Best ios Training institutes in Chennai
IOS Training in Tambaram
IOS training in Guindy
Python Training in Chennai
Big data training in chennai
SEO training in chennai
JAVA Training in Chennai
Blogger Riya Raj, at August 23, 2019 4:29 AM  
This was a great blog. Really worth reading it. Thanks for spending time to share this content with us.
IELTS Coaching in Tambaram
IELTS Coaching in T Nagar
IELTS Coaching in Velachery
Spoken English Classes in Chennai
Spoken English in Chennai
IELTS Coaching in Chennai
IELTS Chennai
English Speaking Classes in Mumbai
Spoken English Classes in Mumbai
IELTS Classes in Mumbai
Blogger Anbarasan14, at August 26, 2019 7:26 AM  
This is an awesome post.Really very informative and creative contents.
IELTS Coaching in Chennai
Best IELTS Coaching in Chennai
French Language Classes in Chennai
pearson vue exam centers in chennai
Informatica MDM Training in Chennai
Hadoop Admin Training in Chennai
IELTS Coaching in Tambaram
IELTS Coaching in Anna Nagar
Blogger rutmanaish, at August 27, 2019 7:31 AM  
Excellent post, it will be definitely helpful for many people. Keep posting more like this.
Ethical Hacking course in Chennai
Ethical Hacking Training Institute in Chennai
Hacking course in Chennai
ccna Training in Chennai
Salesforce course in Chennai
PHP Training in Chennai
Tally course in Chennai
Ethical Hacking course in OMR
Ethical Hacking course in Anna Nagar
Ethical Hacking course in Vadapalani
Blogger Manthra, at August 28, 2019 1:47 AM  
valuable blog,Informative content...thanks for sharing, Waiting for the next update...
clinical sas training in chennai
clinical sas course
clinical sas Training in Porur
clinical sas Training in Velachery
clinical sas Training in Tambaram
SAS Training in Chennai
Spring Training in Chennai
LoadRunner Training in Chennai
QTP Training in Chennai
javascript training in chennai
Blogger rinjuesther, at August 28, 2019 4:21 AM  
Get inspired by your blog. Keep doing like this....
Tally Course in Chennai
Tally training in coimbatore
Tally course in madurai
Tally Classes in Chennai
tally classes in coimbatore
tally coaching centre in coimbatore
Selenium Training in Chennai
Blogger subhashini, at August 31, 2019 5:13 AM  
Valuable one...thanks for sharing...
QTP Training in Chennai
QTP Training Institutes in Chennai
best qtp training institutes in chennai
QTP Training in Porur
QTP Training in T Nagar
LoadRunner Training in Chennai
Html5 Training in Chennai
clinical sas training in chennai
Spring Training in Chennai
Photoshop Classes in Chennai
Blogger SHASHI, at September 04, 2019 5:07 AM  
The blog which you have posted is more impressive... thanks for sharing with us...
Selenium Training in Chennai
best selenium training in chennai
selenium classes in chennai
best selenium training in chennai
Selenium Training in Tnagar
Selenium training in Thiruvanmiyur
Big data training in chennai
Software testing training in chennai
Android Training in Chennai
JAVA Training in Chennai
Blogger Riya Raj, at September 05, 2019 1:35 AM  
This was an excellent post and very good information provided, Thanks for sharing.
Python Training in Chennai
Python Course in Bangalore
Python Training in Coimbatore
Python course in Chennai
Big Data Training in Bangalore
dot net training institutes in bangalore
Best Python Training in Chennai
Python Classes in Chennai
Blogger sasi, at September 06, 2019 2:22 AM  
Rice Bags Manufacturers
Pouch Manufacturers
wall putty bag manufacturers
fertilizer bag manufacturers
seed bag manufacturers
gusseted bag manufacturers
bopp laminated bags manufacturer
Lyrics with music
Blogger sachin sinhmar, at September 23, 2019 1:22 AM  
we have provide the best ppc service.
ppc company in gurgaon
website designing company in Gurgaon
PPC company in Noida
seo company in gurgaon
PPC company in Mumbai
PPC company in Chandigarh
Digital Marketing Company
Blogger sachin sinhmar, at September 23, 2019 1:22 AM  
we have provide the best fridge repair service.
fridge repair in faridabad
Videocon Fridge Repair in Faridabad
Whirlpool Fridge Repair in Faridabad
Hitachi Fridge Repair In Faridabad
Washing Machine Repair in Noida
godrej washing machine repair in noida
whirlpool Washing Machine Repair in Noida
IFB washing Machine Repair in Noida
LG Washing Machine Repair in Noida
Blogger sachin sinhmar, at September 23, 2019 1:22 AM  
iso certification in noida
iso certification in delhi
ce certification in delhi
iso 14001 certification in delhi
iso 22000 certification in delhi
iso consultants in noida
Blogger sachin sinhmar, at September 23, 2019 1:22 AM  
iso registration in delhi
iso 22000 certification cost
ISO 9001 Certification in Noida
Blogger sachin sinhmar, at September 23, 2019 1:22 AM  
Excellent and very cool idea and great content of different kinds of the valuable information's.
Hadoop Admin Training in Chennai
Hadoop Administration Training in Chennai
German Classes in Chennai
IELTS Coaching in Chennai
Japanese Classes in Chennai
Spoken English Classes in Chennai
spanish classes in chennai
content writing course in chennai
Hadoop Admin Training in OMR
Hadoop Admin Training in Porur
Blogger harish kalyan, at September 24, 2019 4:21 AM  
Thanks for sharing such a great blog Keep posting.
Loadrunner Training in Delhi
Blogger manisha, at October 14, 2019 4:05 AM  

Add a comment