Hello,

I'm having a hard time getting the b17 release running using Tomcat and Spring. What I am trying to accomplish is the setup as described by Manohar Viswanathan, but unlike Manohar I am using the B17 release.

This is what I've done so far.

The 'standard' stuff in web.xml. The 'org.restlet.target.class' is set to 'com.javafabric.jobstoday.ws.rest.util.RestTarget', a class extending 'org.restlet.component.RestletContainer'. The 'handle' method is overridden. For the sake of readability I've attached the sources files. Looking at RestTarget you'll notice that on the first handle invocation a manager bean is retrieved from the Spring context. That manager uses the RestTarget instance to setup a 'RestletContainerBuilder'.

The following snippet shows how I think the various resources should be linked to instances of Restlet. This snippet is from the manager's init method.

RestletContainerBuilder builder =    Builders.buildContainer(rootContainer);

for ( ResourceMapping mapping : resourceMappings ) {
  Map<String, Restlet> restletMap = mapping.getRestletMap();
  for ( String key : restletMap.keySet() ) {
    LOG.info(key + "/" + restletMap.get(key));
    builder.attachRouter().attach(key, restletMap.get(key));
  }
}

Now, assuming that the key has a value of '/vacancy' and the corresponding map class is an instance of Restlet with a handleGet method, then an 'http://localhost:8080/ws-rest/vacancy' URL should invoke the restlet's handleGet method?

I've included the spring configuration file (ws-rest-application-context.xml). the resource (Vacancy.java), an overridden RestletContainer (RestTarget.java) and the manager to set up the restlets and their corresponsind URLs (RestManager.java).

Deployment of this code works like a charm. With the a 'http://localhost:8080/ws-rest' url I notice the invocation of the handle method of RestTarget. However, Tomcat gives a 405 error; 'The method specified in the Request-Line is not allowed for the resource identified by the request URI'. What is it that I do work?

Thank you very much for your time,
Marcel



Resources:
http://manoharviswanathan.com/blog/tech/developing-restful-web-services-in-java/
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee";
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd";
         version="2.4">

    <!-- $Id: web.xml 56 2006-06-30 11:38:51Z mgl $ -->
    <display-name>JobsToday WS Rest</display-name>

    <distributable/>

    <context-param>
        <param-name>org.restlet.target.class</param-name>
        <param-value>com.javafabric.jobstoday.ws.rest.util.RestTarget</param-value>
    </context-param>

    <!-- Parameter indicating the Servlet attribute to use to store the target Restlet reference -->
    <context-param>
        <param-name>org.restlet.target.attribute</param-name>
        <param-value>org.restlet.target</param-value>
    </context-param>

    <!-- Parameter indicating the name of an initialization parameter that should be set with the ServerServlet context path -->
    <context-param>
        <param-name>org.restlet.target.init.contextPath</param-name>
        <param-value>contextPath</param-value>
    </context-param>


    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:ws-rest-application-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>RestServlet</servlet-name>
        <servlet-class>com.noelios.restlet.ext.servlet.ServerServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>RestServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans";
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
       xmlns:util="http://www.springframework.org/schema/util";
       xmlns:aop="http://www.springframework.org/schema/aop";
       xmlns:tx="http://www.springframework.org/schema/tx";
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd";>

    <!-- $Id: $-->


    <!-- Restlets -->
    <bean id="vacancyRestlet" class="com.javafabric.jobstoday.ws.rest.resource.Vacancy"/>

    <!-- Manager: manages mapping of restlets, guard etc -->
    <bean id="manager" class="com.javafabric.jobstoday.ws.rest.util.RestManager">

        <property name="resourceMappings">
            <list>
                <bean class="com.javafabric.jobstoday.ws.rest.util.ResourceMapping">
                    <property name="restletMap">
                        <bean class="java.util.HashMap">
                            <constructor-arg>
                                <map>
                                    <entry key="/vacancy">
                                        <ref local="vacancyRestlet"/>
                                    </entry>
                                </map>
                            </constructor-arg>
                        </bean>
                    </property>
                </bean>
            </list>            
        </property>
    </bean>


</beans>
/*
 *
 * Copyright 2004 - 2006 JavaFabric, the Netherlands. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are not permitted.
 *
 * Neither the name of JavaFabric or the names of contributors may be
 * used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * JAVAFABRIC AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR
 * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE,
 * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES.
 * IN NO EVENT WILL JAVAFABRIC OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF JAVAFABRIC HAS BEEN ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package com.javafabric.jobstoday.ws.rest.util;

import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restlet.connector.Client;
import org.restlet.component.RestletContainer;
import org.restlet.Restlet;


/**
 * TBS
 * 
 * <p><b>Usage:</b><code> N/A</code>
 * 
 * @author <a href="mailto:[EMAIL PROTECTED]">Marcel Schepers</a>
 * @version $Id: $
 * @since Aug 10, 2006
 */
public class ResourceMapping implements Serializable {
    private static final Log LOG = LogFactory.getLog(ResourceMapping.class);

    private Map<String, Restlet> restletMap = new HashMap<String, Restlet>();

    public Map<String, Restlet> getRestletMap() {
        return restletMap;
    }

