Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring REST Web Service and Content Negotiation

DZone's Guide to

Spring REST Web Service and Content Negotiation

· Integration Zone
Free Resource

Discover how Microservices are a type of software architecture where large applications are made up of small, self-contained units working together through APIs that are not dependent on a specific language. Brought to you in partnership with AppDynamics.

There is couple of ways to enable content negotiation in spring REST web service.

  • Using header values in @RequestMapping annotation.

We can map a request based on its Accept header value in the @RequestMapping .  Also multiple values can be specified separated with comma.

@RequestMapping(value="/order/{id}", method = RequestMethod.GET, headers = "Accept=application/json","application/xml")
	public Customer findOrderById(@PathVariable String id)
	{
		Order order;
		try 
		{
			order = orderService.getOrderDetails(id);
		} 
		catch (OrderNotFoundException e) 
		{
			system.out.println("Order not found in the system");
		}
		return order;
	}

I want to mention here that , instead of @PathVariable annotation we can use @RequestParam annotation to map values in request url. We can explicitly define the parameters to be mapped using the param field.

@RequestMapping(value="/order/", , params = "id", method = RequestMethod.GET, headers = "Accept=application/json,application/xml")
	public Customer findOrderById(@RequestParam("id") long id)
	{
		Order order;
		try 
		{
			order = orderService.getOrderDetails(id);
		} 
		catch (OrderNotFoundException e) 
		{
			system.out.println("Order not found in the system");
		}
		return order;
	}

  • Using spring content negotiation manager.

When the controller returns the value, content negotiation manager gets the control and check for three things in the request.

1.  Is there an extension (eg .xml/.json) with the request?

2.  Is there a parameter (eg ?format=json)  with the request?

3.  Is there a accept header specified in the request?

Content negotiation manager always checks for strategy in this order, path extension, parameter and Accept header. In spring rest web service by default content negotiation manager will work with extension. We don’t need to make any configuration for this. But using extensions are not standard in REST web service.

In order to enable custom content negotiation logic, you need to define a content negotiation manager in the diapatcher servlet. Please see below the bean defined.

<!-- To switch on  content negotiation strategies -->
	<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
	
	<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
		<property name="favorPathExtension" value="false"/>
		
		<property name="favorParameter" value="true"/>
		
		<property name="parameterName" value="formatType"/>
		
		<property name="mediaTypes">
			<map>
				<entry key="json" value="application/json"></entry>
				<entry key="xml" value="application/xml"></entry>				
			</map>
		</property>
		
		<property name="ignoreAcceptHeader" value="false"/>
		
	</bean>

For this content negotiation manager we defined the three strategies we defined earlier. We can set those values to true or false. Here we are disabling the strategies 1 and 3 and enabling strategy 2. We can explicitly provide the parameter name(eg : formatType) and the media types that can be used.

I hope this will help you to properly define a content negotiation strategy for your REST web service.

Discover the six challenges and best practices in managing microservice performance, brought to you in partnership with AppDynamics.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}