Skip to content

Read RestTemplate Accept header from entity annotation [SPR-12096] #16712

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

Closed
spring-projects-issues opened this issue Aug 18, 2014 · 7 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Aug 18, 2014

Christopher Smith opened SPR-12096 and commented

Current best practice is to version REST APIs by media type (application/vnd.example.person-v1+json), but the RestTemplate does not provide a simple mechanism for indicating the Accept header for an entity type when using a general-purpose converter (such as Jackson). Instead, the AcceptHeaderRequestCallback will add all potentially matching media types to the Accept header.

It should be possible to annotate an entity class to specify the media type that RestTemplate will request from the server so that older clients will not send an unversioned request that they can't understand:

@EntityMediaType("application/vnd.example.person-v1+json")
public class Person {
    // stuff
}

Affects: 4.0.6

Issue Links:

0 votes, 5 watchers

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

What about setting the supportedMediaTypes property on the converter?

@spring-projects-issues
Copy link
Collaborator Author

Christopher Smith commented

That approach is cumbersome and, without completely hand-configuring the template, unreliable. In my case, the standard Jackson 2 mapper is perfectly sufficient for the actual conversion, and at a minimum I'd have to create a template without default converters (because the standard converter would add Accept: application/json, which might return the wrong version for the entity class) and write and register a converter for every single class I want to use with the template. Instead, I just want to declaratively specify a different Accept type (which can't currently be overridden, just appended to, with additional converters) on the single class in question (not in some companion class or external configuration) and run the conversion through the usual utilities.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

I guess what I was getting at is do you need to use different versions on different entities in the same app?

Configuring converters on the RestTemplate overrides defaults. So you'll need to list the converters you want, which is really straight forward and only done once. The ability to apply different versions on different entities IMO would be a stronger requirement for having some such annotation. Hence my question.

@spring-projects-issues
Copy link
Collaborator Author

Christopher Smith commented

I'm not sure I understand your question. Each entity class has its own (versioned) media type, but besides that, the out-of-the-box converter's behavior handles everything perfectly; listing converters requires writing, instantiating, and updating converter classes that do nothing except narrow the Accept type.

I would expect to use the same RestTemplate instance for all of the REST interactions with a Web application, but that template would be handling requests for a number of different entity classes with distinct media types.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Okay I see your point. We can consider ways to improve working with versioned media types. One concern with the annotation is the ability to use it with more than one version but I can see that a single version is the 80% (common) case. When changing versions you would have to make sure the versions in all entity annotations are updated accordingly, which seems like a chore although I don't have any better ideas.

Note that there is also the option to use the RestTemplate's exchange methods, essentially passing a RequestEntity with the Accept header set, but considering that this is required for every operation with a response entity, it amounts to bypassing the more convenient RestTemplate methods by HTTP method wholesale.

@spring-projects-issues
Copy link
Collaborator Author

Christopher Smith commented

Generally speaking, the Java entity class will correspond to a specific API version, since the server side will need to be able to distinguish between representation classes for different versions. I'm actually using a rest.v0 package to separate these. In the unusual case where an entity class is forward-compatible, it might make sense for the annotation to be multi-valued, but since you have to tell the template ahead of time which class to deserialize onto (no inference from the media type), there wouldn't be any ambiguity.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Apr 13, 2015

Rossen Stoyanchev commented

After some internal discussion the prevailing opinion is that such an annotation is not a good fit for use with the RestTemplate and would be too narrowly defined. It would be a better candidate for a higher-level REST programming model for example such as the one proposed here #16747.

Note also that it would be trivial for you to add such support by overriding the acceptHeaderRequestCallback method.

@spring-projects-issues spring-projects-issues added status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants