RequestMapping not working in spring - java

I have simple controler:
public class Controller {
#RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
public void test(HttpServletResponse response) throws IOException {
System.out.println("HELLO WORLD");
}
}
When I start jetty server and go to localhost:8080/test I am not getting output System.out.println("HELLO WORLD");
I have nothing about this controler in web.xml.
Where is a problem? How can I get my controler?

Annotate your class with #Controller
like
#Controller
public class AppController {
#RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
public void test(HttpServletResponse response) throws IOException {
System.out.println("HELLO WORLD");
}
}
Check for base package registred under Component Scanning
What is Component Scan?
Component scanning with <context:component-scan base-package="<<your classes base package>>" /> in xml configuration and #ComponentScan in annotation based configuration is telling spring that it should search the class path for all the classes under<> and look at each class to see if it has a #Controller, or #Repository, or #Service, or #Component and if it does then Spring will register the class with the bean factory

#Controller
#RequestMapping(value="/")
public class AppController {
#RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
public void test(HttpServletResponse response) throws IOException {
System.out.println("HELLO WORLD");
}
}
add request mapping to your controller level then it works.

Related

#RequestMapping java.lang.AssertionError: Status Expected :200 Actual :404

Assertion error using #RequestMapping annotation outside of the class
I am getting this error message:
java.lang.AssertionError: Status
Expected :200
Actual :404
My Controller is like this
#Service
#RestController
#RequestMapping("/execute/files")
#ResponseBody
public class ControllerFiles {
#Autowired
#Qualifier("fileRunner")
ProcessRunnerInterface processRunnerInterfaceFiles;
public InputState executeRestFile(#RequestParam String name) throws ExecutionFailedException, URISyntaxException {
///code///
}
public List<String>....{
///code///
}
}
My Test
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class ControllerFilesTest {
#Autowired
private MockMvc mockMvc;
#Autowired
ControllerFiles controllerFiles;
#Test
public void testSpringMvcGetFiles() throws Exception {
this.mockMvc.perform(get("/execute/files").param("name", "Spring Community Files"))
.andDo(print()).andExpect(status().isOk());
}
}
But when I have my code like this the test work fine!
#Service
#RestController
public class ControllerFiles {
#Autowired
#Qualifier("fileRunner")
ProcessRunnerInterface processRunnerInterfaceFiles;
#RequestMapping("/execute/files")
#ResponseBody
public InputState executeRestFile(#RequestParam String name) throws ExecutionFailedException, URISyntaxException {
///code///
}
public List<String>....{
///code///
}
}
Any ideas what is going wrong?
The methods in your RestController need to be marked as #RequestMapping if you want them to be picked up as request resources. If you want to keep the base request mapping at the controller level as in your first RestController then you need to do the following:
#RestController
#RequestMapping("my/path")
public class MyController {
#RequestMapping("/")
public InputState myMethod() {
...
}
}
As it is said in documentation:
In the above example, #RequestMapping is used in a number of places. The first usage is on the type (class) level, which indicates that all handler methods in this controller are relative to the /appointments path.
So the class level #RequestMapping is only indicating relativnes. It is not declare actual resource paths based on public methods only. So you need to annotate your method like this:
#GetMapping
public InputState executeRestFile(#RequestParam String name) throws Exception {
// omited
}
Or like this:
#RequestMapping(method = RequestMethod.GET)
public InputState executeRestFile(#RequestParam String name) throws Exception {
// omited
}

How to ignore level #RequestMapping() and direct call method level #RequestMapping()?

How to do I ignore the class level #RequestMapping("/home") and directly call the method level #RequestMapping("/users") in Spring?
#Controller
#RequestMapping("/home")
#RequestMapping("/method1")
public void method1(){
...
}
#RequestMapping("/users")
public void listUsers(){
...
}
I want to call http://localhost:8080/users to invoke listUsers() method.
You cannot bypass requestmapping defined at class level. for If so why you want a class level mapping then... you can instead do something like this in the method level request mapping
#Controller
#RequestMapping("/home/method1")
public void method1(){
...
}
#RequestMapping("/users")
public void listUsers(){
...
}
In that case you may try this...
#Controller
#RequestMapping({ "/home", "/users" })
#RequestMapping("/method1")
public void method1(){
...
}
#RequestMapping(method="RequestMethod.GET")
public void listUsers(){
...
}
Change #RequestMapping("/users") for #RequestMapping(method=RequestMethod.GET)
From my understanding, what you expect is a class-level RequestMapping. The method-level RequestMapping should be under the path of class-level's.
I'll give you some examples:
#RestController
#RequestMapping("/home")
public class HomeController {
// Full path of following endpoint: /home/parents.
#RequestMapping(value = "/parents", method = RequestMethod.GET)
public ResponseEntity<List<People>> getParents() {
return ResponseEntity.ok(methodToGetParents());
}
For the path of "users" you should do it in another class (controller):
#RestController
#RequestMapping("/users")
public class UsersController {
// Full path of following endpoint: /users.
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<People>> getUsers() {
return ResponseEntity.ok(methodToGetUsers());
}

Error Contoller Howto : Spring-boot + Spring-Data-Rest

Spring Boot with Spring Data Rest - how to use a custom error handler.
Created an error controller I tried to skip the default error handler by using following code.
Why it is not working!
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration(exclude = { BasicErrorController.class })
#EnableMetrics
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
.....................
.....................
and error controller as below
#Component
#RestController
#RequestMapping(value = "/error")
public class CustomErrorController extends BasicErrorController {
public CustomErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes);
// TODO Auto-generated constructor stub
}
private static final String PATH = "/error";
#RequestMapping(value = PATH)
public String error() {
return "Error handling";
}
#Override
public String getErrorPath() {
return PATH;
}
}
I haven't used this kind of solution, but, it seems that your request mapping is not right.
The request mapping of CustomErrorController is '/error', and in
#RequestMapping(value = PATH)
public String error() {
return "Error handling";
}
There is a another '/error' in request mapping path. Then the url for this error handler is '/error/error'.
You have #RequestMapping("/error") annotation on your controller and second #RequestMapping("/error") on your method. This results in /error/error mapping, not the /error mapping as you specified in getErrorPath() method and maybe in your configuration (application.properties, server.path.error).

