Skip to content

Commit ff2d423

Browse files
committed
Correct the root context path used with Undertow
Undertow, like Tomcat, uses "" for the context path of the root context. Previously, the Undertow deployment was being configured with "/" for the root context. This was leading to a silent failure in AsyncContextImpl.dispatch when it failed to look up the deployment manager for the current request. This commit updates UndertowEmbeddedServletContainerFactory to use the correct context path (an empty String) for the root context. Fixes gh-2365
1 parent f019fb2 commit ff2d423

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

spring-boot-samples/spring-boot-sample-undertow/src/main/java/sample/undertow/web/SampleController.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,23 +16,37 @@
1616

1717
package sample.undertow.web;
1818

19+
import java.util.concurrent.Callable;
20+
1921
import org.springframework.beans.factory.annotation.Autowired;
20-
import org.springframework.stereotype.Controller;
2122
import org.springframework.web.bind.annotation.RequestMapping;
22-
import org.springframework.web.bind.annotation.ResponseBody;
23+
import org.springframework.web.bind.annotation.RestController;
2324

2425
import sample.undertow.service.HelloWorldService;
2526

26-
@Controller
27+
@RestController
2728
public class SampleController {
2829

2930
@Autowired
3031
private HelloWorldService helloWorldService;
3132

3233
@RequestMapping("/")
33-
@ResponseBody
3434
public String helloWorld() {
3535
return this.helloWorldService.getHelloMessage();
3636
}
3737

38+
@RequestMapping("/async")
39+
public Callable<String> helloWorldAsync() {
40+
return new Callable<String>() {
41+
42+
@Override
43+
public String call() throws Exception {
44+
return "async: "
45+
+ SampleController.this.helloWorldService.getHelloMessage();
46+
}
47+
48+
};
49+
50+
}
51+
3852
}

spring-boot-samples/spring-boot-sample-undertow/src/test/java/sample/undertow/SampleUndertowApplicationTests.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
3434
* Basic integration tests for demo application.
3535
*
3636
* @author Ivan Sopov
37+
* @author Andy Wilkinson
3738
*/
3839
@RunWith(SpringJUnit4ClassRunner.class)
3940
@SpringApplicationConfiguration(classes = SampleUndertowApplication.class)
@@ -47,10 +48,19 @@ public class SampleUndertowApplicationTests {
4748

4849
@Test
4950
public void testHome() throws Exception {
51+
assertOkResponse("/", "Hello World");
52+
}
53+
54+
@Test
55+
public void testAsync() throws Exception {
56+
assertOkResponse("/async", "async: Hello World");
57+
}
58+
59+
private void assertOkResponse(String path, String body) {
5060
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
51-
"http://localhost:" + this.port, String.class);
61+
"http://localhost:" + this.port + path, String.class);
5262
assertEquals(HttpStatus.OK, entity.getStatusCode());
53-
assertEquals("Hello World", entity.getBody());
63+
assertEquals(body, entity.getBody());
5464
}
5565

5666
}

spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import org.springframework.util.Assert;
7171
import org.springframework.util.ResourceUtils;
7272
import org.springframework.util.SocketUtils;
73-
import org.springframework.util.StringUtils;
7473
import org.xnio.Options;
7574
import org.xnio.SslClientAuthMode;
7675

@@ -329,8 +328,7 @@ private DeploymentManager createDeploymentManager(
329328
registerServletContainerInitializerToDriveServletContextInitializers(deployment,
330329
initializers);
331330
deployment.setClassLoader(getServletClassLoader());
332-
String contextPath = getContextPath();
333-
deployment.setContextPath(StringUtils.hasLength(contextPath) ? contextPath : "/");
331+
deployment.setContextPath(getContextPath());
334332
deployment.setDeploymentName("spring-boot");
335333
if (isRegisterDefaultServlet()) {
336334
deployment.addServlet(Servlets.servlet("default", DefaultServlet.class));

spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.undertow.servlet.api.DeploymentInfo;
2121

2222
import java.util.Arrays;
23+
import java.util.concurrent.atomic.AtomicReference;
2324

2425
import org.junit.Test;
2526
import org.mockito.InOrder;
@@ -31,6 +32,7 @@
3132
import org.springframework.http.HttpStatus;
3233

3334
import static org.hamcrest.Matchers.equalTo;
35+
import static org.junit.Assert.assertEquals;
3436
import static org.junit.Assert.assertThat;
3537
import static org.mockito.Matchers.anyObject;
3638
import static org.mockito.Mockito.inOrder;
@@ -132,4 +134,19 @@ public void basicSslClasspathKeyStore() throws Exception {
132134
testBasicSslWithKeyStore("classpath:test.jks");
133135
}
134136

137+
@Test
138+
public void defaultContextPath() throws Exception {
139+
UndertowEmbeddedServletContainerFactory factory = getFactory();
140+
final AtomicReference<String> contextPath = new AtomicReference<String>();
141+
factory.addDeploymentInfoCustomizers(new UndertowDeploymentInfoCustomizer() {
142+
143+
@Override
144+
public void customize(DeploymentInfo deploymentInfo) {
145+
contextPath.set(deploymentInfo.getContextPath());
146+
}
147+
});
148+
this.container = factory.getEmbeddedServletContainer();
149+
assertEquals("", contextPath.get());
150+
}
151+
135152
}

0 commit comments

Comments
 (0)