Hi Allen

Thanks a lot for the feedback!
Allow me some more comments and attempts at being a little clearer :-)

> I took a bit of a look at it and it looks fine, thanks for providing
> this example.  It's a little hard to compare since it doesn't actually
> run properly, but I was able to get the basic idea.

Sorry about that. I jumped in the middle of some major code changes for 4.0 so I had troubles getting something stable to run, but yup, that wasn't really the goal.

> As for my general
> thoughts on Spring vs. Guice ...
>
> http://code.google.com/p/google-guice/wiki/SpringComparison
>
> Guice seems to be the smaller, lighter, and more focused DI option and I
> strongly prefer their Module approach and their use of annotations over
> config files.  The performance stuff sounds interesting as well although
> I don't consider it a huge issue.  The benefit of Spring of course is
> that it offers more options in terms of non-DI stuff such as the mail
> sender and thread executor stuff.
>

Yes, I've tried to show in my sample, there's a lot more in Spring than DI.
Generally speaking and performance-wise, the only hit with Spring is at application startup, so it's of very little concern in a web app world, or systems such as Roller. Actually, I've heard a lot of claims about Spring slowliness that have been proven wrong with my past experiences, and honestly, the benchmark code (http://google-guice.googlecode.com/svn/trunk/test/com/google/inject/PerformanceComparison.java) looks a little silly to me: it goes down in the guts of the Spring API that no-one ever touches to benchmark some accesses or construction patterns that the Spring factories implementation classes optimize, bypassing that totally, which is the whole point of Spring providing such a vast API and set of objects. There are many areas where performance actually improves by using Spring since you can for example lazy-load any bean you choose and don't have to manage any synchronized access (or very few on implementation specific classes) or caching-related things in the code.

I don't have exact figures for Roller but I noticed a 12s delay vs 8s in Tomcat context loading using Spring. Past that point, without using lazy-loading, I couldn't see any difference, even when adding interceptors to log DAO or business methods. You can "feel" beans being lazy-loaded (1/2s at worse?) when switching that on but again, that doesn't matter since it's done once.


> * I definitely hate all the config files.  I don't know if you separated
> them for example purposes, but you have like 7 config files and IMO that
> is way confusing.  I would really only consider Spring if this was all
> merged into a single file or at least just one or two files.


The mail and database provider are in separated files to make sure that modules that would only use the mail provider or database provider don't load any unwanted/unnecessary bean by using only one file (a common mistake with using Spring without lazy-loading, which I did when I started playing with the Roller code for mail util).

Now for all the rest (all the XML for the implementation beans), it really is just me and my coding style (I'm a "500 lines of functional code in a single java class is probably more than you'll ever need" kind of refactoring ayatohlah). It's very easy to have only 3 Spring files, or even only 1. However, separating the business impl also helped me switch from one back-end to another in one line while testing/experimenting.

Using config files is indeed a different approach than using annotations. I am personnally a fan of XML and I much prefer configuration files to instrumenting code with annotations or other comment tags that are tool-specific, requiring for example a build cycle to fix a setting (such as the hibernate tags). I also tend to dislike binding business objects to anything else than the API they belong to. However, that's a very philosophical debate that we'll keep for another time.


> * The property file injection thing is interesting and seems powerful,
> but i'm worried it's not entirely appropriate for us.  for one, it means
> that there are now 2 ways to get properties out of those config files
> (via Spring and RollerConfig) and that complicates things.  second, lots
> of the the stuff in those configs doesn't apply to the backend, so it
> seems weird to support duplicated config mechanisms for the backend
> wired by Spring and for the rest of the code.  In your example you
> didn't include the fact that a 3rd way to specify roller properties is
> by supplying a path to a file via a jvm option, so you would need to
> support that as well.

As I mentionned in my previous mail, I didn't went as far as I wanted to with property files. Of course, RollerConfig and RollerRuntimeConfig should use the same mechanism and sources, which can easily be done by modifying their implementation. Ideally, there should be few to no references to static methods in a code that is using DI as its core (each property a class needs should be injected, so as to help testing and re-use) but we can get around easily with that since RollerConfig is pretty much everywhere. I didn't provided a RollerConfig implementation that reads its configuration from Spring for lack of time, and fear to break too much stuff in the same batch.


> In your example you
> didn't include the fact that a 3rd way to specify roller properties is
> by supplying a path to a file via a jvm option, so you would need to
> support that as well.

I wasn't aware of that option, but that should be a breeze to add. That won't probably even require writing any code.

> * The way you did the persistence stuff is probably what i liked least.
>  I am not in favor of wiring up our backend in a Spring specific way
> using things like Springs HibernateUtils, etc.  I already think that ORM
> solutions provide enough of a challenge in terms of figuring out exactly
> how a call to save an object turns into actual jdbc actions and tracing
> that process becomes much more complicated when you mix in yet another
> dependency like Spring.  So I am not a fan of introducing Spring in this
> area and what we have now works fine so there is no reason to change it.
>  All that being said, this stuff has nothing to do with using Spring DI
> for the backend and is not required as far as I know so it's just
> something I would cut out.

Indeed, there is no reason to change the existing and the "hibernate2" package is a scary, ugly and bad attempt at showing how transaction can be moved to yet-more-XML-headaches and replace home-grown "strategies".

Ideally, it is best to use Spring's HibernateCallback(s) and HibernateTemplate, which is one area where you want to tie an implementation layer with Spring. But with those, you usually never have to manage any transaction aspect, unless you do very complicated and/or unlawful things with your SQL/Hibernate code, or need to support transactions other multiple datasources. It also allows for using JTA by just switching it on.
The business impl layer of this project
http://denis.balazuc.net/roller/blug-project-demo.zip
is probably a much better example of a simple DAO layer using Spring with Hibernate.

Basically, HibernateXXXImpl (or HibernateRollerImpl - see below) can be taken as is, have its strategy configured and injected through Spring, and off we go.


> * You suggested getting rid of the XXXRollerImpl classes and just using
> a generic RollerImpl class but that sounds like a bad idea in my mind.
> The purpose of having those classes is to force a persistence strategy
> as a whole meaning that a JPARollerImpl should only allow injection of
> JPAXXXManagerImpl classes.  From an api point of view it would be very
> silly to be mixing JPA and Hibernate code together at runtime.

You could go either or both ways actually.
Injecting a XXXRollerImpl in RollerFactory, or get rid all along of the XXXRollerImpl really is a design-decision. My only reason was to remove classes that do some wiring by code, managing their own singletons to show how it gets simplified. It surely makes little sense in the existing implementation. However, using Spring, it's a matter of defining a "prototype" (or "abstract" or "template") bean and moving configuration around, as long as you have the proper setters and getters.


> Like the
> last point, I think this is not something that really has a bearing on
> whether or not Spring DI could be used, but it's something that I am not
> a fan of in your particular design.  Also related to this one is that I
> am 100% against allowing for public setter methods in the Roller
> interface or it's implementations.  I mentioned this before, but the
> Roller instance should be immutable as far as the api goes and I think
> we need to enforce that when we do this DI work.
>

I could not agree more that setters have nothing to do in the Roller interface. However, If you're using setter injection, you need public setter (getters aren't necessary if not part of the implemented interface) in interface implementors. I am usually against public setters when it's not needed, but once you have DI in mind while designing/coding, there's rarely any misuse of it. You can opt for constructor injection, but unless the whole design is 100% interface-driven, it makes it harder to integrate interceptors, use dynamic proxies or reflection without a default constructor.

When I started working using DI, having public setters and getters used to itch me a lot (maybe less than protected member variables though), but since the "javabean-like" approach gets on everything, from Struts action forms to Spring beans, it's now became the usual pattern and at the end of the day is much cleaner than using protected members which access can't be traced to avoid getters/setters (even protected), and allows for a lot more fun such as mocks/stubs/etc.

> * The thread manager stuff is probably the most interesting piece in my
> mind and I wouldn't mind making use of Spring's built-in executor
> service stuff.  The problem though is that we don't really have much
> need to do this 'cuz our code is fine as it is, and the other problem is
> that translating our config file properties into Spring has proven
> challenging with the Acegi stuff and I am hesitant to try.

The ExecutorService is actually a java.util.concurrent implementation that got switched in Roller between two updates I did of the code IIRC. All I did is add a constructor to inject the service, as I did for all other XXXimpl, comment out my current Spring conf, switch it to injecting an ExecutorService using the parameters I gathered - that's all....Yup, that easy - and that was fun to do! :-)

It's actually a good example where Spring can really make a difference with its possibilites. You can inject anything from a flat static implementation of an interface, to an EJB, and this totally transparently at a switch of a config. With Spring's use of interceptors and dynamic proxies, you can go extremely far. I'm currently working on a well-known brand of J2EE 1.4 app servers IRL and with current threadmanager and scheduling implementation, I am not sure I would not get barked at and asked to use a WorkManager if I were to run Roller tasks on them. Being able to not touch the Roller code (maybe provide my own external package) and change one bean using a config file to make use of those server's built-in TaskScheduler(s) would be a very good thing.


Aside from the rich set of services that Spring offers, one of my main argument in favor of Spring for Roller is actually that it's already used in Roller with Acegi, which makes the config changes in the webapps and build files quite minimal. Also Struts/Struts2 modules already could benefit from it: actions that want mail senders, or filters, or renderers, all this may be injected through Spring extremely easily with the Struts plugin. I was actually surprised that it wasn't already that way and that they were still hard-wired dependencies on various services.

As for translating configuration files, I'm looking for something I could help on, show me where to look ;-) It is true that the learning curve with the Spring config is steep at first but after the getting-used-to phase, it's easy to navigate between the Spring API and the XML to change pretty much any aspect of an application at a glance.


> So overall my basic feeling is that Guice provides the nicer option
> specifically for DI and I love that it's all done via java code and
> annotations and that the way you define Modules provides some compile
> time checking.  Spring would work fine for DI, but I am still just luke
> warm on the config file wiring, so if I was making a decision now I
> would go with Guice.
>

As I mentionned earlier, I much prefer configuration files to instrumenting code with annotations but it all boils down to design decisions. Spring makes sense since it's already in Roller and allows for all those neat services and helpers that it comes with on top of the DI way that Roller is taking. It's worth the XML headaches IMO (I can't legally ship aspirin from here...). In the end, a good Spring deployement should hide the complexity of its configuration to end-users or users of the API but may go as far as one wants in decoupling code.

If you want more Spring magic to be shown (I haven't covered Struts2 yet!) or someone to do any config macarena you hate, I'd be happy to do more. If you give the go on Guice I'll just read more on and get my hands deeper on it, but in both cases I'd love to help.

Thanks again for the great feedback.

Denis Balazuc
"A good Spring implementation is indistinguishable from magic."
No...Wait...That doesn't sound right...


Allen Gilliland wrote:
I took a bit of a look at it and it looks fine, thanks for providing this example. It's a little hard to compare since it doesn't actually run properly, but I was able to get the basic idea. As for my general thoughts on Spring vs. Guice ...

From what I have seen from Spring and Guice so far I would basically agree with what this article says ...

http://code.google.com/p/google-guice/wiki/SpringComparison

Guice seems to be the smaller, lighter, and more focused DI option and I strongly prefer their Module approach and their use of annotations over config files. The performance stuff sounds interesting as well although I don't consider it a huge issue. The benefit of Spring of course is that it offers more options in terms of non-DI stuff such as the mail sender and thread executor stuff.

As for some of my thoughts on what I looked at in your code ...

* I definitely hate all the config files. I don't know if you separated them for example purposes, but you have like 7 config files and IMO that is way confusing. I would really only consider Spring if this was all merged into a single file or at least just one or two files.

* The way you build and configure the mail and db providers is interesting and could be useful, but I don't think it's a significant improvement over what we already have.

* The property file injection thing is interesting and seems powerful, but i'm worried it's not entirely appropriate for us. for one, it means that there are now 2 ways to get properties out of those config files (via Spring and RollerConfig) and that complicates things. second, lots of the the stuff in those configs doesn't apply to the backend, so it seems weird to support duplicated config mechanisms for the backend wired by Spring and for the rest of the code. In your example you didn't include the fact that a 3rd way to specify roller properties is by supplying a path to a file via a jvm option, so you would need to support that as well.

* The way you did the persistence stuff is probably what i liked least. I am not in favor of wiring up our backend in a Spring specific way using things like Springs HibernateUtils, etc. I already think that ORM solutions provide enough of a challenge in terms of figuring out exactly how a call to save an object turns into actual jdbc actions and tracing that process becomes much more complicated when you mix in yet another dependency like Spring. So I am not a fan of introducing Spring in this area and what we have now works fine so there is no reason to change it. All that being said, this stuff has nothing to do with using Spring DI for the backend and is not required as far as I know so it's just something I would cut out.

* You suggested getting rid of the XXXRollerImpl classes and just using a generic RollerImpl class but that sounds like a bad idea in my mind. The purpose of having those classes is to force a persistence strategy as a whole meaning that a JPARollerImpl should only allow injection of JPAXXXManagerImpl classes. From an api point of view it would be very silly to be mixing JPA and Hibernate code together at runtime. Like the last point, I think this is not something that really has a bearing on whether or not Spring DI could be used, but it's something that I am not a fan of in your particular design. Also related to this one is that I am 100% against allowing for public setter methods in the Roller interface or it's implementations. I mentioned this before, but the Roller instance should be immutable as far as the api goes and I think we need to enforce that when we do this DI work.

* The thread manager stuff is probably the most interesting piece in my mind and I wouldn't mind making use of Spring's built-in executor service stuff. The problem though is that we don't really have much need to do this 'cuz our code is fine as it is, and the other problem is that translating our config file properties into Spring has proven challenging with the Acegi stuff and I am hesitant to try.


So overall my basic feeling is that Guice provides the nicer option specifically for DI and I love that it's all done via java code and annotations and that the way you define Modules provides some compile time checking. Spring would work fine for DI, but I am still just luke warm on the config file wiring, so if I was making a decision now I would go with Guice.

Thanks again to Denis for providing the Spring example, it's much easier to do a comparison when we can see both options :)

-- Allen

Reply via email to