10

I have a simple @Controller within a spring-mvc environment. This is the Controller:

@Controller
public class MessageController {
    private static Logger LOG = LoggerFactory
            .getLogger(MessageController.class);

    @RequestMapping(value = "/messages/{userId}/{messageId}", method = RequestMethod.GET)
    public Message getMessage(@PathVariable("userId") String uid,
            @PathVariable("messageId") String msgid) {
        LOG.trace("GET /message/{}/{}", uid, msgid);
        return new Message();
    }
}

This is the servlet-mapping in web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
             http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>Messaging Service</display-name>

    <servlet>
        <servlet-name>messaging</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>messaging</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

When I start the app via jetty and run a request against /messages/abc/def, I get the following log:

INFO: Mapped "{[/messages/{userId}/{messageId}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public ....Message ....MessageController.getMessage(java.lang.String,java.lang.String)
WARNING: No mapping found for HTTP request with URI [/messages/abc/messages/abc/def] in DispatcherServlet with name 'messaging'

What did I do wrong here? The request definitely only contains /messages/abc/def, why is this internally translated to /messages/abc/messages/abc/def?

Ashot Karakhanyan
  • 2,804
  • 3
  • 23
  • 28
Rainer Jung
  • 636
  • 7
  • 23

6 Answers6

19

I guess it's related to default view name resolution.

If you want a value returned by your handler method to be encoded as response body (in JSON, XML, etc), you need to annoate the method with @ResponseBody, or annotate the whole controller with @RestController (in Spring 4.x).

Otherwise, Spring tries to render a view with your return as model attribute. And since you didn't provide a name of a view to render, Spring tries to deduce it from request URL.

axtavt
  • 239,438
  • 41
  • 511
  • 482
2

In addition to @axtvat, pay attention to the differences between @Cotroller and @RestController, @RestController fixed the issue for me. https://dzone.com/articles/spring-framework-restcontroller-vs-controller

hagai
  • 424
  • 1
  • 7
  • 13
0

Do you have a file named messaging-servlet.xml that declares the web application context? By default because you have named the DispatcherServlet messaging, Spring will try to locate that file.

geoand
  • 60,071
  • 24
  • 172
  • 190
  • Of course, I do have this file. It's just simple containing: – Rainer Jung Mar 15 '14 at 08:59
  • Then you probably need to add @ResponseBody to getMessage to instruct Spring to return the value as is. This however means that you have to have some sort of message converter such as MappingJackson2HttpMessageConverter (for Json using the Jackson 2 library) – geoand Mar 15 '14 at 09:03
0

I had the same problem.

I fixed it by replacing @Controller with @RestController.

Agustí Sánchez
  • 10,455
  • 2
  • 34
  • 25
0

None of the above solved the problem for me. Using @RestController did not redirect but just printed the correct url (the url without the duplication) on the screen. I found this other solution that worked. What is the difference between response.sendRedirect() and request.getRequestDispatcher().forward(request,response)

0

If your RequestMapping value happens to reference properties [which I admit the OP did not]..

ex:

@RequestMapping(value = "${reference.to.an.application.properties.value}", method = RequestMethod.GET)

.. then make sure to consider how the property value is resolved; especially if there might be any overriding happening in resolution.

classpath root application.properties ex:

reference.to.an.application.properties: /some/path/
reference.to.an.application.properties.value: ${reference.to.an.application.properties}/{ID}

If reference.to.an.application.properties is also defined somewhere else [additionally], that is overriding the same-named property key in properties file (because of Spring properties precedence); somewhere else (in my case, OpenShift properties [which are passed by OpenShift as environment variables to Spring]) for ex:

reference.to.an.application.properties: /some/path/{ID}

Then (by overriding precedence) reference.to.an.application.properties.value would resolve to /some/path/{ID}/{ID} (thus the duplicated URL path), and not /some/path/{ID}

cellepo
  • 4,001
  • 2
  • 38
  • 57