views:

163

answers:

3

The problem I am trying to solve is that I want to check all incoming GET urls against a database. If the the url exist in the database it shall be passed to a certein controller. I'm using Spring 3.0.

First I tried to make an interceptor and add that to DefaultAnnotationsHandlerMapping. Turns out i couldn't modify the url in preHandle(). The plan was to modify the url in the request and then let an annotated controller handle the rest.

Next I tried to make a custom HandleMapping. I extended AbstractUrlHandlerMapping and made my own getHandlerInternal() that returns a String with the name of the Controller and this is working. But I'd prefer a solution where I can modify the url in the request and let an annotated controller handle it.

While writing this I got thinking that maybe a servlet filter is the most proper solution. If that's the case can I get Spring to inject an EntityManager into the filter? Any Spring class I can extend that makes this easier?

What's the most proper way to solve the problem in the first paragraph? If it's the servlet filter please give me some pointers on how to write it.

A: 

You could use a normal javax.servlet.Filter and create a HttpServletRequest-Wrapper that does the URL handling for you.

fforw
A: 

Maybe wrapping the servlet request and passing it to the filter chain.

...
MyHttpServletRequestWrapper wreq = new MyHttpServletRequestWrapper(request);
doFilter(wreq, response, chain);
...

The wrapper returns a modified URL when asked.

rodrigoap
A: 

As has been pointed out by others, a standard servlet filter would do the job, but it's not a very spring-friendly solution - the filter is not managed by Spring, and so cannot be wired with Spring beans. The filter would need to fetch the spring beans programmatically, which isn't nice.

The trouble with modifying the URL of an existing request is that it rather breaks the servlet API model. HttpServletRequest has multiple path- and URL-related methods that extract different parts of the original URL, and you'd have to make sure you somehow modified all of those values. The API just isn't designed for that, whether you use filters or interceptors.

SO rather than trying to subvert the API, my suggestion is you write a Spring controller that accepts the "old" path, and which forwards the request to the "new" path, based on the injected EntityManager. The forwarding can happen by having the controller handler method return a InternalResourceView with the "new" path. It's not strictly speaking a view you're forwarding to, but Spring won't know the difference. Alternatively, you can forward it directly using request.getRequestDispatcher(newPath).forward(request, response).

skaffman
Thanks for you answer, it made me realize I was overengineer my solution. A simple `RequestMapping(value="/*") seems to be all I need.
NA