diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 2f7f0401e5f..18f93039985 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -170,6 +170,11 @@
undertow-servlet
true
+
+ io.undertow
+ undertow-websockets-jsr
+ true
+
org.freemarker
freemarker
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/UndertowWebSocketContainerCustomizer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/UndertowWebSocketContainerCustomizer.java
new file mode 100644
index 00000000000..d36161d35fd
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/UndertowWebSocketContainerCustomizer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.autoconfigure.websocket;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
+
+import org.springframework.boot.context.embedded.undertow.UndertowDeploymentInfoCustomizer;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
+
+/**
+ * {@link WebSocketContainerCustomizer} for
+ * {@link UndertowEmbeddedServletContainerFactory}.
+ *
+ * @author Phillip Webb
+ * @since 1.2.0
+ */
+public class UndertowWebSocketContainerCustomizer extends
+ WebSocketContainerCustomizer {
+
+ @Override
+ protected void doCustomize(UndertowEmbeddedServletContainerFactory container) {
+ WebsocketDeploymentInfoCustomizer customizer = new WebsocketDeploymentInfoCustomizer();
+ container.addDeploymentInfoCustomizers(customizer);
+ }
+
+ private static class WebsocketDeploymentInfoCustomizer implements
+ UndertowDeploymentInfoCustomizer {
+
+ @Override
+ public void customize(DeploymentInfo deploymentInfo) {
+ WebSocketDeploymentInfo info = new WebSocketDeploymentInfo();
+ deploymentInfo.addServletContextAttribute(
+ WebSocketDeploymentInfo.ATTRIBUTE_NAME, info);
+ }
+
+ }
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
index 3225d3a0e7e..0b426611157 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
@@ -75,4 +75,16 @@ public class WebSocketAutoConfiguration {
}
+ @Configuration
+ @ConditionalOnClass(io.undertow.websockets.jsr.Bootstrap.class)
+ static class UndertowWebSocketConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(name = "websocketContainerCustomizer")
+ public EmbeddedServletContainerCustomizer websocketContainerCustomizer() {
+ return new UndertowWebSocketContainerCustomizer();
+ }
+
+ }
+
}
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 25b5a39b803..220bf5314ab 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -563,6 +563,11 @@
undertow-servlet
${undertow.version}
+
+ io.undertow
+ undertow-websockets-jsr
+ ${undertow.version}
+
javax.cache
cache-api
diff --git a/spring-boot-starters/spring-boot-starter-undertow/pom.xml b/spring-boot-starters/spring-boot-starter-undertow/pom.xml
index f4bcf69ea0d..2fcc566e53c 100644
--- a/spring-boot-starters/spring-boot-starter-undertow/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-undertow/pom.xml
@@ -33,6 +33,10 @@
+
+ io.undertow
+ undertow-websockets-jsr
+
javax.servlet
javax.servlet-api
diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowDeploymentInfoCustomizer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowDeploymentInfoCustomizer.java
new file mode 100644
index 00000000000..99fa91129a8
--- /dev/null
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowDeploymentInfoCustomizer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.context.embedded.undertow;
+
+import io.undertow.servlet.api.DeploymentInfo;
+
+/**
+ * Callback interface that can be used to customize an Undertow {@link DeploymentInfo}.
+ *
+ * @author Phillip Webb
+ * @since 1.2.0
+ * @see UndertowEmbeddedServletContainerFactory
+ */
+public interface UndertowDeploymentInfoCustomizer {
+
+ /**
+ * @param deploymentInfo the {@code DeploymentInfo} to customize
+ */
+ void customize(DeploymentInfo deploymentInfo);
+
+}
diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java
index e60f8b7f83e..916b93b3f46 100644
--- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java
@@ -86,7 +86,9 @@ import org.xnio.SslClientAuthMode;
public class UndertowEmbeddedServletContainerFactory extends
AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware {
- private List undertowBuilderCustomizers = new ArrayList();
+ private List builderCustomizers = new ArrayList();
+
+ private List deploymentInfoCustomizers = new ArrayList();
private ResourceLoader resourceLoader;
@@ -132,14 +134,12 @@ public class UndertowEmbeddedServletContainerFactory extends
/**
* Set {@link UndertowBuilderCustomizer}s that should be applied to the Undertow
* {@link Builder}. Calling this method will replace any existing customizers.
- * @param undertowBuilderCustomizers the customizers to set
+ * @param customizers the customizers to set
*/
- public void setUndertowBuilderCustomizers(
- Collection extends UndertowBuilderCustomizer> undertowBuilderCustomizers) {
- Assert.notNull(undertowBuilderCustomizers,
- "undertowBuilderCustomizers must not be null");
- this.undertowBuilderCustomizers = new ArrayList(
- undertowBuilderCustomizers);
+ public void setBuilderCustomizers(
+ Collection extends UndertowBuilderCustomizer> customizers) {
+ Assert.notNull(customizers, "Customizers must not be null");
+ this.builderCustomizers = new ArrayList(customizers);
}
/**
@@ -147,20 +147,51 @@ public class UndertowEmbeddedServletContainerFactory extends
* applied to the Undertow {@link Builder} .
* @return the customizers that will be applied
*/
- public Collection getUndertowBuilderCustomizers() {
- return this.undertowBuilderCustomizers;
+ public Collection getBuilderCustomizers() {
+ return this.builderCustomizers;
}
/**
* Add {@link UndertowBuilderCustomizer}s that should be used to customize the
* Undertow {@link Builder}.
- * @param undertowBuilderCustomizers the customizers to add
+ * @param customizers the customizers to add
+ */
+ public void addBuilderCustomizers(UndertowBuilderCustomizer... customizers) {
+ Assert.notNull(customizers, "Customizers must not be null");
+ this.builderCustomizers.addAll(Arrays.asList(customizers));
+ }
+
+ /**
+ * Set {@link UndertowDeploymentInfoCustomizer}s that should be applied to the
+ * Undertow {@link DeploymentInfo}. Calling this method will replace any existing
+ * customizers.
+ * @param customizers the customizers to set
*/
- public void addUndertowBuilderCustomizers(
- UndertowBuilderCustomizer... undertowBuilderCustomizers) {
- Assert.notNull(undertowBuilderCustomizers,
- "undertowBuilderCustomizers must not be null");
- this.undertowBuilderCustomizers.addAll(Arrays.asList(undertowBuilderCustomizers));
+ public void setDeploymentInfoCustomizers(
+ Collection extends UndertowDeploymentInfoCustomizer> customizers) {
+ Assert.notNull(customizers, "Customizers must not be null");
+ this.deploymentInfoCustomizers = new ArrayList(
+ customizers);
+ }
+
+ /**
+ * Returns a mutable collection of the {@link UndertowDeploymentInfoCustomizer}s that
+ * will be applied to the Undertow {@link DeploymentInfo} .
+ * @return the customizers that will be applied
+ */
+ public Collection getDeploymentInfoCustomizers() {
+ return this.deploymentInfoCustomizers;
+ }
+
+ /**
+ * Add {@link UndertowDeploymentInfoCustomizer}s that should be used to customize the
+ * Undertow {@link DeploymentInfo}.
+ * @param customizers the customizers to add
+ */
+ public void addDeploymentInfoCustomizers(
+ UndertowDeploymentInfoCustomizer... customizers) {
+ Assert.notNull(customizers, "UndertowDeploymentInfoCustomizers must not be null");
+ this.deploymentInfoCustomizers.addAll(Arrays.asList(customizers));
}
@Override
@@ -199,7 +230,7 @@ public class UndertowEmbeddedServletContainerFactory extends
else {
configureSsl(port, builder);
}
- for (UndertowBuilderCustomizer customizer : this.undertowBuilderCustomizers) {
+ for (UndertowBuilderCustomizer customizer : this.builderCustomizers) {
customizer.customize(builder);
}
return builder;
@@ -298,6 +329,9 @@ public class UndertowEmbeddedServletContainerFactory extends
deployment.setServletStackTraces(ServletStackTraces.NONE);
deployment.setResourceManager(getDocumentRootResourceManager());
configureMimeMappings(deployment);
+ for (UndertowDeploymentInfoCustomizer customizer : this.deploymentInfoCustomizers) {
+ customizer.customize(deployment);
+ }
DeploymentManager manager = Servlets.defaultContainer().addDeployment(deployment);
manager.deploy();
SessionManager sessionManager = manager.getDeployment().getSessionManager();
diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java
index 7cccaee2573..2b4b656f5e0 100644
--- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java
@@ -17,6 +17,7 @@
package org.springframework.boot.context.embedded.undertow;
import io.undertow.Undertow.Builder;
+import io.undertow.servlet.api.DeploymentInfo;
import java.util.Arrays;
@@ -62,19 +63,19 @@ public class UndertowEmbeddedServletContainerFactoryTests extends
}
@Test
- public void setNullUndertowBuilderCustomizersThrows() {
+ public void setNullBuilderCustomizersThrows() {
UndertowEmbeddedServletContainerFactory factory = getFactory();
this.thrown.expect(IllegalArgumentException.class);
- this.thrown.expectMessage("undertowBuilderCustomizers must not be null");
- factory.setUndertowBuilderCustomizers(null);
+ this.thrown.expectMessage("Customizers must not be null");
+ factory.setBuilderCustomizers(null);
}
@Test
- public void addNullContextCustomizersThrows() {
+ public void addNullAddBuilderCustomizersThrows() {
UndertowEmbeddedServletContainerFactory factory = getFactory();
this.thrown.expect(IllegalArgumentException.class);
- this.thrown.expectMessage("undertowBuilderCustomizers must not be null");
- factory.addUndertowBuilderCustomizers((UndertowBuilderCustomizer[]) null);
+ this.thrown.expectMessage("Customizers must not be null");
+ factory.addBuilderCustomizers((UndertowBuilderCustomizer[]) null);
}
@Test
@@ -84,9 +85,8 @@ public class UndertowEmbeddedServletContainerFactoryTests extends
for (int i = 0; i < customizers.length; i++) {
customizers[i] = mock(UndertowBuilderCustomizer.class);
}
- factory.setUndertowBuilderCustomizers(Arrays.asList(customizers[0],
- customizers[1]));
- factory.addUndertowBuilderCustomizers(customizers[2], customizers[3]);
+ factory.setBuilderCustomizers(Arrays.asList(customizers[0], customizers[1]));
+ factory.addBuilderCustomizers(customizers[2], customizers[3]);
this.container = factory.getEmbeddedServletContainer();
InOrder ordered = inOrder((Object[]) customizers);
for (UndertowBuilderCustomizer customizer : customizers) {
@@ -94,6 +94,39 @@ public class UndertowEmbeddedServletContainerFactoryTests extends
}
}
+ @Test
+ public void setNullDeploymentInfoCustomizersThrows() {
+ UndertowEmbeddedServletContainerFactory factory = getFactory();
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Customizers must not be null");
+ factory.setDeploymentInfoCustomizers(null);
+ }
+
+ @Test
+ public void addNullAddDeploymentInfoCustomizersThrows() {
+ UndertowEmbeddedServletContainerFactory factory = getFactory();
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Customizers must not be null");
+ factory.addDeploymentInfoCustomizers((UndertowDeploymentInfoCustomizer[]) null);
+ }
+
+ @Test
+ public void deploymentInfo() throws Exception {
+ UndertowEmbeddedServletContainerFactory factory = getFactory();
+ UndertowDeploymentInfoCustomizer[] customizers = new UndertowDeploymentInfoCustomizer[4];
+ for (int i = 0; i < customizers.length; i++) {
+ customizers[i] = mock(UndertowDeploymentInfoCustomizer.class);
+ }
+ factory.setDeploymentInfoCustomizers(Arrays
+ .asList(customizers[0], customizers[1]));
+ factory.addDeploymentInfoCustomizers(customizers[2], customizers[3]);
+ this.container = factory.getEmbeddedServletContainer();
+ InOrder ordered = inOrder((Object[]) customizers);
+ for (UndertowDeploymentInfoCustomizer customizer : customizers) {
+ ordered.verify(customizer).customize((DeploymentInfo) anyObject());
+ }
+ }
+
@Test
public void basicSslClasspathKeyStore() throws Exception {
testBasicSllWithKeystore("classpath:test.jks");