Spring MVC #RequestMapping ... using method name as action value?

Say I have this:
#RequestMapping(value="/hello")
public ModelAndView hello(Model model){
System.out.println("HelloWorldAction.sayHello");
return null;
}
Is it possible to skip the value="hello" part, and just have the #RequestMapping annotation and have spring use the method name as the value, similar to this:
#RequestMapping
public ModelAndView hello(Model model){
System.out.println("HelloWorldAction.sayHello");
return null;
}
Thanks!
===================EDIT=====================
Tried this but not working:
#Controller
#RequestMapping(value="admin", method=RequestMethod.GET)
public class AdminController {
#RequestMapping
public ResponseEntity<String> hello() {
System.out.println("hellooooooo");
}
}
Try to add "/*" on the request mapping value of the class
#Controller
#RequestMapping(value="admin/*")
public class AdminController {
#RequestMapping
public ResponseEntity<String> hello() {
System.out.println("hellooooooo");
}
}
You can go the page http://localhost:8080/website/admin/hello
It should work if you move the RequestMethod on your specific method:
#Controller
#RequestMapping(value="admin")
public class AdminController {
#RequestMapping(method=RequestMethod.GET)
public ResponseEntity<String> hello() {
System.out.println("hellooooooo");
}
}
and access it through http://hostname:port/admin/hello
Have a look here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping
Good luck

How to unit test a Spring MVC annotated controller?

I am following a Spring 2.5 tutorial and trying, at the same time, updating the code/setup to Spring 3.0.
In Spring 2.5 I had the HelloController (for reference):
public class HelloController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("Returning hello view");
return new ModelAndView("hello.jsp");
}
}
And a JUnit test for the HelloController (for reference):
public class HelloControllerTests extends TestCase {
public void testHandleRequestView() throws Exception{
HelloController controller = new HelloController();
ModelAndView modelAndView = controller.handleRequest(null, null);
assertEquals("hello", modelAndView.getViewName());
}
}
But now I updated the controller to Spring 3.0, and it now uses annotations (I also added a message):
#Controller
public class HelloController {
protected final Log logger = LogFactory.getLog(getClass());
#RequestMapping("/hello")
public ModelAndView handleRequest() {
logger.info("Returning hello view");
return new ModelAndView("hello", "message", "THIS IS A MESSAGE");
}
}
Knowing that I am using JUnit 4.9, can some one explain me how to unit test this last controller?
One advantage of annotation-based Spring MVC is that they can be tested in a straightforward manner, like so:
import org.junit.Test;
import org.junit.Assert;
import org.springframework.web.servlet.ModelAndView;
public class HelloControllerTest {
#Test
public void testHelloController() {
HelloController c= new HelloController();
ModelAndView mav= c.handleRequest();
Assert.assertEquals("hello", mav.getViewName());
...
}
}
Is there any problem with this approach?
For more advanced integration testing, there is a reference in Spring documentation to the org.springframework.mock.web.
With mvc:annotation-driven you have to have 2 steps: first you resolve the request to handler using HandlerMapping, then you can execute the method using that handler via HandlerAdapter. Something like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("yourContext.xml")
public class ControllerTest {
#Autowired
private RequestMappingHandlerAdapter handlerAdapter;
#Autowired
private RequestMappingHandlerMapping handlerMapping;
#Test
public void testController() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
// request init here
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);
// modelAndView and/or response asserts here
}
}
This works with Spring 3.1, but I guess some variant of this must exist for every version. Looking at the Spring 3.0 code, I'd say DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter should do the trick.
You can also look into other web testing frameworks that are independent of Spring like HtmlUnit, or Selenium. You won't find any more robust strategy with JUnit alone other than what Sasha has described, except you should definitely assert the model.

Categories

Resources