Log url to Spring controller from inside it - java

Suppose you have a Spring MVC controller, something like this
#Controller
public class RestController {
#GetMapping(value = "/test")
public #ResponseBody Test getTestData(...) {
// console log path to controller: http://localhost:80/app/test
return testData;
}
}
Is it possible to log/print from inside the controller the url to it? In the example above the output would be something like https://localhost:80/app/test
Using .getRequestUrl from the servlet is not behaving correctly.

You can inject UriComponentsBuilder as parameter then use the method toUriString(). From the documentation, it is used to build a relative URI from the current request’s, this should work as your are expected Doc.
#Controller
public class RestController {
...
#GetMapping(value = "/test")
public #ResponseBody Test getTestData(UriComponentsBuilder ucb, ...) {
LOGGER.debug(ucb.toUriString());
// console log path to controller: http://localhost:80/app/test
return testData;
}
...
}

Related

Class with #RequestMapping is never used

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

Exception using Spring Data JPA and QueryDsl via REST Controller

I'm trying to implement a controller method similar to how is documented in the latest Gosling release train of Spring Data that supports QueryDsl. I've implemented the controller as shown in the example in the docs at http://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type-safe. Everything compiles and when I start the application (using Spring Boot 1.2.5.RELEASE), everything starts fine.
However, when I try to call my rest endpoint, I always get the following exception:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mysema.query.types.Predicate]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)
My guess is that the QuerydslPredicateArgumentResolver is not being applied to the request, and thus the exception. But I see that the QuerydslPredicateArgumentResolver is registered as a bean when I query the Spring Boot manage endpoint /manage/beans. I have also ensured that #EnableSpringDataWebSupport is on my #Configuration class to no effect.
I have the controller annotated with #BasePathAwareController, since I'm using this with Spring Data REST and I want the methods to be under a similar path as the ones that Spring Data REST exposes. I also tried using #RepositoryRestController, but that didn't seem to matter. However, when using #RestController and putting it under a path that was different then the base path that Spring Data REST is using, things worked. So the question is, should it work?
The entire controller right now is:
#RestController
#RequestMapping(value = "/query")
public class AvailController
{
private final AvailRepository repo;
#Autowired
public AvailController(AvailRepository repository)
{
this.repo = repository;
}
#RequestMapping(value = "/avails", method = GET)
public #ResponseBody Page<Avail> getAvails(Model model,
#QuerydslPredicate(root = Avail.class) Predicate predicate,
Pageable pageable,
#RequestParam MultiValueMap<String, String> parameters)
{
return repo.findAll(predicate, pageable);
}
}
I had the same problem with instantiation of Predicate. In the example:
#Controller
#RequiredArgsConstructor(onConstructor = #__(#Autowired) )
class UserController {
private final UserRepository repository;
#RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model, //
#QuerydslPredicate(root = User.class) Predicate predicate, //
#PageableDefault(sort = { "lastname", "firstname" }) Pageable pageable, //
#RequestParam MultiValueMap<String, String> parameters) {
(...)
(https://github.com/spring-projects/spring-data-examples/blob/master/web/querydsl/src/main/java/example/users/web/UserController.java#L42 ) is using just #Controller and I was using #RepositoryRestController, that seems to be the reason. #RestController also works for me.
I created https://jira.spring.io/browse/DATAREST-838
I also had this issue when trying to implement a custom controller that mimics the returned value as Spring Data REST. I wanted to inject QuerydslPredicate to the controller method and got the annoying 'BeanInstantiationException'.
I found a work around for this by adding the following configuration file to my application:
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE )
public class MvcConfig extends WebMvcConfigurerAdapter {
#Autowired
#Qualifier("repositoryExporterHandlerAdapter")
RequestMappingHandlerAdapter repositoryExporterHandlerAdapter;
#Override
public void addArgumentResolvers(
List<HandlerMethodArgumentResolver> argumentResolvers) {
List<HandlerMethodArgumentResolver> customArgumentResolvers = repositoryExporterHandlerAdapter.getCustomArgumentResolvers();
argumentResolvers.addAll(customArgumentResolvers);
}
}
See here for reference: https://jira.spring.io/browse/DATAREST-657

Forward request to another controller in Spring MVC

I'd like to know if there is a way I can forward a request from one controller to another without actually changing the URL in the browser.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true)
//forward to another controller but keep the url in the browser as /myurl
}
examples that I found online were redirecting to another url which was causing other controllers to handle that. I don't want to change the URL.
Try to return a String instead of ModelAndView, and the String being the forward url.
#RequestMapping({"/myurl"})
public String handleMyURL(Model model) {
if(somecondition == true)
return "forward:/forwardURL";
}
Instead of forwarding, you may just call the controller method directly after getting a reference to it via autowiring. Controllers are normal spring beans:
#Controller
public class MainController {
#Autowired OtherController otherController;
#RequestMapping("/myurl")
public String handleMyURL(Model model) {
otherController.doStuff();
return ...;
}
}
#Controller
public class OtherController {
#RequestMapping("/doStuff")
public String doStuff(Model model) {
...
}
}
As far as I know "forward" of a request will be done internally by the servlet, so there will not be a second request and hence the URL should remain the same. Try using the following code.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true){
return new ModelAndView("forward:/targetURL");
}
}

Handle same URL in different controllers based on parameters - Spring MVC

I have a controller which handles a specific URL
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL()
Instead I want to have 2 separate controllers that let me handle this same /myurl based on the parameters passed to it.
If URL is
/myurl?a=1
goto controller A, otherwise use controller B.
Is there a way to do that?
I found this similar question Spring MVC - Request mapping, two urls with two different parameters
where someone has mentioned "use one method in a misc controller that dispatches to the different controllers (which are injected) depending on the request param." , how do I implement that?
Controller 1
#RequestMapping(value= {"/myurl"}, params = { "a" })
public ModelAndView handleMyURL()
Controller 2
#RequestMapping(value= {"/myurl"}, params = { "b" })
public ModelAndView handleMyURL()
Take a look at chapter 4 of this post for more detail
#Controller
#RequestMapping(value= {"/myurl"})
public TestController{
#Autoware
private TestAController testAController;
#Autoware
private TestBController testBController;
public void myMethod(String a){
if(a.equals("1"){
testAController.foo(a);
}else{
testBController.foo(a);
}
}
}
#Controller
#RequestMapping(value= {"/myurl1"})
public class TestAController{
public void foo(String a){
...
}
}
#Controller
#RequestMapping(value= {"/myurl2"})
public class TestBController{
public void foo(String a){
...
}
}

#Path equivalent in spring-boot

Say I have controller with a method defined like this:
#RestController
#RequestMapping("/{user-id}/foo")
public class FooController {
#RequestMapping("bar")
public BarController someBarLogic() {
//
}
}
Is it possible to go further than {user-id}/foo/bar without specifying the whole root-path ? (Is there a way to relativize the path like #Path annotation in Jersey or an equivalent annotation in Spring-Boot ?)
It looks like you're looking for ant-style wildcards in path patterns. Have a look here:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-patterns
Accordingly you can define a RequestMapping like this
#RestController
#RequestMapping("/foo")
public class DemoController {
#RequestMapping(value = "/bar/**", method = RequestMethod.GET)
public String getDemo() {
return "Hello world!";
}
}
which will match /foo/bar/baz.
Ok, another example based on your comment below:
#RestController
public class DemoController {
#RequestMapping(value = "/**/baz/**", method = RequestMethod.GET)
public String getDemo() {
return "Hello world!";
}
}
This will match the same url as above, and also /foo/bar/baz/bar/foo

Categories