Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repository controllers not invoked if resource is handled manually in dedicated media type [DATAREST-490] #867

Closed
spring-projects-issues opened this issue Mar 11, 2015 · 4 comments
Assignees
Labels
type: bug

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Mar 11, 2015

Eberhard Wolff opened DATAREST-490 and commented

I have a Spring Data REST project. For some URLs I want to create a @Controller that renders the resources as HTML. I am using a @RequestMapping with produces = MediaType.TEXT_HTML_VALUE. In fact this controller is called if the URL is requested. However, if I do a request for JSON I get a 406 - while in fact the Spring Data REST controller should be called. I noticed that the log output says that the Spring Data REST controller doesn't register with any value for produces.

I think a value for produces should be given. Maybe there is a way to do this but I didn't find it in the reference documentation. Maybe there are other ways to get different representations of the REST resources but that doesn't seem to be documented either. I guess different representations for the same resource are an important part of REST so I think there should be a way to do what I want to do


Affects: 2.2.2 (Evans SR2), 2.3 RC1 (Fowler)

Issue Links:

  • DATAREST-522 GET on RestRepository not possible, if a RestController for the same path is available

Referenced from: commits 4f8298c

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 11, 2015

Oliver Drotbohm commented

The issue is not so much the Spring Data REST controllers not defining any produces attribute but our custom HandlerMapping setup: we currently register two HandlerMapping instances: one that handles all controllers annotated with @BasePathAwareController which are controllers whose mappings have to honor the Spring Data REST base-path configuration (e.g. the ones serving ALPS metadata). The second handler mapping handles all controllers that expose resources for repositories.

The split is necessary as the latter handling applies a stricter check for mappings to make sure it's not actually trying to handle requests for paths that are not backed by repositories. In a standard Spring MVC application, this setup will even be prepended with a standard RequestMappingHandlerMapping that will cause all standard Spring MVC controllers to be handled.

Depending on whether you use @BasePathAwareController or @Controller in your scenario, Spring MVC detects the the mapping bound to text/html as content type but rightfully not consider it as its produces clause does not match. org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(…) will then discover the request actually matching except the media type and thus throw an exception to indicate that state. This however bubbles up through DispatcherServlet.getHandler(…) which actually iterates all HandlerMapping to find a suitable ones but thus causes all other registered HandlerMapping instances not even being tried.

IYAM, that particular method should actually continue trying to resolve a handler until it exhausted all registered and only throw the exception if it couldn't find one eventually. Although I haven't made up my mind on which exception to finally throw in case multiple HandlerMappings threw exceptions. As this would mean a pretty core change to the framework, I wonder what juergen.hoeller and Rossen Stoyanchev think about this.

The even more problematic aspect here is that we can't fully solve this issue in Spring Data REST. I could of course hide our two HandlerMapping implementations behind a delegating HandlerMapping that does the special exception handling. This however would not fix the issue for users using @Controller as this would still be handled by a separate HandlerMapping and thus run into the issue described above

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 11, 2015

Eberhard Wolff commented

Thanks a lot for looking into this! At least I did not do anything stupid. :-)

I have a workaround: I am using @RequestMapping with .html in the URL - and that works

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 11, 2015

Oliver Drotbohm commented

This should be fixed with this commit. I basically implemented what I described above, so that you should be able to get this working using @BasePathAwareController. Discovered a [tiny glitch|SPR-12806] in DispatcherServlet along the way.

Feel free to give the 2.3.0 snapshots a try (switching the Spring Boot spring-data-releasetrain.version property to Fowler-BUILD-SNAPSHOT

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 25, 2015

Thibaud Lepretre commented

Lol that why my application failed when upgrading to Fowler train :) I can now remove my similar bean I created before 2.3.0 like following: http://stackoverflow.com/a/27802520/636472.

However could be possible to have a configure method inside RepositoryRestMvcConfiguration to custom it? In my case I want to add RequestMappingHandlerMapping inside delegation chain.

configure should allow to add handler inside list and maybe change Order value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug
Projects
None yet
Development

No branches or pull requests

2 participants