Hi all !
Anyone had time to have a quick look at this?
I'd love to get some feedback, see if I should carry on in that
direction (I'd be more than happy to!)
Thanks a lot
Denis Balazuc
Denis Balazuc wrote:
> Hello all
>
> I've finally found some time to tidy up a Spring demo for Roller. I've
> tried to include various different aspects of what Spring can bring into
> a project such as Roller (depency injection, interceptors and
> transaction management mostly) and focused on easy back-end switch and
> simple configuration for the mail and the main datasource. There are
> many areas that I didnt address but where I can see some benefits from it.
>
> #Journey onward with Spring!
>
> Before going further, I would like to mention that, with ACEGI already
> at the source of the security model of the Roller webapp, it was easy to
> convince myself that introducing Spring in the business layer was just a
> natural continuation of the work that's already been done there and a
> good goal to pursue. Besides only addressing the back-end, there is a
> lot that can be done on the webapp side too. So...Spring's already
> there, temperature's getting good....let's go!
>
> A few first things
>
> * File(s) URL are at the end of this mail. For the impatients, it's
> better to read from the bottom to the top.
>
> * When mentionning classnames or other code details, I will be referring
> to version 541334 of the trunk, which is before refactoring of the pojos
> and right in the middle of the creation of the /component directory.
> Classnames and details discussed hereunder may be slighty out of date. I
> also did not consider Planet as I reckoned that most of what is involved
> applies to Planet the exact same way, and RollerConfig (which should be
> trivial to Springify) to avoid getting in the midst of
> too-much-changes-at-once.
>
> * version 541334 has a few problems with creating new entries or categories
> If you ever happen to want to try to run my build, expect a few things
> to not work correctly, including things I've probably destroyed along
> the way. Having everything pristine is not the goal of this demo and
> code has moved since so it really did not really matter.
>
> * I haven't tested all of everything, some bits hereunder are also
> theory only, but those are not rocket science to implement despite my
> hidden kid desire to be a rocket scientist.
>
> #Mail and DataSource
>
> First thing, I wanted to address the problem of switching the mail
> session and the datasource, from JNDI to plain good auld java code or
> others. Spring allows you to switch those implementations without code
> that will fetch a property, check which of JNDI or plain mail session
> (or jdbc datasource) to use, and so forth. Surely it requires injecting
> a bean or some lookup code. For that, I have modified MailUtil.java and
> re-implemented DataProvider.java to use a Spring bean. In the case of
> MailUtil.java, a Spring interface, JavaMailSender is being used
> internally in place of a javax.mail.Session instance. In the case of
> DataProvider.java, Spring actually makes it obsolete as it can provide a
> datasource bean from configuration so its implementation looks up for a
> datasource bean.
> An interesting note is that the roller(-custom).property switch
> (depending on the "database.configurationType" property) is implemented
> within the Spring configuration, removing the need for the various
> service providers or factories within the code.
> This also shows how it's possible to move a lot of configuration logic
> out of the code and into XML files that usually never change.
>
> See
> src/applicationContext-rollerMail.xml
> src/applicationContext-rollerDatasource.xml
>
> #"Back-end" implementation
> I got caught in the middle of JPA changes while doing this work,
> so....switching back-end sounded like a good target for dependency
> injection. We have interfaces, we have implementation classes, ideal
> conditions for a lift-off!
> RollerImpl.java has been modified and merged from
> HibernateRollerImpl.java so it contains ALL the Roller manager
> implementations. Those are injected through
> src/org/apache/roller/business/applicationContext-business.xml using
> either common beans for the managers that do not have links to the
> database, either back-end implementation specific beans (Hibernate, JPA,
> all you can invent). Of course, the singleton nature of those
> implementations is preserved where required.
>
> See
> src/org/apache/roller/business/applicationContext-business-hibernate.xml
>
> This allows for
>
> -- Switching back-end implementations such as Hibernate, JPA or unit
> test mocks/stubs easily.
>
> -- Adding declarative transaction management and remove the need for the
> code to worry about that aspect which in Roller impersonates as the
> "HibernatePersistenceStrategy". In that particular matter, there would
> be a lot to discuss about the current implementation of the Hibernate
> layer using the HibernatePersistenceStrategy and the different approach
> that is, somewhat unfortunately, required to take when going the Spring
> way. For instance, the usage of Spring's HibernateTemplate or
> HibernateCallback(s) are encouraged, effectively tying the DAO code to
> Spring, but also moving the transaction headaches to configuration. As a
> developer, I tend to favor the fact that I do not have to worry about
> transactions or such horrible things, and leave those headaches to those
> who integrate with various systems. Being able to do it by configuration
> is a good plus.
>
> -- Ungluing the implementation code and allowing the removal of
> HibernateRollerImpl and friends, since each single manager is a
> different Spring bean, maybe sharing common attributes (such as the
> HibernatePersistenceStrategy). Those beans are injected in the
> RollerImpl facade, which allows for easy switching when, for example,
> unit test comes in the loop.
>
> -- In the very interesting case of the ThreadManager, and more generally
> the scheduling of tasks, my first thought went about what's going to
> happen to application managed thread pools or schedulers in a strict
> J2EE environment. If you intend to run Roller in a J2EE 1.4 containers,
> you may want to use container-managed thread pools, or WorkManager(s) or
> other Websphere-like WorkArea(s) and Scheduler(s). Since you can,
> transparently to the code, lookup an EJB or provide a home-grown
> implementation of a ThreadFactory/ExecutorService/etc, Spring is very
> much welcomed here. As an example. the switch from ThreadFactory to
> ExecutionService(s) in the branches after the one I was working one can
> be performed from configuration, with a small changes in the
> ThreadManagerImpl code to allow injection.
>
> #Property loading
> As mentionned above, Spring makes it easy to load various property
> sources. Spring configuration files may also reference property values
> using the usual ${value} syntax, which is what is used to populate
> properties among the various manager beans and, among many, provide the
> datasource parameters depending on the roller.properties and
> roller-custom.properties. Again, RollerConfig wasn't taken into
> consideration but it's easy to adapt its implementation to fetch its
> properties from Spring.
>
> see src/applicationContext-rollerProperties.xml
>
> #Conclusion
> I'm not great a concluding so here's some more concrete material
>
> #Files and reference
>
> I've packed some demo code within the following files. I decided against
> providing a really functional patch to submit to JIRA since my code
> baseline is already old compared to the recent changes for 4.0 and this
> whole thing is just a proof of concept.
>
>
> *
> http://denis.balazuc.net/roller/roller_541344-spring-stable.zip
> (1) That's the Roller code my build is based on (from version 541344 of
> the trunk). Much too big (150Mb) to download and messed up since it's my
> working copy, but well...
>
> *
> http://denis.balazuc.net/roller/roller_541344-spring-stable-webapp.zip
> My current test web app only (Roller - no Planet) with all JAR files but
> exploded roller-*.jar for reference (25Mb)
>
>
> *
> http://denis.balazuc.net/roller/roller_541344-spring-stable-webapp-nojars.zip
>
> My current test web app only (Roller - no Planet) without any JAR file
> and exploded roller-*.jar for reference (6.7 Mb)
>
>
> *
> http://denis.balazuc.net/roller/roller-trunk-541344-spring-patch.txt
> Patch made from (1) from trunk version #541344. You will still need the
> JAR files listed above. I"m not very familiar with patching so it might
> not be reliable.
>
>
> First things you may want to look at are the Spring configuration files
> (it's not XML hell, honest)
>
> /src/applicationContext-rollerProperties.xml
> /src/applicationContext-rollerMail.xml (used in MailUtil.java)
> /src/applicationContext-rollerDatasource.xml
>
> /src/applicationContext-roller.xml
> /src/org/apache/roller/business/applicationContext-business.xml
> /src/org/apache/roller/business/applicationContext-business-hibernate.xml
>
>
> #Build considerations
> I had to replace a few JAR files with new ones and created
> /tools/spring-2.0.5
> /tools/spring-2.0.5/acegi-security-1.0.3.jar
> /tools/spring-2.0.5/ehcache-1.2.4.jar
> /tools/spring-2.0.5/spring.jar
>
>
> #More files for the curious
>
> * There is a
> /src/org/apache/roller/business/applicationContext-business-hibernate2.xml
> along with its own hibernate2 implementation package, which uses a
> Hibernate SessionFactory provided by Spring and delegating transaction
> management to the configuration, rather than implementing a specific
> "strategy". This setting is not currently working as it would require a
> different approach on DAOs. The provided example shows how transaction
> management could be done, but ideally, Spring's HibernateTemplate and
> HibernateCallback(s) should be used to perform simple unit of (database)
> work within a transaction into the Hibernate implementation layer if
> Spring is to be exploited with its full potential.
>
> * The file
> /src/org/apache/roller/business/applicationContext-business-jpa.xml is
> not functional at all but exists for the sole purpose of demonstrating
> how painlessly implementations can be switched if required.
>
>
> **
> http://denis.balazuc.net/roller/blug-project-demo.zip
> This is a personal project I had started after Struts-ifying Pebble
> (http://pebble.sourceforge.net/), which still serves my wife's blog
> nicely but needs replacement, and before meeting Roller. Most of the
> Spring ideas exposed here come from there. I've tried to separate the
> DAO and business layers in various projects, which helps leveraging
> Spring's benefits.
>
> Cheers
> Denis Balazuc
>
|