Best way to handle JAX-RS REST API URI versioning - java

I did my search first in stackoverflow & I was not able to find out any answers related to my question. All I can find was questions related to REST uri design.
My question in on the backend side.
Suppose we have two different version of REST uri's
http://api.abc.com/rest/v1/products
http://api.abc.com/rest/v2/products
What is the best approach to follow on the backend side (server side code) for proper routing, manageability & reuse of the existing classes across these two set of api's based on version?
I have thought of approach to define resource classes with different #Path annotations for e.g. have a package for v1 & v2 separately & in ProductsResource class of that package, define
package com.abc.api.rest.v1.products;
#Path("/rest/v1/products")
public class ProductsResource {...}
package com.abc.api.rest.v2.products;
#Path("/rest/v2/products")
public class ProductsResource {...}
& then have the implementation logic based on the versions. The problems with this approach is when we are only changing one particular resource api from the set of api's, we have to copy other classes to the v2 package also. Can we avoid it?
How about to write a custom annotation say #Version & have values of the versions it supports? Now whether it is v1 or v2, both request will go to same resource class.
Say for e.g.
package com.abc.api.rest.products;
#Path("/rest/{version: [0-9]+}/products")
#Version(1,2)
public class ProductsResource {...}
UPDATE:
There was a API versioning suggestion by Jarrod to handle version in headers. That's also one way to do it however, I am looking forward for best practices to use when we are following URI based versioning

The problem with putting it in the URL is that the URL is supposed to represent a resource by location. An API Version is not a location and it not part of the identifier of the resource.
Sticking /v2/ in the URL breaks all existing links that came before.
There is one correct way to specify API versioning:
Put it in the mime-type for the Accept: header that you want. Something like Accept: application/myapp.2.0.1+json
Chain of Responsiblity pattern goes well here especially if there will be significant number of API versions that are different enough to have to have their own handler, that way methods don't get out of hand.

This blog post has an example of what is considered the by some to be the correct approach, i.e. not having the version in the URI: http://codebias.blogspot.ca/2014/03/versioning-rest-apis-with-custom-accept.html
In short, it leverages JAX-RS #Consume annotation to associate the request for a particular version to a specific implementation, like:
#Consumes({"application/vnd.blog.v1+xml", "application/vnd.blog.v1+json"})

I was just wondering why not have a subclass of ProductService called
#Path(/v2/ProductService)
ProductServiceV2 extends ProductService {
}
#Path(/v1/ProductService)
class ProductService{
}
and only override whatever is changed in v2. Everything unchanged will work the same as in v1/ProductService.
This defintely leads to more # of classes but is one easier way of coding for only whatever is changing in the new version of api and reverting to the old version without duplicating code.

Related

Is it a bad idea to use #RequestMapping in interface?

