Almost all APIs are dealing with different release versions. Often you see this kind of versioning:
But I haven't found a source discribing how to organize them in a Spring stack. I guess having a /v1
prefix like @RequestMapping("/v1/questions")
on every Controller is not the best approach.
Imagine there is a @Service
layer of just the current release (in our case V2).
Our Service should handle the requests of V1 and V2. The only change was that V2 added a new field on a question entity (that means a V1 Question could be easily converted to a V2 question).
Now the Questions are:
- how to organize the different
~.web.* @Controller
from a java package point of view? - how to annotate the different
~.web.* @Controller
that they are aware of their versions? In manner of theRequestMapping
? Or is it possible to configure them with a context:component-scan in a V1 java package? - how to organize the converter? Where to put them, how to name them? Smth. like QuestionsV1ToV2 Controller?
- Is there a DTO layer requered? Because our Domain has to deal with many versions as the same time?
An example could look like this (i added the packages everywhere):
// on V1 Question look like this:
public class project.domain.Question
{
private String question;
}
// on v2 Question looks like this:
public class project.domain.Question
{
private String question;
private Date creationDate;
}
@Service
public class project.service.QuestionService
{
public long create(Question q) {...};
public Question read(long id) {...};
public void remove(long id) {...};
public void update(Question qd) {...};
}
@Controller
@RequestMapping("/v2/question")
public class project.web.v2.QuestionController
{
@Autowired
project.service.QuestionService questionService;
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public long create(Question q)
{
return questionService.create(q);
}
}
@Controller
@RequestMapping("/v1/question")
public class project.web.v1.QuestionController
{
@Autowired
project.service.QuestionService questionService;
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public long create(Question q)
{
// this will not work, because the v1 haven't had the 'creationDate' field.
return questionService.create(q);
}
}