Spring MVC "duplicates" parts of the URL
Asked Answered
C

6

11

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?

Crevice answered 15/3, 2014 at 8:30 Comment(4)
Please, show <servlet-mapping> section of web.xml file.Grethel
I added web.xml to the question.Crevice
Hi, I met this issue. Did you have any solution?Photometry
Yes, see the first Answer, annotate your method with @ResponseBody.Crevice
B
21

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.

Boschvark answered 15/3, 2014 at 8:56 Comment(2)
Annotating with @RestController actually fixed the mapping-problem, though I now still receive a 406 Not AcceptableCrevice
Fixed the 406 by adding jackson-mapper-asl to the dependencies.Crevice
S
3

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

Soporific answered 28/12, 2017 at 20:26 Comment(0)
S
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.

Sutter answered 15/3, 2014 at 8:51 Comment(2)
Of course, I do have this file. It's just simple containing: <context:component-scan base-package="o.r.s.messaging"/> <mvc:annotation-driven />Crevice
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)Sutter
P
0

I had the same problem.

I fixed it by replacing @Controller with @RestController.

Predation answered 25/3, 2019 at 10:58 Comment(0)
S
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)

Syncope answered 31/3, 2022 at 8:54 Comment(0)
S
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}

Sow answered 8/6, 2023 at 19:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.