After a "slight" delay, I've been working on a solution. (I'm a
Master's student and it appears I have little spare time for private
projects right now, hence the delay)
I didn't want to use Spring if it's not needed; in my opinion just using
Tapestry should be enough.
One line of thought that I've been toying with the last couple of days
is to have a @UseDatabase annotation, e.g.
@Inject @UseDatabase("one") Session sessionOne,
@Inject @UseDatabase("two") Session sessionTwo
The implementation is a custom object provider, which provides objects
for the interfaces Session, HibernateSessionSource,
HibernateSessionManager, HibernateTransactionDecorator and
HibernateTransactionAdvisor.
There is a configurator object (MultiHibernateEntityPackageManager) that
is configured by Map<String, Collection<String>>, with the semantics
(database-id) -> {packageName}
By default is uses "/hibernate-«name».cfg.xml" for the configuration.
Obviously, because it's a custom object provider, the whole lifecycle
stuff doesn't apply, which is a terribly ugly hack really. Besides, it's
absolutely not compatible with the original tapestry-hibernate-core module.
A different issue is that the Tapestry/Hibernate (web) integration
module also depends on Session objects, which needs to be solved at some
point (right now I just deleted them, keeping only a modified
CommitAfterWorker, which works btw).
All in all, this seems to work, but it's ugly and I have some feeling
I'm also violating Tapestry principles somewhere.
A different line of thought that I am considering is using a construct
like in the Tapestry / Swing integration package, to create all
services. There is still the issue of the Tapestry/Hibernate (web)
integration module assuming that there is only one database.
It would have
@InjectService("SessionOne") Session sessionOne.
I don't really see how the Marker option would be implemented, but this
may be my lack of experience with Tapestry. You say it can be done
without changing the framework? At the very least, it seems Persisting /
ValueEncoder / all that stuff would be broken.
Any thoughts?
Op 2-6-2010 17:23, Howard Lewis Ship schreef:
there's been some talk about allowing for seperate Sessions (and
related), using marker annotation to identify which one you need.
I.e., you might have
@Inject @Product
private Session productSession;
@Inject @Content
private Session contentSession;
That's not too hard; the tricky part is the replication of several
services with the same interface; i.e., you will need an @Product
HibernateConfigurer and a @Content HibernateConfigurer, etc.
This could all be done, and done on top of tapestry-hibernate without
changing the framework, I think. The only tricky part is that the
default HibernateConfigurer assumes that you start by reading
hibernate.cfg.xml and that would need to be more flexible
(hibernate-products.cfg.xml, hibernate-session.cfg.xml).
On Tue, Jun 1, 2010 at 3:25 PM, Tom van Dijk<[email protected]> wrote:
Hi,
I'll be brief to save you time.
I want to turn my webapplication (for a company I work for, I'm doing a
proof of concept to see if what I want is possible) into a Tapestry5 based
system.
Our web applications use multiple databases (to enforce seperation of
concerns and for possible future scaling)
We currently use two filters that provide two EntityManagerFactory objects
(this is just for a small proof of concept webapp) and what I would like is
to have two differently configured Session services. Obviously, I want to
move on, embrace the future and start using a proper IoC framework.
Now I see in the issue system that this (using multiple databases) is
unsupported. My question concerns a generalized approach. My first thoughts
were on creating some kind of a general Factory service that would spawn the
necessary custom services, but at second thought I found something that
might be less complex.
What if there were a way to copy existing services and override their
configurations? Unless I'm really stupid, this is not yet possible.
One rather obvious issue is that the services I'd like to copy depend on
eachother, so there would have to be a method to map them all to a copy.
Else I would copy a service only to find that it's still depending on the
original's services.
Constraints:
The software is supposed to be unaware of the implementation classes but it
may of course be aware of the externally provided services.
I don't want to copy existing code. Obviously. It would hurt reusability.
Basically, what we're dealing with is a matter of creating different
services (or groups of services) with different configurations.
So, we have 3 services
HibernateSessionManager
HibernateSessionSource
HibernateEntityPackageManager
Session
Now what I would like is to create 3 new services:
ContentSessionManager
ContentSessionSource
ContentEntityPackageManager
ContentSession
ProductsSessionManager
ProductsSessionSource
ProductsEntityPackageManager
ProductsSession
Now I would like a service "ServiceCopier" or something like that to
implement: [pseudocode]
Map<String, String> content = { "Session" => "ContentSession",
"HibernateSessionManager" => "ContentSessionManager",
"HibernateSessionSource"=>"ContentSessionSource",
"HibernateEntityPackageManager"=>"ContentEntityPackageManager" }
Map<String, String> products = {"Session" => "ProductsSession",
"HibernateSessionManager" => "ProductsSessionManager",
"HibernateSessionSource"=>"ProductsSessionSource",
"HibernateEntityPackageManager"=>"PrudctsEntityPackageManager" }
copier.add(first);
copier.add(second);
This would happen in the Module, of course. I would also set
DefaultConfiguration to false and provide my own thingie for that, but
that's simple once the new services are coaxed to use the contributions
using their new service id.
The service builder would construct the three services as normal, except
that whenever ContentSessionManager depends on HibernateSessionSource, it
will depend on ContentSessionSource instead, et cetera. I can then use
@InjectService("ContentSession")
There is one important thing: the contributions from the original service
will have to be included, as well as contributions for the new service id.
If this would not happen, configurers such as
PackageNameHibernateConfigurer.java would not be included. The proper usage
of the concept explained here is that a user would not provide extra
configuration contributions for the base case, but only for the derived
services.
Hmmm this sounds conceptually a bit like namespaces, but you're way ahead of
me in experience so I can't really comment on the similarity.
Anyway, I promised to keep it brief and I doubt I could describe it in less
words. I've described my problem and leave it to you to reply.
Hoping for an answer,
Tom van Dijk.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]