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

--
troove Inc.
http://troove.net/
(877) 330-8504

"The troove appliance -- enterprising find"



On Sep 4, 2007, at 2:56 PM, Tom McGee wrote:

I need more ability to configure and/or define restlet classes
(Component, Route, Router, Application, Filter, Resource and Restlet)
with spring. I think I have a spring framework addiction :-)

There is something of an architectural mismatch between the restlets
framework and the spring framework. With spring the way it works best
to let the spring container create and configure object instances.
The context for object instance is injected by spring. With restlets
the context is passed throw the applications object instances with a
chain of constructors.

To get around this I'm not using spring to create the restlets class
instances directly.  Instead I use spring to create factories that
make the instances. For example here's a  Resource factory:

public abstract class ResourceFactory extends Finder {

public Resource createResource(Request request, Response response) {
        Resource result = build();
        result.init(getContext(), request, response);
        return result;
    }

    public abstract Resource build();
}

public class PlayRestResourceFactory extends ResourceFactory
implements RouteCallback, UriPatternProvider{

        @Override
        public Resource build() {
                return new Resource(){
                        private String testname;
                        
                        @Override
public void init(Context context, Request request, Response response) {
                                super.init(context, request, response); 
                                
                                testname = (String) 
request.getAttributes().get("testname");
                                this.getVariants().add(new 
Variant(MediaType.TEXT_PLAIN));
                        }
                        @Override
                        public Representation getRepresentation(Variant 
variant) {
return new StringRepresentation(testname+" "+playBean.getMessage ());
                        }
                        
                };
        }

        private PlayBean playBean;

        public void setPlayBean(PlayBean playBean) {
                this.playBean = playBean;
        }

        public void routeCallback(Route r) {
                System.out.println("PlayRestResourceFactory::routeCallback");
                
        }

        public String getUriPattern() {
                return "/test3/tom_{testname}";
        }

}

I have factory objects for Application, Filter, Resource, Restlet and Router.

Where I could not control the creation of objects with factories I've
added callback objects to at least give access to configure. Here's
the callback a Component:

public class PlayComponentCallback implements ComponentCallback {

        public void componentCallback(Component c) {
                c.setLogService(new LogService(false));
        }
}

I have callbacks for Component, Route and Router.

I have extended ServerServlet use these new classes:

public class SpringRestletServlet extends ServerServlet {

        private static final long serialVersionUID = 2974584650224678065L;

        // init param name of spring bean name for component callback
        private static final String COMPONENT_CALLBACK_INIT_PARAM =
"lazyeye.restlet.spring.servlet.SpringRestletServlet.componentCallback ";
        // init param name of spring bean name for application factory
        private static final String APPLICATION_FACTORY_INIT_PARAM =
"lazyeye.restlet.spring.servlet.SpringRestletServlet.applicationFactor y";
        // default value of spring bean name for component callback
        private static final String COMPONENT_CALLBACK_DEFAULT =
"restletComponentCallback";
        // default value of spring bean name for application factory
        private static final String APPLICATION_FACTORY_DEFAULT =
"restletApplicationFactory";
        
        private String componentCallbackId;
        private String applicationFactoryId;
        

        /*
* reads the init parameters for component callback and application factory * then does parent init() and then send the the component to the component
         * callback.
         *
         * @see com.noelios.restlet.ext.servlet.ServerServlet#init()
         */
        public void init() throws ServletException {
                componentCallbackId =
this.getInitParameter (COMPONENT_CALLBACK_INIT_PARAM,COMPONENT_CALLBACK_DEFAULT);
                applicationFactoryId =
this.getInitParameter (APPLICATION_FACTORY_INIT_PARAM,APPLICATION_FACTORY_DEFAULT);

                super.init();

// Look to see if there is a ComponentCallback object defined for this
                // SpringRestletServlet instance and call it if it's there.
                if ((getSpringContext() != null)
                                && 
(getSpringContext().containsBean(componentCallbackId))) {
ComponentCallback componentCallback = (ComponentCallback) getSpringContext()
                                        .getBean(componentCallbackId);
                        
componentCallback.componentCallback(this.getComponent());
                }
        }

        private ApplicationContext springContext;

        /**
         * @return spring application context
         */
        public ApplicationContext getSpringContext() {
                if (springContext == null) {
                        springContext = WebApplicationContextUtils
                                        
.getWebApplicationContext(this.getServletContext());
                }
                return springContext;
        }

        /*
         * This is an overwrite of the parent method. Now the Application is
created using
* a an ApplicationFactory object obtained from the Spring application context.
         *
* @see com.noelios.restlet.ext.servlet.ServerServlet#createApplication (org.restlet.Context)
         */
        public Application createApplication(Context context) {
                Application result = null;
                if ((getSpringContext() != null)
                                && 
(getSpringContext().containsBean(applicationFactoryId))) {
                        ApplicationFactory applicationFactory = 
(ApplicationFactory)
getSpringContext()
                                        .getBean(applicationFactoryId);
                        result = applicationFactory.build(context);
                }
                if (result == null) {
                        result = super.createApplication(context);
                }
                return result;
        }
}


None of this has been fully tested yet but I want to share what I've
done so far with the hope that I might get your opinions.
<ComponentCallback.java>
<RouteCallback.java>
<RouterCallback.java>
<ApplicationFactory.java>
<ApplicationFactoryImp.java>
<FilterFactory.java>
<ResourceFactory.java>
<RestletFactory.java>
<RouterFactory.java>
<RouterFactoryImp.java>
<UriPatternProvider.java>
<SpringRestletServlet.java>

Reply via email to