Adam,
Thanks for your insightful response.
I agree that the coupling with Spring is not ideal (as indicated by
the ugly cast to SpringApplicationContext in my createResource
method). However, SpringFinder and SpringApplicationContext are my
only touch points. Those would be pretty easy to rewrite in the
improbable chance I'd change my IoC framework. More important for me
was to (1) decouple resource creation from Spring and (2) make the
Finder generic enough so that I can add resource definitions to the
Spring context without having to change the Finder (i.e. using the
beanOfType look-up).
As to your other point, I'm not sure how creating Resource instance
from Spring would necessitate creating "heavy" middle-tier classes
for each request. As my simple example shows, most (all?) of the
Resource's collaborators will be singletons. As such, Spring only has
to create them once. Otherwise, its just calling new UserResource and
invoking the setters with already instantiated singletons. Am I
missing something?
Again, thanks.
Justin
On Sep 4, 2007, at 6:15 PM, Adam Taft wrote:
That's a decent approach. As you say, you _have_ to make sure your
beans are marked as non-singleton (prototype) scope. Otherwise,
you've got threading problems.
The (tiny) problem with your approach is that you are tightly
coupling your SpringFinder with the Spring library. Well, duh
right? Ya, this isn't too much a problem for most people.
However, it is a problem if you decide to use another IoC framework
at some point. Spring would be _ideally_ configured without any in-
class dependencies. But, obviously that's just the pie-in-the-sky
ideal.
I like injecting the necessary properties into the Finder class
itself, and then my createResource class creates simple little
connector classes to the appropriate spring beans. For one, this
saves the Spring dependency.
This approach is also nice because it saves the Spring container
from having to continually generate the more "heavy" middle-tier
classes (like services, daos, etc.). With this approach, the heavy
stuff is still a singleton spring bean, and the Finder still gets
to create small little Resource classes like it wants to.
With your approach, however, you end up having to continually
create your inner spring beans per request. Maybe this scales,
maybe it doesn't, but it's something at least to keep in mind.
I guess generally that's why I like my spring managed beans to stay
singletons and using a small "wrapper" that converts the normally
stateful Resource into a stateless request into the singleton.
Adam
Justin Makeig wrote:
Tom, thanks for your additional input into Restlet/Spring
integration. I too am looking for "the" solution.
So far, I take a slightly different approach and use Spring's
ApplicationContext as my Resource factory.
I've created SpringApplicationContext as an extension of
com.noelios.restlet.application.ApplicationContext and expose the
Spring ApplicationContext as a property. I extended Finder as
SpringFinder. Its createResource method looks as such:
@Override
public Resource createResource(final Request request, final
Response response) {
ApplicationContext springContext = ((SpringApplicationContext)
this.getContext()).getSpringApplicationContext();
Resource resource = (Resource) BeanFactoryUtils.beanOfType
(springContext, getTargetClass());
resource.init(getContext(), request, response);
return resource;
}
I get the Spring ApplicationContext from the Finder's (Restlet)
context and then look for a resource bean there by type. So
essentially, my Spring ApplicationContext is my resource factory.
For example,
<bean id="userResource" class="net.troove.ui.restlet.UserResource"
singleton="false">
<property name="userDao" ref="userDao"/>
<!-- Other collaborators here -->
</bean>
<bean id="userDao" class="net.troove.test.SimpleUserDao"
singleton="true" />
where net.troove.ui.restlet.UserResource extends
org.restlet.resource.Resource.
Because resources are request-scoped, you have to make sure they
declare singleton="false".
Comments/criticism would be much appreciated.
Justin