diff --git a/pom.xml b/pom.xml
index 8b3df8de0d..99e9d5a7e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -237,6 +237,7 @@
liquibase
spring-boot-property-exp
mockserver
+ undertow
diff --git a/undertow/pom.xml b/undertow/pom.xml
new file mode 100644
index 0000000000..a0f2dc53ee
--- /dev/null
+++ b/undertow/pom.xml
@@ -0,0 +1,58 @@
+
+ 4.0.0
+ com.baeldung.undertow
+ undertow
+ jar
+ 1.0-SNAPSHOT
+ undertow
+ http://maven.apache.org
+
+
+ 1.8
+ 1.8
+
+
+
+
+ io.undertow
+ undertow-core
+ 1.4.18.Final
+
+
+ io.undertow
+ undertow-servlet
+ 1.4.18.Final
+
+
+
+
+ ${project.artifactId}
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ com.baeldung.undertow.SimpleServer
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java b/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java
new file mode 100644
index 0000000000..7f869746be
--- /dev/null
+++ b/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java
@@ -0,0 +1,16 @@
+package com.baeldung.undertow;
+
+import io.undertow.Undertow;
+import io.undertow.util.Headers;
+
+public class SimpleServer {
+
+ public static void main(String[] args) {
+ Undertow server = Undertow.builder().addHttpListener(8080, "localhost").setHandler(exchange -> {
+ exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
+ exchange.getResponseSender().send("Hello Baeldung");
+ }).build();
+ server.start();
+ }
+
+}
diff --git a/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java b/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java
new file mode 100644
index 0000000000..90cad9ebbd
--- /dev/null
+++ b/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java
@@ -0,0 +1,20 @@
+package com.baeldung.undertow.ftp;
+
+import java.nio.file.Paths;
+
+import io.undertow.Undertow;
+import io.undertow.server.handlers.resource.PathResourceManager;
+
+import static io.undertow.Handlers.resource;
+
+public class FileServer {
+
+ public static void main(String[] args) {
+ Undertow server = Undertow.builder().addHttpListener(8080, "localhost")
+ .setHandler(resource(new PathResourceManager(Paths.get(System.getProperty("user.home")), 100))
+ .setDirectoryListingEnabled(true))
+ .build();
+ server.start();
+ }
+
+}
diff --git a/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java b/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java
new file mode 100644
index 0000000000..e0984f65a5
--- /dev/null
+++ b/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java
@@ -0,0 +1,77 @@
+package com.baeldung.undertow.secure;
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import io.undertow.security.idm.Account;
+import io.undertow.security.idm.Credential;
+import io.undertow.security.idm.PasswordCredential;
+
+public class CustomIdentityManager implements io.undertow.security.idm.IdentityManager {
+
+ private final Map users;
+
+ CustomIdentityManager(final Map users) {
+ this.users = users;
+ }
+
+ @Override
+ public Account verify(Account account) {
+ return account;
+ }
+
+ @Override
+ public Account verify(Credential credential) {
+ return null;
+ }
+
+ @Override
+ public Account verify(String id, Credential credential) {
+ Account account = getAccount(id);
+ if (account != null && verifyCredential(account, credential)) {
+ return account;
+ }
+ return null;
+ }
+
+ private boolean verifyCredential(Account account, Credential credential) {
+ if (credential instanceof PasswordCredential) {
+ char[] password = ((PasswordCredential) credential).getPassword();
+ char[] expectedPassword = users.get(account.getPrincipal().getName());
+
+ return Arrays.equals(password, expectedPassword);
+ }
+ return false;
+ }
+
+ private Account getAccount(final String id) {
+ if (users.containsKey(id)) {
+ return new Account() {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Principal principal = new Principal() {
+ @Override
+ public String getName() {
+ return id;
+ }
+ };
+
+ @Override
+ public Principal getPrincipal() {
+ return principal;
+ }
+
+ @Override
+ public Set getRoles() {
+ return Collections.emptySet();
+ }
+ };
+ }
+ return null;
+ }
+
+}
diff --git a/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java b/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java
new file mode 100644
index 0000000000..6f520944db
--- /dev/null
+++ b/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java
@@ -0,0 +1,52 @@
+package com.baeldung.undertow.secure;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.undertow.Undertow;
+import io.undertow.io.IoCallback;
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.security.api.AuthenticationMode;
+import io.undertow.security.api.SecurityContext;
+import io.undertow.security.handlers.AuthenticationCallHandler;
+import io.undertow.security.handlers.AuthenticationConstraintHandler;
+import io.undertow.security.handlers.AuthenticationMechanismsHandler;
+import io.undertow.security.handlers.SecurityInitialHandler;
+import io.undertow.security.idm.IdentityManager;
+import io.undertow.security.impl.BasicAuthenticationMechanism;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+
+public class SecureServer {
+
+ public static void main(String[] args) {
+ final Map users = new HashMap<>(2);
+ users.put("root", "password".toCharArray());
+ users.put("admin", "password".toCharArray());
+
+ final IdentityManager idm = new CustomIdentityManager(users);
+
+ Undertow server = Undertow.builder().addHttpListener(8080, "localhost").setHandler(addSecurity((exchange) -> {
+ final SecurityContext context = exchange.getSecurityContext();
+ exchange.getResponseSender().send("Hello " + context.getAuthenticatedAccount().getPrincipal().getName(),
+ IoCallback.END_EXCHANGE);
+ }, idm)).build();
+
+ server.start();
+
+ }
+
+ private static HttpHandler addSecurity(final HttpHandler toWrap, final IdentityManager identityManager) {
+ HttpHandler handler = toWrap;
+ handler = new AuthenticationCallHandler(handler);
+ handler = new AuthenticationConstraintHandler(handler);
+ final List mechanisms = Collections
+ . singletonList(new BasicAuthenticationMechanism("Baeldung_Realm"));
+ handler = new AuthenticationMechanismsHandler(handler, mechanisms);
+ handler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler);
+ return handler;
+ }
+
+}
diff --git a/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java b/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java
new file mode 100644
index 0000000000..9e0e065c3a
--- /dev/null
+++ b/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java
@@ -0,0 +1,36 @@
+package com.baeldung.undertow.socket;
+
+import io.undertow.Undertow;
+import io.undertow.server.handlers.resource.ClassPathResourceManager;
+import io.undertow.websockets.core.AbstractReceiveListener;
+import io.undertow.websockets.core.BufferedTextMessage;
+import io.undertow.websockets.core.WebSocketChannel;
+import io.undertow.websockets.core.WebSockets;
+
+import static io.undertow.Handlers.path;
+import static io.undertow.Handlers.resource;
+import static io.undertow.Handlers.websocket;
+
+public class SocketServer {
+
+ public static void main(String[] args) {
+ Undertow server = Undertow.builder().addHttpListener(8080, "localhost")
+ .setHandler(path().addPrefixPath("/baeldungApp", websocket((exchange, channel) -> {
+ channel.getReceiveSetter().set(new AbstractReceiveListener() {
+ @Override
+ protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) {
+ final String messageData = message.getData();
+ for (WebSocketChannel session : channel.getPeerConnections()) {
+ WebSockets.sendText(messageData, session, null);
+ }
+ }
+ });
+ channel.resumeReceives();
+ })).addPrefixPath("/", resource(new ClassPathResourceManager(SocketServer.class.getClassLoader(),
+ SocketServer.class.getPackage())).addWelcomeFiles("index.html")))
+ .build();
+
+ server.start();
+ }
+
+}