----- Original Message -----
From: "Mondain" <mondain(a)gmail.com>
To: undertow-dev(a)lists.jboss.org
Sent: Thursday, 6 February, 2014 9:36:34 AM
Subject: [undertow-dev] Embedding undertow into Red5
I'm a core dev on the Red5 project and I would like to offer
undertow as an
alternative to our current embedded tomcat server. I have read through the
examples, unit tests, and documentation regarding undertow. I have coded and
run my "plugin" implementation, but all I am getting are "Not Found"
responses in the browser. My suspicion is that the web.xml is not being read
in and / or parsed, but I'm not sure since I'm new with this code base.
Below you will see how I'm setting up and starting things; let me know what
I'm doing incorrectly.
Hi Mondain,
You are correct in your suspicion that Undertow is not parsing the web.xml. Undertow
provides an embedded Servlet implementation but it does not implement the
discovery/parsing parts, as this is left up to the embedding application.
Basically instead of using web.xml you need to add servlets, filters etc to the
DeploymentInfo structure programatically. The main reason for this is basically because
Undertow is designed to integrate well into other applications (especially Wildfly), and
application servers generally provide their own implementation of parsers, annotation
processors etc.
With that said though at some point we will probably do a standalone parser/annotation
processor to make this work out of the box (probably by just copying the relevant bits
from wildfly and packaging them in their own jar). This is a fairly low priority item at
the moment though.
Stuart
//get a reference to the current threads classloader
final ClassLoader originalClassLoader =
Thread.currentThread().getContextClassLoader();
// root location for servlet container
String serverRoot = System.getProperty("red5.root");
String confRoot = System.getProperty("red5.config_root");
System.setProperty("UNDERTOW_HOME", serverRoot);
if (webappFolder == null) {
// Use default webapps directory
webappFolder = FileUtil.formatPath(System.getProperty("red5.root"),
"/webapps");
}
System.setProperty("red5.webapp.root", webappFolder);
// scan the sub directories to determine our context paths
buildContextPathList(webappFolder);
try {
// create our servlet container
container = ServletContainer.Factory.newInstance();
// create a root path handler
final PathHandler rootHandler = new PathHandler();
// create one server and use it everywhere
Undertow.Builder builder = Undertow.builder();
// loop through connectors adding listeners to the builder
for (UndertowConnector undertowConnector : connectors) {
InetSocketAddress addr = undertowConnector.getSocketAddress();
builder.addListener(addr.getPort(), addr.getHostName(),
(undertowConnector.isSecure() ? ListenerType.HTTPS : ListenerType.HTTP));
}
// loop the other contexts
for (String contextPath : contextPaths) {
// create a class loader for the context
ClassLoader classLoader = buildWebClassLoader(originalClassLoader,
webappFolder, contextPath);
// create deployment info
DeploymentInfo info = deployment()
.setClassLoader(classLoader)
.setContextPath(contextPath.equalsIgnoreCase("/ROOT") ? "/" :
contextPath)
.setDefaultEncoding("UTF-8")
.setDeploymentName(contextPath.substring(1) + ".war")
.setUrlEncoding("UTF-8");
// add the new deployment to the servlet container
DeploymentManager manager = container.addDeployment(info);
// deploy
manager.deploy();
// add path
rootHandler.addPrefixPath(info.getContextPath(), manager.start());
// get deployment
Deployment deployment = manager.getDeployment();
// get servlet context
final ServletContext servletContext = deployment.getServletContext();
log.debug("Context initialized: {}", servletContext.getContextPath());
try {
log.debug("Context: {}", servletContext);
final ClassLoader webClassLoader = info.getClassLoader();
log.debug("Webapp classloader: {}", webClassLoader);
// get the (spring) config file path
final String contextConfigLocation =
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONFIG_LOCATION_PARAM)
== null ? defaultSpringConfigLocation
:
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONFIG_LOCATION_PARAM);
log.debug("Spring context config location: {}", contextConfigLocation);
// get the (spring) parent context key
final String parentContextKey =
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.LOCATOR_FACTORY_KEY_PARAM)
== null ? defaultParentContextKey
:
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.LOCATOR_FACTORY_KEY_PARAM);
// set current threads classloader to the webapp classloader
Thread.currentThread().setContextClassLoader(webClassLoader);
// create a thread to speed-up application loading
Thread thread = new Thread("Launcher:" + servletContext.getContextPath()) {
public void run() {
//set thread context classloader to web classloader
Thread.currentThread().setContextClassLoader(webClassLoader);
//get the web app's parent context
ApplicationContext parentContext = null;
if (applicationContext.containsBean(parentContextKey)) {
parentContext = (ApplicationContext)
applicationContext.getBean(parentContextKey);
} else {
log.warn("Parent context was not found: {}", parentContextKey);
}
// create a spring web application context
final String contextClass =
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONTEXT_CLASS_PARAM)
== null ? XmlWebApplicationContext.class
.getName() :
servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONTEXT_CLASS_PARAM);
// web app context (spring)
ConfigurableWebApplicationContext appctx = null;
try {
Class<?> clazz = Class.forName(contextClass, true, webClassLoader);
appctx = (ConfigurableWebApplicationContext) clazz.newInstance();
// set the root webapp ctx attr on the each servlet context so spring can
find it later
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
appctx);
appctx.setConfigLocations(new String[] { contextConfigLocation });
appctx.setServletContext(servletContext);
// set parent context or use current app context
if (parentContext != null) {
appctx.setParent(parentContext);
} else {
appctx.setParent(applicationContext);
}
// refresh the factory
appctx.refresh();
appctx.start();
} catch (Throwable e) {
throw new RuntimeException("Failed to load webapplication context class", e);
}
}
};
thread.setDaemon(true);
thread.start();
} catch (Throwable t) {
t.printStackTrace();
} finally {
//reset the classloader
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
// Dump deployments list
if (log.isDebugEnabled()) {
for (String deployment : container.listDeployments()) {
log.debug("Container deployment: {}", deployment);
}
}
// add a root handler
builder.setHandler(rootHandler);
// build the server instance
server = builder.build();
log.info ("Starting Undertow");
server.start();
} catch (Exception e) {
if (e instanceof BindException || e.getMessage().indexOf("BindException") !=
-1) {
log.error("Error loading undertow, unable to bind connector. You may not have
permission to use the selected port", e);
} else {
log.error("Error loading undertow", e);
}
}
Regards,
Paul
_______________________________________________
undertow-dev mailing list
undertow-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/undertow-dev