Is there a simple way to solve content negotiation in Spring boot - spring-mvc

We plan to use content type negitiation as a form of versioning for our rest API but it seems more complex than it should be.
Given the follwing example code :
#RestController
#RequestMapping("/products")
ProductController {
.......
#RequestMapping(value = "/{productID}", method = RequestMethod.GET, produces = "productVersion2/json")
public ResponseEntity<ProductV2> getVersion2(#PathVariable String productID) {
.......
return new ResponseEntity<ProductV2>(product, HttpStatus.OK);
The correct method is being called when test this from e.g postman, but i get a HTTP 406 Not Acceptable as a response. I have been looking several places, but I have not found a a page with a good explanation of what i need to do to make this work.
The response is to be parsed with json just like all other requests, but the response object is modified.
The thought is that we by doing this can support several "versions" of the same API and we can gradually make clients move over to the new api, while still having the same uri/resource to access.
Can anyone point to a good tutirial or a step by step guide of how this can be solved in spring boot ?
I have read this article : http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc/#combined-controller
but I was not able to get a clear anderstanding of what was needed to make it work

Your media type is wrong. To use custom media types for API versioning you could use application/productVersion2+json instead of productVersion2/json. I suspect you get the 406 because Spring Boot has no way to find out how to serialize your object into JSON because productVersion2/json isn't a valid media type for json data.
There is more than one way to pick a media type to do this, I've googled a more comprehensive document here.

Related

Can I configure asp.net so some responses are serialized as camelCase and some as PascalCase?

I have an API with two clients: OldClient and newClient. I currently have this in Startup.cs so my json responses are serialized as PascalCase, i.e. as per all my .net objects which have first letter capitalized.
services.AddControllers().AddJsonOptions(jsonOptions =>
{
// So json output is like 'SomeId' instead of 'someId':
jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null;
...
}
OldClient loves this format. However, newClient would really prefer camelCase.
Is there a way I can configure my app to respond with camelCase for newClient requests and PascalCase for OldClient requests? newClient can send a header to indicate that it wants camelCase.
You can check out this issue on aspnetcore's github page
The possibility of using specific JSON Serializer Options on a per-controller basis hasn't been implemented yet. It has been moved to ".NET 8 planning", which means it's still a ways-away.
Meanwhile, you could work around this issue by:
For data reception and model-binding, you could create a Custom ModelBinder by implementing IModelBinder interface in a ModelBinderAttribute in order to utilize your specific JSON Serialization options. Then, you could simply add the attribute to the endpoints where you need it.
For data responses, you could simply use:
return new JsonResult([object], [CustomJSONSerializationSettings]);
It's quite annoying to have to modify these per-endpoint, but it seems like it's the only way until the feature is added in .net 8 (if we're lucky).

Alfresco Java backed web-script lookup by cmis:objectId

I am writing my first java-backed webscript for Alfresco community edition. I am implementing document properties / preview service, and I take a parameter which is the cmis:objectId of the document in question. I'm having trouble getting started because I haven't been able to access the document based on the cmis id.
What is the best way to get a document (NodeRef?) based on the cmis:objectId when operating server-side in a web-script controller? I see Jeff Potts' great examples on how to implement web scripts, but the mixing of the Java API and CMIS concepts has me stuck. Should I just use the search service and find the object based on the cmis:objectId property? Any pointers appreciated.
Well, the answer is a little ugly, but hopefully this helps someone...
A good way to look up the NodeRef using an 'opaque' objectId should be to use CMISServices, obtained from the registry in your java backed web script, i.e.
docRef = registry.getCMISService().getLatestVersion(docIdStr, false);
Unfortunately, there's a bug in the Alfresco code (or so it seems to me, admittedly a bit of a newbie). The alfresco CMISServicesImpl.getLatestVersion() uses a getObject() method under the covers. That method takes an objectId String as a parameter, but then strips off the version information at the end (i.e. the ";1.0" part of the objectId) and then checks to see if the remaining string is a valid NodeRef. In doing so, it checks it against this pattern (in NodeRef.java):
private static final Pattern nodeRefPattern = Pattern.compile(".+://.+/.+");
If the validation fails, you get a CMISInvalidArgumentException, with a message that xxxxx "is not an object ID".
So, to make a long story short, when I call the web script using a parameter for the objectId like this:
29ea5a16-12a8-497d-aad3-f43969e8a672;1.0
I get the CMIS exception. But, if I call the method with an objectId parameter that looks like this:
workspace://SpacesStore/29ea5a16-12a8-497d-aad3-f43969e8a672;1.0
... then, the "CMIS" lookup succeeds and I get my desired NodeRef back. Of course, all that the CMIS services are doing under the covers is stripping off the ";1.0" from the object ID, treating it as a NodeRef string, and doing the lookup using that.
In other words, you can't do it the right way in 4.2. The best thing to do is as #Gagravarr says and tweak your own objectId string to turn it into a NodeRef. Hopefully it's fixed in 5.x.

JSON + SOAP - Is DataContract necessary?

Here's my problem.
I'm using SOAP to retrieve information from a third-party web service.
Response time is too high, so I was planning on using JSON instead, at least in a couple of methods.
For this I'm using DataContractJsonSerializer, but I seem to be having some trouble.
For example, in SOAP there's a method called getAvailablePublic with returns an object of type getAvailablePublicResponse.
There's an equivalent for this method in JSON, which also returns a an object of type getAvailablePublicResponse.
In order to deserialize the information I needed to create a couple of data contracts, and here are my concerns:
Do I really need to create a DataContract? Why can't I use getAvailablePublicResponse object from asmx?
The problem is that if I create a DataContract, I need to use a different name other than getAvailablePublicResponse, as I would have two objects with the same name (the one created by me, and the one from SOAP), and this would require making several changes in my solution.
Hope this makes sense.
Thanks.
Can you post your client code that is making the call to the web service? I don't know what you are using now, but I'm a fan of RestSharp for making remote calls and serializing JSON to C# classes. Something like this:
RestClient client = new RestClient("http://some.domain.com/someservice?someparam=yes");
var results = client.Execute<MyGreatDTOClass>(new RestRequest(Method.GET));

Json Dynamic views spring MVC

I am kind of new to spring MVC
and I wanted to use JasonViews (Jackson) for dynamic JSON per request and I didn't want to change my controllers too much .. so #marty here gave me a great solution in his blog
http://martypitt.wordpress.com/2012/11/05/custom-json-views-with-spring-mvc-and-jackson/
The problem is that I need control over the HTTP status codes,so my controllers are returning types of HttpResponse{T} and not List{T} how can I customize the code in order to support parsing of types like HttpResponse{List{Book}}?
If not possible, can I control the Http status code without the HttpResponse?
I may need to see an example of your code to really understand what you are asking, but this might point you in the right direction:
Take #marty's code and try extending HttpEntityMethodProcessor with it.
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.htmlS
Then, you need to make your method signatures look like
public ResponseEntity<MyType> getMyTypeWithControlOverResponseEntity(...) {...}
You can find more info on this signature type at:
http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-httpentity
Let me know if this is not the right direction you were trying to go or need more help. =)

Custom SOAP response of ASMX service

I'm trying to implement a custom SOAP response of the legacy web service.
At the moment it has the following format:
<ServiceResponse>
<ServiceResult>some return value</ServiceResult>
</ServiceResponse>
I need to add string value like this:
<ServiceResponse>NEW VALUE
<ServiceResult>some return value</ServiceResult>
</ServiceResponse>
I'm not sure if it is a good idea at all? Is this SOAP xml valid? If yes, how it can be accomplished?
Any suggestion or idea would be appreciated
That xml isn't valid, in a node you can't have both text and a child node like you have there.
If you're writing your webservice in .NET I would advise you construct a Serializable class that represents the data structure that you want to return, when you create your webservice it will automatically get converted into a valid soap data structure. You will also be able to see the definition of your response when you browse the WSDL at Service.asmx?wsdl.
If you'd like some more info on SOAP checkout the specification at w3.org
Edit: Removed false claim as pointed out by marc_s

Resources