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

<mvc:view-resolvers> does not reliably find declared ContentNegotiationManager [SPR-13559] #18135

Closed
spring-issuemaster opened this issue Oct 9, 2015 · 3 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Oct 9, 2015

Paul Chapman opened SPR-13559 and commented

In the following, does the ContentNegotiatingViewResolver created by <mvc:view-resolvers> automatically get set with the mvcContentNegotiationManager? My tests are telling me not.

	<mvc:annotation-driven
		content-negotiation-manager="mvcContentNegotiationManager" />

	<!-- View resolver chain -->
	<mvc:view-resolvers>
		<mvc:content-negotiation use-not-acceptable="true" />
		<mvc:bean-name />
		<mvc:tiles />
		<bean class="rewardsonline.accounts.JsonViewResolver" />
	</mvc:view-resolvers>

	<bean id="mvcContentNegotiationManager"
		class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
		<property name="ignoreAcceptHeader" value="true" />
		<property name="defaultContentType" value="text/html" />
	</bean>

Running this as a servlet app does work, but my MockMvc test fails trying to generate JSON.

If I explicitly get the ContentNegotiatingViewResolver when the test starts and manually set the ContentNegotiationManager to mvcContentNegotiationManager, it works.

I would expect the CNVR created using <mvc:view-resolvers/> to be initialised with the same ContentNegotiationManager that was specified to <mvc:annotation-driven>.


Affects: 4.1.7, 4.2.1

Referenced from: commits 0f1897d, c599514, 563a120, f84a0c9

Backported to: 4.1.9

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 9, 2015

Rossen Stoyanchev commented

What version are you using? Also could you provide some details on how your tests indicate what CNVC is used?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 11, 2015

Paul Chapman commented

I am using Spring V4.2.0.RELEASE.

The code I wrote did the following:

  1. Fetched the one and only view-resolver the application context. - turns out to be a ViewResolverComposite.
  2. Iterates over its view-resolvers to find the CNVR
  3. Found the one and only ContentNegotiationManager in the application context.
  4. Used reflection to access the contentNegotiationManager inside the CNVR
  5. Checked to see if the two ContentNegotiationManagers were the same instance - they weren't
  6. Used cnvr.setContentNegotiationManager(contentNegotiationManager) to set the ContentNegotiationManager in the CNVR instance to eb the one in the application context.

After that, when I ran my MockMvc test to fetch JSON, I did get JSON returned. Before it was returning HTML and my test failed - I think because the original ContentNegotiationManager in the CNVR instance was not the one I had configured to look for .json on the end of the URL.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 19, 2015

Rossen Stoyanchev commented

It appears this is sensitive to where the "mvcContentNegotiationManager" bean appears. It works if it is before <mvc:view-resolvers>.

On the implementation side, ViewResolversBeanDefinitionParser is checking if context.getRegistry().containsBeanDefinition(beanName) where beanName is "mvcContentNegotiationManager". Two issues here, one it shouldn't be sensitive to the order of declaration and two it should work in cases where a ContentNegotiationManager is configured with a bean reference, i.e.:

<mvc:annotation-driven content-negotiation-manager="myManager" />
<bean id="myManager" class="..." />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.