views:

901

answers:

3

I have a developed a Restlet application. I would like to return a JSP file on a URL request through Restlet. How can I achieve this without using a redirect?

i.e. Let's say I have the file "contact.jsp" on mydomain.com and I want people to be able to access contact.jsp at http://mydomain.com/contact

Thus, in Restlet, I would have:

router.attach("/contact", MyResource.class);

But how can I return the "contact.jsp" page? I know that a redirect would work, but I don't want users to see the ".jsp" in "http://mydomain.com/contact.jsp"... or is there another strategy that would work without even using restlet? Maybe some modification of my web.xml file?

Edit (2009-08-14):

My answer posted below doesn't work on App-Engine and Restlet. It does work however, if I don't include Restlet, or allow Restlet to have a url-pattern of "/*"

What would be ideal is to have a subclass of the Router that allows me to do this:

router.attach("/contact", "/contact.jsp");

Thanks!

Edit (2009-08-17):

I'm surprised I haven't had any responses since I posted a bounty. Will someone comment and let me know if my question/problem isn't clear?

Edit (2009-08-17):

Interesting observation. When using the method described by "Rich Seller" below, it works when deployed on Google App-Engine and not locally. Additionally, If I call http://mydomain.com/contact.jsp on Google App-Engine it bypasses Restlet and goes straight to the JSP. But, locally, Restlet takes over. That is, http://localhost:8080/contact.jsp does not go to the JSP and goes to Restlet. Do deployed app-engine applications respond differently to URLs as their local counterpart?

+1  A: 

Looks like a simple web.xml configuration.

<servlet>
     <servlet-name>contactServlet</servlet-name>
     <jsp-file>/contact.jsp</jsp-file>
</servlet>

<servlet-mapping>
     <servlet-name>contactServlet</servlet-name>
     <url-pattern>/contact</url-pattern>
</servlet-mapping>

This works without Restlet in App-Engine. But once I include Restlet, it doesn't work if I set my Reslet url-pattern to "/*"

JP
+1  A: 

Restlet doesn't currently support JSPs directly. They're difficult to handle outside of the servlet container.

There's a discussion on Nabble about this issue that you may find useful, at the moment it looks like you need to either return a redirect to the JSP mapped as normal in the web.xml, or hack it to process the JSP and return the stream as the representation.

The response dated "Apr 23, 2009; 03:02pm" in the thread describes how you could do the hack:

if (request instanceof HttpRequest &&
    ((HttpRequest) request).getHttpCall() instanceof ServletCall) {

    ServletCall httpCall = (ServletCall) ((HttpRequest) request).getHttpCall();

    // fetch the HTTP dispatcher
    RequestDispatcher dispatcher = httpCall.getRequest().getRequestDispatcher("representation.jsp");

    HttpServletRequest proxyReq = new HttpServletRequestWrapper(httpCall.getRequest());

    // Overload the http response stream to grab the JSP output into a dedicated proxy buffer
    // The BufferedServletResponseWrapper is a custom response wrapper that 'hijacks' the
    // output of the JSP engine and stores it on the side instead of forwarding it to the original
    // HTTP response.
    // This is needed to avoid having the JSP engine mess with the actual HTTP stream of the
    // current request, which must stay under the control of the restlet engine.
    BufferedServletResponseWrapper proxyResp = new BufferedServletResponseWrapper(httpCall.getResponse());

    // Add any objects to be encoded in the http request scope
    proxyReq.setAttribute("myobjects", someObjects);

    // Actual JSP encoding
    dispatcher.include(proxyReq, proxyResp);

    // Return the content of the proxy buffer
    Representation rep = new InputRepresentation(proxyResp.toInputStream(),someMediaType);

The source for the BufferedServletResponseWrapper is posted a couple of entries later.

Rich Seller
I can't get this to work, I keep getting an exception.
JP
what exception are you getting?
Rich Seller
It seems to be getting caught on "dispatcher.include"... and then it repeats..
JP
I'm not near an IDE to test this today, so this is a guess. do you have the servlet-mapping defined in web.xml as well as the dispatcher code? this maybe is causing the problem.
Rich Seller
No, the only servlet-mapping I have in web.xml is Restlet.
JP
So, here is an interesting observation... it works when deployed to app-engine. However, it doesn't work on my local machine in Eclipse. Very odd. Unfortunately, I can't use it until I can get it to work on my local machine, so that I can debug. Any thoughts on why this might be?
JP
A: 

"I would like to return a JSP file on a URL request through Restlet" - My understanding is JSP's are converted to servlets. Since Servlets are orthogonol to Restlets not sure how you can return JSP file through Restlet.

Assuming you are asking for a way to use JSP in addition to Restlet, This is best achieved by mapping your restlets to a rootpath such as /rest instead of /* and using the .jsp as usual.

Gmu