We have some already developed REST APIs in SpringBoot.
Now we want to prepend some text (version of API eg /v1/) to all the #RequestMapping.
Is there any way of doing this except prepending /v1/ to every #RequestMapping
example: Current RequestMapping /employess and /cars/1/driver
Need to build like this /v1/employess and /v1/cars/1/driver
You can use such property in your application.properties file:
server.servlet.contextPath=/v1
or you can have a base controller class and extend it with all your controller classes
#RestController
#RequestMapping(value = "${rest.api.version}")
public class MyAbstractController {
}
and store rest.api.version in your application.properties file.
You could do it in at least 2 ways.
Option 1: extend AbstractAnnotationConfigDispatcherServletInitializer as below:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected String[] getServletMappings() {
return new String[] { "/v1/*" };
}
}
Option 2: add a request mapping on class level on the controllers you want the version prepended as below
#RestController
#RequestMapping("/v1")
public class Controller {
}
I would go for option 1.
If you want to append every request with "/v1", You can do so by using #RequestMapping annotation at the class level, in this way all the incoming calls(which has "/v1" in it) will land in your controller
#RestController
#RequestMapping("/v1")
public class YourController {
}
Related
I'm trying to write REST server, using this video example (careful, russian speech).
In the example, when lecturer writes #RequestMapping above controller class, class becomes in use. But in my case, controller class "is never used", and when I started tomcat server with my controller and going on page http://localhost:8000/app/remind/get , I get this error: No mapping for GET /app/remind/get
This is my controller code:
#Controller
#RequestMapping("/reminder")
public class ReminderController {
#RequestMapping(value = "/get", method = RequestMethod.GET)
#ResponseBody
public String getReminder(){
return "my reminder";
}
}
And this is my WebConfig.java
#Configuration
#EnableWebMvc
#ComponentScan("com.fillooow.remindme.server")
public class WebConfig extends WebMvcConfigurerAdapter {
}
So, can you explain, why my class "is never used" and what am I missing?
EDIT
My problem was wrong context in configuration file ("/" instead of "/app")
Suggestion: try #GetMapping; be sure you're using the correct URL:
#Controller
#RequestMapping("/reminder")
public class ReminderController {
#GetMapping(value = "/get")
#ResponseBody
public String getReminder(){
return "my reminder";
}
}
... and ...
http://localhost:8000/app/reminder/get
ALSO: I'm not sure about your context root ("app") or your port ("8000" vs. "8080").
POSSIBLE ALTERNATIVE:
http://localhost:8080/reminder/get
ADDITIONAL SUGGESTION: Enable debugging
logging.level.org.springframework=DEBUG
Try the endpoint like as below
http://localhost:8000/reminder/get
I am using #RepositoryResource annotation on my Reposioptory interface with this code:
#RepositoryRestResource(collectionResourceRel = "rest", path = "rest")
public interface HoliDayRepository extends CrudRepository<HoliDayEntity, Integer> {
HoliDayEntity findOne(Integer id);
}
and i have alsoe added RequestMapping("rest) in controller class
#RestController
#RequestMapping("/rest")
public class DayController {}
but when i start spring boot application and try this link :http://localhost:8080/rest i got 404 error also while building application i have ResourceNotFoumd exceptions how should i manage these errors?
with spring boot you don't need to create your own controller; also make sure your web application mapping is different to the one you use for spring data, for example you can set in application.properties spring.data.rest.base-path: /api
Have a look at this example:
public interface PersonRepository extends JpaRepository<Person, UUID> {
List<Person> findByAddress(String address);
}
with just this code you should able to access spring data repositories here: http://localhost:8080/api and the person endpoint here http://localhost:8080/api/person
Have a look at this tutorial: https://spring.io/guides/tutorials/react-and-spring-data-rest/ or this example: https://github.com/Paizo/SpringBootCamelStreamsExample
You need a method which should be called when you hit your endpoint.
try below and also check spring example:
https://spring.io/guides/tutorials/bookmarks/
#Autowired
private HoliDayRepository holiDayRepository; //your repository to execute the query
#GetMapping(value = "/{id}")//you can use #RequestMapping(method = RequestMethod.GET, value = "/{holida}")
public ResponseEntity<HoliDayEntity > getHolidayById(#PathVariable("id") Integer id) {
HoliDayEntity holiDayEntityresponse = productOperations.getProductById(id);
return new ResponseEntity<>(holiDayEntityresponse , HttpStatus.OK);
}
EDIT:
As pointed by Gimby, this is not applicable when #RepositoryRestResource is used. Both the code and the tutorial attached are refering to creating new REST service by creating the controller
I have following issue: we've been developing website using Spring tools 3.8.3 and one of the option is to allow users to reset their passwords. In order to do that they need to specify their email address and validate captcha. When these steps are completed data is sent to ResetPassword controller which does all necessary checks and work. Controller has following address:
website.com/path/resetPassword/
And has following structure where it extends abstract controller template to define the input and output beans:
#RequestMapping(path="website.com/path/resetPassword/",
consumes = "application/JSON",
produces = "application/JSON",
method = "POST")
public class ResetPassController extends ControllerTemplate<ResetPassCaptchaBean, ResponseBean>{
// Autowired field declaration
// Couple of methods calling services
}
The bean also has only two fields - email and captcha accordingly. Captcha field uses annotation to check if either it's valid or not:
public class ResetPassCaptchaBean extends ResetPassBean {
#CaptchaValid
private String captcha;
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
public String getCaptcha() {
return captcha;
}
}
public class ResetPassBean {
private String email;
public void setEmail(String email) {
this.email= email;
}
public String getCaptcha() {
return email;
}
}
Now we are adding mobile API and it's necessary to do the same procedure but without using captcha validation. Therefore we're simply using the bean without captcha field. Since captcha is validated using the annotation in the bean it's completely not used in the controller itself and therefore we'd like to have the same controller both for handling requests from web site and from mobile API.
I understand that it's possible to create two different controllers and move all the implementation to service layer (read other class) but then there still would be two identical classes with only one line difference
public class ResetPassController extends ControllerTemplate<ResetPassCaptchaBean, ResponseBean>{
//Autowiring same stuff
//Calling same methods
}
and
public class MobileResetPassController extends ControllerTemplate<ResetPassBean, ResponseBean>{
//Autowiring stuff
//Calling same methods
}
So the question is: leave it with two identical controllers or is there other solution?
Thanks!
How to add routes dynamically in resteasy (or jax-rs implementation).Right now, I add the routes with #Path annotation.
Example
#Controller
#Path("/api")
public class Controller {
#GET
#Path("/route1")
public String route1() {
return "Welcome ";
}
}
But, I need to add more routes at runtime based on some user input. My aim is create rest apis at runtime based on user inputs.
You need to write your path as a regular expression. Here is the tutorial.
So it shall look like this:
#Controller
#Path("/api")
public class Controller {
#GET
#Path("/{subPath}")
public String subPath() {
return "Welcome ";
}
}
I want to have two resources at URLs: /apps and /apps/runs.
So, I created resources as shown below. I use Spring for object injection. When I use this way, I am getting the 404 error for HTTP get requests on /apps/runs. Am I doing some thing wrong?
Here is my code:
#Scope("prototype")
#Path("/apps")
public class ManufacturersResource {
#GET
#Produces("application/xml")
public List<Applications> getApplications() {
return apps.findAll();
}
}
#Scope("prototype")
#Path("/apps/runs")
public class ManufacturersResource {
#GET
#Produces("application/xml")
public List<ApplicationInstances> getApplicationInstances() {
return appInstances.findAll();
}
}
Jersey won't allow you to have two files share a common prefix, if one is using the prefix as an entire resource url.
So you can move both methods inside the same file, or have /apps be something else like /apps/list