Allen Gilliland wrote:
On Mon, 2006-03-06 at 15:06, Sean Gilligan wrote:
Allen, I definitely recommend that you at least spend a couple of hours
looking at Spring for distributed transactions and pluggable ORM layers
before going ahead with your proposed refactoring of the transaction code.
I will certainly do that, but this may be the realm where I would be least
likely to start using a framework like Spring.
In many ways, Spring is the "un-framework". The developers try really
hard to allow you to minimize or avoid altogether dependencies on the
framework, as well as give you choices "a la carte" rather than
force/push you to adopt everything. Many commercial offerings (for
obvious reasons) encourage you to depend on their product/API in as many
ways as possible. The same is true for many Open Source projects as
well, as it is only human to want the product of your labor to solve as
many problems as possible. In the Spring Framework, I see a concerted
effort and a philosophy of resisting this urge as much as possible.
My main concern is that we would move away from our own implementation of
Hibernate and into a version of Spring Hibernate, doing Hibernate the way
Spring suggests.
My (limited) understanding of how Spring works at this layer is that you
can use Springs declarative transactions as method interceptors on top
of just about any DAO layer or service object and that you don't have to
use the Spring Hibernate Templates to do this.
In other words, *I think* you could use Spring Declarative Transactions
without moving away from Roller's current implementation of Hibernate.
I'm not sure that this will work, though. My experience has been using
the default Spring+Hibernate+Declarative-Transactions implementation.
Anil, Matt, do you guys have any guidance here?
The key to using Spring Declarative Transactions is to wrap existing
Dao/Manager/Service Objects with the "TransactionProxyFactoryBean",
which implements the pre/post method-call magic to implement the
transactions. This means that whatever is using the Managers should be
getting the implementation from BeanFactory, so this is one change that
would be required in the Roller code. A side benefit to this change is
that the same mechanism used to install the proxies is the mechanism
used to plug in other manager implementations.
Now the proxies need to have a TransactionManager injected and Spring
provides a HibernateTransactionManager, which in turn requires (via
D.I.) a Hibernate SessionFactory. I don't know what would be involved
in "sharing" a SessionFactory between the current Roller code and these
Spring components. Anil, Matt?
>> If you really wanted to keep certain beans
restricted to a particular layer or module, that module could have a
private BeanFactory that the other components are not aware of. In
other words they won't be able to get access to the "ctx"
variable/reference. (In my opinion, this shouldn't be necessary.)
Hmm. That sounds promising to me. I'd like to hear more about that.
I've never done this before, but believe it should be possible. Most
Spring apps tend to use a single (Web)ApplicationContext (which is a
subclass of BeanFactory) that is a single context (container). Most
apps break up the layers (Presentation, Service, Data) into separate
configuration files, but objects from all layers are (theoretically)
obtainable by any component that has a context reference. (Although, as
Anil says, using a context reference is to be avoided in favor of DI.)
So you should be able to allocate a private BeanFactory in the Business
or Persistence layer that nothing else is aware of. (By just choosing a
constructor that points to a config file or resource and stuffing the
context away somewhere.)
I'm willing to look into this further if that will help you.
This is the other big thing that I am concerned about with Spring in
Roller. I really don't want go back to making the config more
complicated and spread out.
This is a valid concern and one that Spring doesn't automatically
address. And there is an inherent trade-off in making components more
modular vs. keeping configuration simple and in one place. Anil (and
the team) should address these issues in any proposal(s).
I think at this point I am also just having a bit of fun giving you guys a hard
time about your attempts to get Spring into Roller ;)
Hah! The camel's nose is already in the tent, via Acegi! Resistance is
futile! ;)
Seriously, though, the Spring Framework (or un-framework) is modular and
adopting it is not an all-or-nothing decision. There are multiple ways
that it could help (or hurt, if misused) Roller. Each one should be
carefully analyzed and discussed and the possible answers are "yes",
"no", and "yes, but here's a better way...". We should pay careful
attention to issues of configuration and the trade-off between
modularity and complexity. It is important to distinguish between
implementing (or refactoring) a module to use IOC/DI vs. implementing an
interface vs. extending a class. It's good that you're playing the role
of the skeptic here, it will result in better designs.
Cheers,
Sean