Spring boot embedded tomcat behaves differently to standalone - spring

I have a Spring boot application that exposes a REST API via Spring MVC.
When I run my application locally using the embedded tomcat I can access resources with a trailing slash on the end - e.g POST /resource/
However, when I deploy the war to a standalone tomcat instance, I get a 404 if I include the trailing slash on the URL, but a success without the trailing slash - e.g POST /resource.
The embedded tomcat works with or without the trailing slash.
My request mapping is
#RequestMapping(value = "/resource", method = RequestMethod.POST)
I've tried all sorts of configuration options including
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
matcher.setUseTrailingSlashMatch(true);
}
The only difference I can see is the embedded tomcat is v8 and the standalone is v7. Both running the exact same sourcecode but behaving differently.
Can anyone advise on how to correct this issue?
Thanks

I was able to resolve the issue. For anyone else finding this post...
For some reason, Tomcat 7 was trying to map requests with a trailing slash to a welcome file (index.jsp). It also does not recognise the endpoint if the request contains a trailing slash unless you specifically set a request mapping for "/" despite the setUseTrailingSlashMatch match to true.
This behavior was not mirrored in my embedded tomcat (v8).
I resolved the issue by removing the welcome files from the web.xml and updating my request mapping to:
#RequestMapping(value = {"/resource","/resource/"}, method = RequestMethod.POST)

Related

Why is plus(+) decoded to space ( ) in url path with springboot rest controller?

When calling GET http://localhost:8080/things/ZhaD2lk27XQPRJtwrABltd+UTWXcbnY%2FTrpxGP7VDVo= my Spring Boot application RestController with a request handler like this:
#RequestMapping("/things/{thingId}")
public ResponseEntity<Thing> getThing(
#PathVariable String thingId) {
System.out.println("thingId=" + thingId);
...
results in the following being printed ZhaD2lk27XQPRJtwrABltd UTWXcbnY/TrpxGP7VDVo= instead of what I would have expected ZhaD2lk27XQPRJtwrABltd+UTWXcbnY/TrpxGP7VDVo=.
As you can see, the plus is being turned into a space. This should not happen with the path part, only the query part. This is why the Spring UriComponentsBuilder.build().encode() I'm using to build the URL doesn't turn the plus into %2B.
I needed to tweak the application already to get the encoded slash (/) to work. See REST Endpoint unreachable if ID in URL contains %2F for details.
I'm using SpringBoot 1.4.4.RELEASE which uses Tomcat embed 8.5.11.
I have tried calling the service from Spring RestTemplate, Postman and Chrome. Same results in all cases, the plus is turned into a space
I was able to resolve after identifying that my IDE had automagically added spring-boot-starter-undertow to the POM file. I did not exclude spring-boot-starter-tomcat from spring-boot-starter-web so I'm not sure what was happening under the covers but removing the spring-boot-starter-undertow dependency fixed the issue.

Spring Boot + Jersey + view controller not working together [duplicate]

I am getting a HTTP 404 error when trying to serve index.html ( located under main/resources/static) from a spring boot app. However if I remove the Jersey based JAX-RS class from the project, then http://localhost:8080/index.html works fine.
The following is main class
#SpringBootApplication
public class BootWebApplication {
public static void main(String[] args) {
SpringApplication.run(BootWebApplication.class, args);
}
}
I am not sure if I am missing something here.
Thanks
The problem is the default setting of the Jersey servlet path, which defaults to /*. This hogs up all the requests, including request to the default servlet for static content. So the request is going to Jersey looking for the static content, and when it can't find the resource within the Jersey application, it will send out a 404.
You have a couple options around this:
Configure Jerse runtime as a filter (instead of as a servlet by default). See this post for how you can do that. Also with this option, you need to configure one of the ServletProperties to forward the 404s to the servlet container. You can use the property that configures Jersey to forward all request which results in a Jersey resource not being found, or the property that allows you to configure a regex pattern for requests to foward.
You can simply change the Jersey servlet pattern to something else other than the default. The easiest way to do that is to annotate your ResourceConfig subclass with #ApplicationPath("/root-path"). Or you can configure it in your application.properties - spring.jersey.applicationPath.

How to enable swagger in a jersey + spring-boot web application [duplicate]

I am getting a HTTP 404 error when trying to serve index.html ( located under main/resources/static) from a spring boot app. However if I remove the Jersey based JAX-RS class from the project, then http://localhost:8080/index.html works fine.
The following is main class
#SpringBootApplication
public class BootWebApplication {
public static void main(String[] args) {
SpringApplication.run(BootWebApplication.class, args);
}
}
I am not sure if I am missing something here.
Thanks
The problem is the default setting of the Jersey servlet path, which defaults to /*. This hogs up all the requests, including request to the default servlet for static content. So the request is going to Jersey looking for the static content, and when it can't find the resource within the Jersey application, it will send out a 404.
You have a couple options around this:
Configure Jerse runtime as a filter (instead of as a servlet by default). See this post for how you can do that. Also with this option, you need to configure one of the ServletProperties to forward the 404s to the servlet container. You can use the property that configures Jersey to forward all request which results in a Jersey resource not being found, or the property that allows you to configure a regex pattern for requests to foward.
You can simply change the Jersey servlet pattern to something else other than the default. The easiest way to do that is to annotate your ResourceConfig subclass with #ApplicationPath("/root-path"). Or you can configure it in your application.properties - spring.jersey.applicationPath.

Requested resource is not available in tomcat 7

I have created an web application based on spring mvc After I deployed it, in Tomcat manager the application is shown and it has been deployed successfully. But when I am accessing the web application it is giving me error saying requested resource is not available.
In log files there are no errors so far. Please help.
Regards,
Shruti
As you are using Spring MVC,
You should have SpringController in your project.
So in your each controller -
for each method there should be
a #RequestMapping(value = "/login", method = RequestMethod.GET) portion.
So your application url should be something like -
<<web server address>>/<your deployed war file name>/<The Request mapping url>
i.e.
something like -
http://localhost:8080/samplewebproject/login
which will give you the requested resource.

Spring #RequestMapping and trailing slash

I am trying to map a method in a Controller using the annotation with URI template:
#RequestMapping(value="/select/{customerNumber}/{resource}", method=RequestMethod.GET)
It appears that this does not get mapped if there is a trailing slash at the end of "resource".
Update: Using Spring 3.0.2 release
Update 2: #RequestMapping seems to behave differently for URI templates vs where I don't use template. For non-template, it does not work if I have a trailing slash. But for templates it does not work if I don't have a trailing slash. Very strange!
This is fixed in 3.0.3 release. SPR-7064

Resources