    public void setRestletMap(Map<String, Restlet> restletMap) {
        this.restletMap = restletMap;
    }

}
/*
 *
 * Copyright 2004 - 2006 JavaFabric, the Netherlands. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are not permitted.
 *
 * Neither the name of JavaFabric or the names of contributors may be
 * used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * JAVAFABRIC AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR
 * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE,
 * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES.
 * IN NO EVENT WILL JAVAFABRIC OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF JAVAFABRIC HAS BEEN ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package com.javafabric.jobstoday.ws.rest.util;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restlet.Restlet;
import org.restlet.component.RestletContainer;

import com.noelios.restlet.build.Builders;
import com.noelios.restlet.build.RestletContainerBuilder;

/**
 * TBS
 * 
 * <p><b>Usage:</b><code> N/A</code>
 * 
 * @author <a href="mailto:[EMAIL PROTECTED]">Marcel Schepers</a>
 * @version $Id: $
 * @since Aug 10, 2006
 */
public class RestManager implements Serializable {
    private static final Log LOG = LogFactory.getLog(RestManager.class);

    private RestletContainer rootContainer;
    private List<ResourceMapping> resourceMappings;

    public void init() {

        if ( rootContainer == null ) {
            throw new RuntimeException("missing required property: 'rootContainer'");
        }

        if ( resourceMappings == null ) {
            throw new RuntimeException("missing required property: 'resourceMappings'");
        }

        RestletContainerBuilder builder = Builders.buildContainer(rootContainer);
        
        for ( ResourceMapping mapping : resourceMappings ) {

            Map<String, Restlet> restletMap = mapping.getRestletMap();
            for ( String key : restletMap.keySet() ) {
                LOG.info(key + "/" + restletMap.get(key));
                builder.attachRouter().attach(key, restletMap.get(key));
            }
        }

    }

    public List<ResourceMapping> getResourceMappings() {
        return resourceMappings;
    }

    public void setResourceMappings(List<ResourceMapping> resourceMappings) {
        this.resourceMappings = resourceMappings;
    }

    public RestletContainer getRootContainer() {
        return rootContainer;
    }

    public void setRootContainer(RestletContainer rootContainer) {
        this.rootContainer = rootContainer;
    }
}
/*
 *
 * Copyright 2004 - 2006 JavaFabric, the Netherlands. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are not permitted.
 *
 * Neither the name of JavaFabric or the names of contributors may be
 * used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * JAVAFABRIC AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR
 * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE,
 * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES.
 * IN NO EVENT WILL JAVAFABRIC OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF JAVAFABRIC HAS BEEN ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package com.javafabric.jobstoday.ws.rest.util;

import java.io.Serializable;
import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restlet.Call;
import org.restlet.component.RestletContainer;
import org.restlet.data.ParameterList;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.noelios.restlet.ext.servlet.ServletCall;

/**
 * Component whose main purpose is to contain and manage a set of Restlets (Handlers, Routers or Filters) in order to
 * constitue a coherent processing chain for incoming REST calls.
 * 
 * @author <a href="mailto:[EMAIL PROTECTED]">Marcel Schepers</a>
 * @version $Id: $
 * @since Aug 10, 2006
 */
public class RestTarget extends RestletContainer implements Serializable {
    private static final Log LOG = LogFactory.getLog(RestTarget.class);
    private volatile boolean initialized = false;

    public RestTarget() {
    }

    @Override
    public void handle(Call call) {

        if ( !this.initialized ) {
            try {
                // Get servlet context.
                ServletCall servletCall = (ServletCall) call.getConnectorCall();
                ServletContext servletContext = servletCall.getContext();
                WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);

                ParameterList parameters = getParameters();
                String contextPath = parameters.getValues("contextPath");
                if ( LOG.isInfoEnabled() ) {
                    LOG.info("contextPath: " + contextPath);
                }

                RestManager manager = (RestManager) wac.getBean("manager");
                manager.setRootContainer(this);
                manager.init();
                start();

                this.initialized = true;

            } catch ( Exception e ) {
                LOG.error(e);
            }
        }

        super.handle(call);
    }


}
/*
 *
 * Copyright 2004 - 2006 JavaFabric, the Netherlands. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are not permitted.
 *
 * Neither the name of JavaFabric or the names of contributors may be
 * used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * JAVAFABRIC AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR
 * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE,
 * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES.
 * IN NO EVENT WILL JAVAFABRIC OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF JAVAFABRIC HAS BEEN ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package com.javafabric.jobstoday.ws.rest.resource;

import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restlet.AbstractRestlet;
import org.restlet.Call;
import org.restlet.data.MediaTypes;

import com.noelios.restlet.data.StringRepresentation;

/**
 * TBS
 * 
 * <p><b>Usage:</b><code> N/A</code>
 * 
 * @author <a href="mailto:[EMAIL PROTECTED]">Marcel Schepers</a>
 * @version $Id: $
 * @since Aug 10, 2006
 */
public class Vacancy extends AbstractRestlet implements Serializable {
    private static final Log LOG = LogFactory.getLog(Vacancy.class);

    public void handleGet(Call call) {
        call.setOutput(new StringRepresentation("Vacancy", MediaTypes.TEXT_PLAIN));
    }


}

Reply via email to