I checked out this SO Post which discusses using RequestMapping in interface. Although the post contains ways to achieve this but it does not mention the pros and cons of doing this.
Architecture wise , is this a bad idea to use controller as interface?
What benefit will we achieve in terms of polymorphism for controller?
There is nothing wrong with putting #RequestMapping on the interface. However make sure you have the right reasons to do it. Polymorphism is probably not a good reason, you will not have a different concrete implementation swapped in at runtime or something like that.
On the other hand, for example, Swagger codegen generates interfaces with #RequestMapping and all the annotations on the methods, fields and return types (together with #Api definitions etc.). Your controller then implements this interface. In this case it makes a lot of sense because it is just enforcing you to respect the Swagger / OpenAPI interface definition originally defined in Yaml. There is a nice side-effect that it makes your controller much cleaner. (Clients can also use the same Yaml to generate their own client stubs for their own language frameworks).
If you opt to do this, make sure you use the latest version of the Spring Framework, because there were some bugs which were fixed only very recently, where not all annotations were being inherited.
https://github.com/spring-projects/spring-framework/issues/15682
If you are stuck with an older Spring version, you might need to repeat the same annotations in your controller.
So, the real reason this would make sense is to enforce the interface contract, and separate the interface definition (together with any information pertaining to the interface) from the actual concrete implementation.
While some arguments against this are that
the request mapping is an implementation detail, or
since you only have one active controller implementation, you might as well put it on the implementation,
(others will probably be provided in different answers soon,)
I was recently faced with the same decision to put jax-rs annotations on the interface or the implementation. So, since everything always "depends" on some context, I want to give you an argument for putting the RequestMapping (or e.g. #Path, etc if not using spring) on the interface:
If you are not using HATEOAS or discovering the endpoints via some other means, the endpoint url, http method, etc. are usually fixed and a static part of your backend API. Therefore, you might as well put it on an interface. This was the case for me because I control both the client and the server side.
The controller usually has only one active implementation, so the reason for doing so is not polymorphism. But your implementation usually has a lot more dependencies than the plain interface. So if you export/provide only your interface to clients (e.g. in a seperate jar/java project/...), you only provide things that the clients really require. In my specific case, I delivered the annotated interface so that a client implementation could can it using a Rest-Client-Library and detect the endpoint paths automatically.

How to solve obstacles related to API version

I am having a restfull service and there are more than 20 clients thats is using this service.
#Path("/provider")
public class Provider{
#Path("/simpleprovider")
#GET
public String getProvider(){
return "Simple Provider";
}
}
Now i have decided to introduce version in service, i have google alot, read my articles but i am totally confused how should i do? suppose i change URI for new service like #Path("/provider/v1") than how should i provide support for existing clients ? by considering this thing should i have to provide change on every client whenever api new version comes in action ?
After Googling i found that there are 3 ways to provide versioning
URL versioning
custom request header
content type
but could not find any practical example please help me in this regard
http://stackoverflow.com/questions/389169/best-practices-for-api-versioning
http://www.narwhl.com/2015/03/the-ultimate-solution-to-versioning-rest-apis-content-negotiation/
http://restcookbook.com/Basics/versioning/
http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html
http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/
Any help will be greatly appreciated
Versioning a service can be very tricky and is always a big decision when determining the versioning strategy. Especially if you have people using the service. From my experience here are some things to consider:
Understand and communicate when and if you plan on sun setting versions of your API. The last thing you want to have is a problem where you are having to upkeep 10 different versions of an API.
Understand if a version change is absolutely necessary. A good rule of thumb is if core functionality is changing or if the contract can potentially break someones software that is integrating with your API. Here are some things to consider when determining if you really need to version:
If you are removing fields from a resource.
If you are removing (or updating) a URL (or method).
If an existing endpoint (or method) logic is going to change such that it would require a consumer to re-implement.
Overall, if a change that you make would break someone integrating with your API.
Are you going to require database changes that would not be backwards compatible with your previous version(s)? This is when versioning can get really fun (sarcastically) because now you might have to make your database backwards compatible which, in my experience, can be difficult problem to deal with moving forward.
To answer your question, though, I have found the best way to version to be in the URL. Be very simple and deliberate with your versioning so that it is crystal clear for your integrator. For example:
GET /v1/products/{id} // Version 1
GET /v2/products/{id} // Version 2
** If you decide on URL versioning then my advice is to put do "v" for version and a SINGLE number like 1 or 2. Don't get into versions, sub versions, etc... This will make your API seem like it revs a lot which can cause concern for consumers. Also, keep the version as FAR left of the URL as possible. The idea is that everything to the right of the version is the new versioned resource.
I would AVOID using headers to version your service. You don't want to hide versions from your consumer. Be as transparent and explicit about versioning as you possibly can.
Versioning in the URL allows you to also do some useful routing and things on your web server and proxies as well. You can either version like this in your actual code, for example:
[HttpGet("v1/products")]
public Product GetProduct(string id)
{
return _repository.GetProduct(id);
}
or you can version using your web server by setting up virtual directories (or whatever). Then your code might look something like this instead:
[HttpGet("products")]
public Product GetProduct(string id)
{
return _repository.GetProduct(id);
}
However you decide to version it is very important to think about the pro's and con's of each decision and weigh them because if you are running an API that people are using the bad decisions will catch up to you in a hurry.

SPRING MVC controller annotations vs xml

For new project, I was searching for which framework is to be used. I looked for the updates for existing frameworks.
I found it very intresting about Spring MVS controller, that in the controller itself you can now define which URL you want to hit. The best thing is that you do not need to rewrite url, that kind of feature is also there, i.e., you can give directly the url like:
\users\amit\stores\store1
Earlier I had to write url rewriting for making it this way, and actual url used to be like:
\StoreDetails?user=amit&store=store1
I found it very good. But on second thought, if I compare, if I start putting the urls in controller itself, will not it make a little difficult to maintain after say 1 year, when I have so many modifications done on the project and at times, the url given to Controller turns not related to the name of the Controller.
For example in above example, I might want to search for storedetails, but by url i would be searchin in StoreController etc.
What you guys suggest is good practice, to go with xml or to go with annotation based.
If you guys using the annotation based, do you face any issue?
Thanks & Regards
Amit
Spring MVC implements a lot of predefined conventions. For example if you do not explicitly define #RequestMapping on controller it will map it to url similar to controller name. For example if you controller is named Users it will be automatically mapped to url users. If then you rename your class to Customers it will be automatically mapped to url customers.
The same happens with methods.
The big question is whether you really want this. Typically you do not want your internal changes (including class renaming) directly and automatically affect API your provide.
If you choose to define mappings explicitly try to organize your project using certain convention that will simplify on-going support in future. You can also use public static final Strings in annotations. All URL dependent strings can be stored in one class, for example:
public interface Mapping {
public final static String USERS = "users";
public final static String PERMISSIONS = "permissions";
}
#RequestMapping(Mapping.USERS)
public UserController {
............
}
I would stick with annotations they are very simple to define and its pretty easy to discover the appropriate method from a view using a good IDE. They key is to search the entire project for a given URL string.
So for example, if I had the following jsp.
Store Link
I would just use the IDE's search feature (in Eclipse > File Search) to find /store/products/ which would most likely contain the controller in my search results. If your crafty with IDE search features the annotation mappings are really a non issue.

How to determine JAX-RS resource paths programatically?

Suppose I have a set of JAX-RS locators and sublocators, like the following:
#Path("/users")
public class UserListResource {
#Path("/{id}")
public UserResource getCustomer(#PathParam("id") int id) {
// Find and return user object
}
}
public class UserResource {
#GET
public String get() {...}
}
For example, a UserResource object with the ID 5 would have the path "/users/5". In my system, I have several different resources.
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
As I read your question, you need to build a URI knowing only the resource class and the id parameter.
It can be done using the UriBuilder class as in:
UriBuilder builder=UriBuilder.fromResource(UserListResource.class);
URI uri=builder.path(UserListResource.class,"getCustomer").build(5);
It uses reflection under the hood, so it is not so easy to refactor, but it is all it is available at the moment.
Overall, be aware that something sounds rather strange with the architecture of your application. It's hard to put a finger on, but the pattern of questions you are asking is raising a number of red flags about how you're going about this. Be aware that if you are seeking to create a RESTful API to your application that you may need to stop, take a few steps back, and rethink what you are trying to do.
To your explicit questions…
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
The server knows the path, as that's always supplied by the user and is used to navigate through the collection of resource classes that make up your application. If you need a UriInfo instance for a particular call, you should inject it as part of that specific call:
#GET
public String get(#Context UriInfo info) {...}
Any information required from the outer context (e.g., what the resource's ID is) is best passed in during construction. You can reparse it out of the URL (obtainable from the UriInfo) again, but that's probably the wrong approach.
Otherwise, if you're doing something much more complex then you need to be more specific in your question.
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
How are you going to have the clients be informed? There's normally no mechanism to push messages from the server to the clients, and clients are typically firewalled so that they can't directly host a service.
Theoretically, you could associate (explicitly, by URL) each resource with its own RSS feed to which a client could listen to if they chose. You wouldn't be able to force clients to listen, but you could give them the option to do so. If you go this route, you don't need to know the UriInfo “ahead of time” as the location information will be present at key times (i.e., at resource creation) and afterwards you're just referring to something that you have control over.
But that's just one way to do it and it adds a lot of complexity; you'd only do it if it was critical to your application. It's often simpler to just have clients poll from time to time. (Note that some sorts of modifications are inherently very destructive; particularly altering the ID or deleting the resource. Don't expect things to cope smoothly with those.)
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
Tough. Repeating information in multiple places, provided you draw it consistently from a single source, is a common practice. There's nothing actually wrong with it.
As I understand your question, you want to know the path as the request is coming in but before it hits your resource; are you open to using Servlet Filters?
JAX-RS specific filters are only supported in 2.0
For the record: after I had posted the question, I thought about our architecture a bit more and came to the conclusion that sending URLS is not as useful as I thought. The application has to know some details about the application structure anyway:
Continuing the example above: even if the client did not know the URL pattern for individual users, it must assume that there is a list of users and know its URL; it also has hard-coded knowledge what dialog to display for editing a user etc.
So all in all, attempting to tell the client (most) URLs it needs is not worth the effort. Instead, we decided to go with a custom API definition file which includes data about the resource contents and their URL scheme. This file is used to generate the following:
the server-side resource classes with the correct JAX-RS annotations
a URL scheme specification document for other developers to code against
classes for our own client (including the URL know how, e.g. user with ID 5 has the URL ...), so we don't have to worry about inconsistencies between our client and server.
This approach has the following advantages:
The need for the server to figure out the URLs from the annotations vanishes, as the client can now do that on its own once it receives a notification that includes the object ID.
We don't have to worry about inconsistencies between our client and the server, as all information is drawn from a single source.
We have one source for the API definition under version control which can be used to verify backwards compatibility with older releases.
Note:
I would probably not claim that the resulting API stays "faithful" to the idea of RESTful webservices, but it works for us and the elements that it borrows from "actual" REST architectural style should make the API clearer and easier to learn than a traditional contract-first webservice.

java rest client: jax-rs & automatic type mapping

Here is what I am trying to do:
Create an interface (as an example):
#Path( "/" )
public interface Bubbles {
#Get
#Path( "blowBubble" )
#Produces( "text/plain" )
Bubble blowBubble();
}
Said interface should be deployed as a restful web service. I don't particularly care too much about the server side at this point, I mainly concerned with the client.
What I am looking for is a library where I can:
1) Implement the interface, without the interface knowing the full URL (knowing the server and port is obviously necessary (it is in the interface after all)
2) Automatically map 'Bubble' to json across the wire. No adding JAXB to it, no building type converters, etc automatically
My problem is that the 2 libraries I have used do 1 or the other, but not both :(
The Restlet library does 2 but not 1, CXF does 1 but not 2.
Are there any libraries that do both?
I have submitted bugs for both and the CXF dev's seem adamant that 2 should not be a feature - I don't understand why.
Thanks in advance.
EDIT #1:
To clarify my intent, I would like to use REST as the backing transport mechanism for SOA java. This transport should, IMO be transparent; if you have an annotated service interface to adhere to, then the client and server should not need to know anything about each other. They should operate on the contract. Furthermore, this API should be non-intrusive; example: I find that annotating business Objects\Entities with JAXB IS intrusive (what if I can't modify the source?).
I think the best answer I can provide you is pick the best, most active stack and add your changes to make yourself the needed support. I do not believe there is a major player that meets yours needs.
Restlet can implements the interface only if you use their own annotations (see ClientResource#create). I made my own code to handle jax-rs annotations...
For the second point, I don't know about CXF. We were using Restlet with Jackson which implements jax-rs commons interface (JacksonJsonProvider): MessageBodyWriter, MessageBodyReader. Perhaps, you can register this class to CXF. This may work since Jackson can work without annotations.
actually CXF does both , when you use JAX-RS just annotate your method with
#Produces("application/json")
and you will get json output out of box

Categories