EL vs Dependency InjectionOne of the many useful utilities in Java EE is dependency injection - particularly for obtaining an EntityManager for your persistent classes. However, as I've alluded in previous posts, my preference is still for the plain old Servlet stack with JPA, JSF and EL dropped in as jar files. That means no dependency injection for me!
I am aware that there are existing inversion of control containers which might be able to solve this particular problem and which are certainly buzz-word compliant. Unfortunately, I couldn't really see that all the additional configuration was actually simplifying the job for me.
So, is there a another way?...
EL vs Dependency Injection
My alternative solution has been to go back to the traditional reference-by-name paradigm we all used with JNDI, except by replacing JNDI with EL. Using EL from Java allows me not only to 'inject' EntityManagers, but also any configuration variable or bean which can be accessed from the ELContext. When coupled with the pluggable EL resolver, its actually hard to think of use cases where I couldn't use EL.
Here is some sample code to resolve an EntityManager:
public List<Object> getObjects() {
EntityManager em = eval("${em}", EntityManager.class);
return em.createQuery("SELECT e FROM Entity e").getResultList();
}
In my code, I'm simply using a RequestFilter to insert the ${em} into the request scope, although you could equally use a custom ELResolver to resolve this variable. The eval() method is a static import which looks like this:
/**
* Shorthand for Application.evaluateExpressionGet(...) which
* automatically casts the result to expected type and uses the current
* FacesContext for evaluating the expression.
*
* @param expression the EL expression to evaluate
* @param clazz the expected resultant class
*/
public static <T extends Object> T eval(String expression,
Class<T> clazz) {
return (T) FacesContext.getCurrentInstance().getApplication().
evaluateExpressionGet(FacesContext.getCurrentInstance(),
expression, clazz);
}
There are also fewer limitations on where EL can be used compared to dependency injection. It can be used whenever an ELContext is available, and in a JSF application that is practically anywhere. I use EL for configuring beans which avoids the use of static variables that can break an application when a shared classloader is being used.
/** remove the file from the filesystem when deleting */
@PreRemove public void deleteFile() {
String dir = eval("${config['uploadsDir']}", String.class);
File file = new File(dir, id.toString());
file.delete();
}
Using EL also makes your code more readable, and your beans scope-independent. Here is a snippet of the first few lines of an ActionListener from some code which doesn't use EL:
/* initial values */
context = FacesContext.getCurrentInstance().getExternalContext();
item = (Content) context.getRequestMap().get("item");
site = (Site) context.getApplicationMap().get("site");
em = (EntityManager) context.getRequestMap().get("em");
and the equivalent using EL:
/* initial values */
item = eval("${item}", Content.class);
site = eval("${site}", Site.class);
em = eval("${em}", EntityManager.class);
Probably my favourite advantage of using EL is that it simplifies the problem of referencing items in an iterated context. For example, given the following template:
<h:dataTable value="${items}" var="${item}">
<h:column>
<h:commandButton action="delete" value="Delete this Item"/>
</h:column>
...
</h:dataTable>
You can resolve the selected item in your action simply by doing this:
Object item = eval("${item}");
There doesn't seem to be much opinion out on using EL from within Java. I've found it a really great way to make my code more readable and patterns more repeatable. Personally, I'd love to see it become a part of the language!
What do you think? I've given some of the advantages of EL, how about some disadvantages? Performance anybody? Type safety? Tell me why I shouldn't keep using this pattern.
Note: the eval() method shown above is available in the Furnace Webapp Framework.
About Roger Keays
|
Roger Keays is an artist, an engineer, and a student of life. He has no fixed address and has left footprints on 40-something different countries around the world. Roger is addicted to surfing. His other interests are music, psychology, languages, the proper use of semicolons, and finding good food.
|
nice one. thanx for sharing
Roger, If spring is too heavyweight for you and if you are looking only at DI, take a look at nanocontainer http://nanocontainer.codehaus.org/
I think you're muddling runtime configuration and startup configuration. DI (when using spring, etc) allows you specify all the dependencies statically in XML files or annotations.
In the desktop app example what you want is a component to determine it's own dependencies at runtime you'll need "something" that is able to determine the right EM to use... typically based on the business object type.
So indirectly you'll end up using service locator pattern when using DI. IMHO you can view DI as an extra layer in this use case so why even bother? The reason is relatively straightfoward, most of the time be it server side or client configuration most things are static. E.g. what datasources to use, configuration parameters, etc. So using DI solves this in a clean simple way. You can determine what happens without running any code and should be relatively clear.
For things that are loosely related, service locator works better. So using a combination of the two provides a far cleaner solution than assuming one is always better than the other. You shouldn't view the two ways as doing things as mutually exclusive. Using DI but looking things up at runtime (e.g. in spring getting a bean using the application) is basically using it as a service locator.
From past experience I've tend to use DI for virtually everything and for configuration that is user driven, etc. move it outside of DI and use service locator, etc.
Hi Tom,
That's an interesting use case, and a problem which also crops up in Java EE when you want to access several databases. A solution using EL/service location could be to give each em a different name. e.g. ${cmsEm} and ${statsEm}, or write a getter to return the required em conditionally: ${module.someEm}
I'm not sure how this might translate to your scenario, but if each frame requires an em, can you use a locator pattern to resolve the current frame and then fetch the em from it?
I'd be interested to know how/if you can solve this using dependency injection too... perhaps someone can comment.
Interesting to see how people keep focussing on JEE applications, and here I am thinking the desktop is supposed to be back ;-)
Anyhow, I wanted to point out an area where your EL solutions as limits: I had to write a EntityManager service locator for my desktop application, because all the existing solutions do not take multiple EMs into account. Usually in a desktop application with multiple frames, each frame must have its own EM. All existing injection or locator solutions are not able to handle this.
Thanks for those references Peter - it looks like the topic really has been covered pretty well before.
I can see there are some good arguments for both patterns. Service Location is working pretty well for me, but I'll keep reading about Spring. I have to admit that I've been deterred from Spring because it seems to have too many features that I don't need.
I'd probably agree that testing is easier with Dependency Injection for classes which can be tested outside of any container, but for context dependent classes such as JSF ActionListeners you generally need the whole environment anyway. Seam appears offer some improvements to this with its @In attribute.
Anyway, just some food for thought.
I can not see how moving back to a convoluted form of service location can be any good. Think about the advantages DI gives you in term of readability, maintenability and testability.
With your approach, each class must know the IDs of the resources it needs. Knowing the type should be enough, why adding more?
I reckon that to avoid typos, you will create some constant class containing all the valid resource IDs and all your class will use this God one.
And how do you test this? You need to create an EL context and stuff it with all required dependencies for a particular class? How do you maintain this list, knowing that your IDE or the compiler won't give you any help in figuring out what yout tested class needs (unlike DI that leverage regular code constructs).
> That means no dependency injection for me!
What about Spring?
Sorry: not convinced.
David
Your EL is just a form of service locator. And enough is writting about service locators vs dependency injection.
http://martinfowler.com/articles/injection.html
Personally I don't give much for service locators because you make assumptions about the environment. But a lot of people think it is a usable approach.
http://pveentjer.wordpress.com