<html><body><div style="font-family: times new roman, new york, times, serif; font-size: 12pt; color: #000000"><br><div><br></div><hr id="zwchr"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Mondain" &lt;mondain@gmail.com&gt;<br><b>To: </b>undertow-dev@lists.jboss.org<br><b>Sent: </b>Thursday, 6 February, 2014 9:36:34 AM<br><b>Subject: </b>[undertow-dev] Embedding undertow into Red5<br><div><br></div><div dir="ltr">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.</div></blockquote><div>Hi&nbsp;<span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;">Mondain,</span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;"><br></span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;">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.&nbsp;</span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;"><br></span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;">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.&nbsp;</span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;"><br></span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;">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.</span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;"><br></span></div><div><span style="font-family: Helvetica, Arial, sans-serif;" data-mce-style="font-family: Helvetica, Arial, sans-serif;">Stuart</span></div><div><br></div><div><br></div><div><br></div><div><br></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div><br></div><div><div><span class="" style="white-space:pre">                </span>//get a reference to the current threads classloader</div><div><span class="" style="white-space:pre">                </span>final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();</div><div><span class="" style="white-space:pre">                </span>// root location for servlet container</div><div><span class="" style="white-space:pre">                </span>String serverRoot = System.getProperty("red5.root");</div><div><span class="" style="white-space:pre">                </span>String confRoot = System.getProperty("red5.config_root");</div><div><span class="" style="white-space:pre">                </span>System.setProperty("UNDERTOW_HOME", serverRoot);</div><div><span class="" style="white-space:pre">                </span>if (webappFolder == null) {</div><div><span class="" style="white-space:pre">                        </span>// Use default webapps directory</div><div><span class="" style="white-space:pre">                        </span>webappFolder = FileUtil.formatPath(System.getProperty("red5.root"), "/webapps");</div><div><span class="" style="white-space:pre">                </span>}</div><div><span class="" style="white-space:pre">                </span>System.setProperty("red5.webapp.root", webappFolder);</div><div><span class="" style="white-space:pre">                </span>// scan the sub directories to determine our context paths</div><div><span class="" style="white-space:pre">                </span>buildContextPathList(webappFolder);</div><div><span class="" style="white-space:pre">                </span>try {</div><div><span class="" style="white-space:pre">                        </span>// create our servlet container</div><div><span class="" style="white-space:pre">        </span> &nbsp; &nbsp; &nbsp; &nbsp;container = ServletContainer.Factory.newInstance();</div><div><span class="" style="white-space:pre">                        </span>// create a root path handler</div><div><span class="" style="white-space:pre">                        </span>final PathHandler rootHandler = new PathHandler();</div><div><span class="" style="white-space:pre">                        </span>// create one server and use it everywhere</div><div><span class="" style="white-space:pre">                        </span>Undertow.Builder builder = Undertow.builder();</div><div><span class="" style="white-space:pre">                        </span>// loop through connectors adding listeners to the builder</div><div><span class="" style="white-space:pre">                        </span>for (UndertowConnector undertowConnector : connectors) {</div><div><span class="" style="white-space:pre">                                </span>InetSocketAddress addr = undertowConnector.getSocketAddress();</div><div><span class="" style="white-space:pre">                                </span>builder.addListener(addr.getPort(), addr.getHostName(), (undertowConnector.isSecure() ? ListenerType.HTTPS : ListenerType.HTTP));</div><div><span class="" style="white-space:pre">                        </span>}</div><div><span class="" style="white-space:pre">                        </span>// loop the other contexts</div><div><span class="" style="white-space:pre">                        </span>for (String contextPath : contextPaths) {</div><div><span class="" style="white-space:pre">                                </span>// create a class loader for the context</div><div><span class="" style="white-space:pre">                                </span>ClassLoader classLoader = buildWebClassLoader(originalClassLoader, webappFolder, contextPath);</div><div><span class="" style="white-space:pre">                                </span>// create deployment info</div><div><span class="" style="white-space:pre">                                </span>DeploymentInfo info = deployment()</div><div><span class="" style="white-space:pre">                </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setClassLoader(classLoader)</div><div><span class="" style="white-space:pre">                </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setContextPath(contextPath.equalsIgnoreCase("/ROOT") ? "/" : contextPath)</div><div><span class="" style="white-space:pre">                </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setDefaultEncoding("UTF-8")</div><div><span class="" style="white-space:pre">                </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setDeploymentName(contextPath.substring(1) + ".war")</div><div><span class="" style="white-space:pre">                </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setUrlEncoding("UTF-8");</div><div><span class="" style="white-space:pre">                                </span>// add the new deployment to the servlet container</div><div><span class="" style="white-space:pre">                                </span>DeploymentManager manager = container.addDeployment(info);</div><div><span class="" style="white-space:pre">                                </span>// deploy</div><div><span class="" style="white-space:pre">                                </span>manager.deploy();</div><div><span class="" style="white-space:pre">                                </span>// add path</div><div><span class="" style="white-space:pre">        </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rootHandler.addPrefixPath(info.getContextPath(), manager.start());</div><div><span class="" style="white-space:pre">                                </span>// get deployment</div><div><span class="" style="white-space:pre">                                </span>Deployment deployment = manager.getDeployment();</div><div><span class="" style="white-space:pre">                                </span>// get servlet context</div><div><span class="" style="white-space:pre">                                </span>final ServletContext servletContext = deployment.getServletContext();</div><div><span class="" style="white-space:pre">                                </span>log.debug("Context initialized: {}", servletContext.getContextPath());</div><div><span class="" style="white-space:pre">                                </span>try {</div><div><span class="" style="white-space:pre">                                        </span>log.debug("Context: {}", servletContext);</div><div><span class="" style="white-space:pre">                                        </span>final ClassLoader webClassLoader = info.getClassLoader();</div><div><span class="" style="white-space:pre">                                        </span>log.debug("Webapp classloader: {}", webClassLoader);</div><div><span class="" style="white-space:pre">                                        </span>// get the (spring) config file path</div><div><span class="" style="white-space:pre">                                        </span>final String contextConfigLocation = servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONFIG_LOCATION_PARAM) == null ? defaultSpringConfigLocation</div><div><span class="" style="white-space:pre">                                                        </span>: servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONFIG_LOCATION_PARAM);</div><div><span class="" style="white-space:pre">                                        </span>log.debug("Spring context config location: {}", contextConfigLocation);</div><div><span class="" style="white-space:pre">                                        </span>// get the (spring) parent context key</div><div><span class="" style="white-space:pre">                                        </span>final String parentContextKey = servletContext.getInitParameter(org.springframework.web.context.ContextLoader.LOCATOR_FACTORY_KEY_PARAM) == null ? defaultParentContextKey</div><div><span class="" style="white-space:pre">                                                        </span>: servletContext.getInitParameter(org.springframework.web.context.ContextLoader.LOCATOR_FACTORY_KEY_PARAM);</div><div><span class="" style="white-space:pre">                                        </span>// set current threads classloader to the webapp classloader</div><div><span class="" style="white-space:pre">                                        </span>Thread.currentThread().setContextClassLoader(webClassLoader);</div><div><span class="" style="white-space:pre">                                        </span>// create a thread to speed-up application loading</div><div><span class="" style="white-space:pre">                                        </span>Thread thread = new Thread("Launcher:" + servletContext.getContextPath()) {</div><div><span class="" style="white-space:pre">                                                </span>public void run() {</div><div><span class="" style="white-space:pre">                                                        </span>//set thread context classloader to web classloader</div><div><span class="" style="white-space:pre">                                                        </span>Thread.currentThread().setContextClassLoader(webClassLoader);</div><div><span class="" style="white-space:pre">                                                        </span>//get the web app's parent context</div><div><span class="" style="white-space:pre">                                                        </span>ApplicationContext parentContext = null;</div><div><span class="" style="white-space:pre">                                                        </span>if (applicationContext.containsBean(parentContextKey)) {</div><div><span class="" style="white-space:pre">                                                                </span>parentContext = (ApplicationContext) applicationContext.getBean(parentContextKey);</div><div><span class="" style="white-space:pre">                                                        </span>} else {</div><div><span class="" style="white-space:pre">                                                                </span>log.warn("Parent context was not found: {}", parentContextKey);</div><div><span class="" style="white-space:pre">                                                        </span>}</div><div><span class="" style="white-space:pre">                                                        </span>// create a spring web application context</div><div><span class="" style="white-space:pre">                                                        </span>final String contextClass = servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONTEXT_CLASS_PARAM) == null ? XmlWebApplicationContext.class</div><div><span class="" style="white-space:pre">                                                                        </span>.getName() : servletContext.getInitParameter(org.springframework.web.context.ContextLoader.CONTEXT_CLASS_PARAM);</div><div><span class="" style="white-space:pre">                                                        </span>// web app context (spring)</div><div><span class="" style="white-space:pre">                                                        </span>ConfigurableWebApplicationContext appctx = null;</div><div><span class="" style="white-space:pre">                                                        </span>try {</div><div><span class="" style="white-space:pre">                                                                </span>Class&lt;?&gt; clazz = Class.forName(contextClass, true, webClassLoader);</div><div><span class="" style="white-space:pre">                                                                </span>appctx = (ConfigurableWebApplicationContext) clazz.newInstance();</div><div><span class="" style="white-space:pre">                                                                </span>// set the root webapp ctx attr on the each servlet context so spring can find it later</div><div><span class="" style="white-space:pre">                                                                </span>servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appctx);</div><div><span class="" style="white-space:pre">                                                                </span>appctx.setConfigLocations(new String[] { contextConfigLocation });</div><div><span class="" style="white-space:pre">                                                                </span>appctx.setServletContext(servletContext);</div><div><span class="" style="white-space:pre">                                                                </span>// set parent context or use current app context</div><div><span class="" style="white-space:pre">                                                                </span>if (parentContext != null) {</div><div><span class="" style="white-space:pre">                                                                        </span>appctx.setParent(parentContext);</div><div><span class="" style="white-space:pre">                                                                </span>} else {</div><div><span class="" style="white-space:pre">                                                                        </span>appctx.setParent(applicationContext);</div><div><span class="" style="white-space:pre">                                                                </span>}</div><div><span class="" style="white-space:pre">                                                                </span>// refresh the factory</div><div><span class="" style="white-space:pre">                                                                </span>appctx.refresh();</div><div><span class="" style="white-space:pre">                                                                </span>appctx.start();</div><div><span class="" style="white-space:pre">                                                        </span>} catch (Throwable e) {</div><div><span class="" style="white-space:pre">                                                                </span>throw new RuntimeException("Failed to load webapplication context class", e);</div><div><span class="" style="white-space:pre">                                                        </span>}</div><div><span class="" style="white-space:pre">                                                </span>}</div><div><span class="" style="white-space:pre">                                        </span>};</div><div><span class="" style="white-space:pre">                                        </span>thread.setDaemon(true);</div><div><span class="" style="white-space:pre">                                        </span>thread.start();</div><div><span class="" style="white-space:pre">                                </span>} catch (Throwable t) {</div><div><span class="" style="white-space:pre">                                        </span>t.printStackTrace();</div><div><span class="" style="white-space:pre">                                </span>} finally {</div><div><span class="" style="white-space:pre">                                        </span>//reset the classloader</div><div><span class="" style="white-space:pre">                                        </span>Thread.currentThread().setContextClassLoader(originalClassLoader);</div><div><span class="" style="white-space:pre">                                </span>}</div><div><span class="" style="white-space:pre">                        </span>}</div><div><span class="" style="white-space:pre">                        </span>// Dump deployments list</div><div><span class="" style="white-space:pre">                        </span>if (log.isDebugEnabled()) {</div><div><span class="" style="white-space:pre">                                </span>for (String deployment : container.listDeployments()) {</div><div><span class="" style="white-space:pre">                                        </span>log.debug("Container deployment: {}", deployment);</div><div><span class="" style="white-space:pre">                                </span>}</div><div><span class="" style="white-space:pre">                        </span>}</div><div><span class="" style="white-space:pre">                        </span>// add a root handler</div><div><span class="" style="white-space:pre">                        </span>builder.setHandler(rootHandler);</div><div><span class="" style="white-space:pre">                        </span>// build the server instance</div><div><span class="" style="white-space:pre">        </span> &nbsp; &nbsp; &nbsp; &nbsp;server = builder.build();</div><div><span class="" style="white-space:pre">                        </span><a href="http://log.info" target="_blank">log.info</a>("Starting Undertow");</div><div><span class="" style="white-space:pre">                        </span>server.start();</div><div><span class="" style="white-space:pre">                </span>} catch (Exception e) {</div><div><span class="" style="white-space:pre">                        </span>if (e instanceof BindException || e.getMessage().indexOf("BindException") != -1) {</div><div><span class="" style="white-space:pre">                                </span>log.error("Error loading undertow, unable to bind connector. You may not have permission to use the selected port", e);</div><div><span class="" style="white-space:pre">                        </span>} else {</div><div><span class="" style="white-space:pre">                                </span>log.error("Error loading undertow", e);</div><div><span class="" style="white-space:pre">                        </span>}</div><div><span class="" style="white-space:pre">                </span>}</div><div><br></div><div><br></div><div><br></div><div>Regards,</div><div>Paul<br clear="all"><div><br></div>-- <br><a href="http://gregoire.org/" target="_blank">http://gregoire.org/</a><br><a href="http://code.google.com/p/red5/" target="_blank">http://code.google.com/p/red5/</a></div></div></div><br>_______________________________________________<br>undertow-dev mailing list<br>undertow-dev@lists.jboss.org<br>https://lists.jboss.org/mailman/listinfo/undertow-dev</blockquote><br></div></body></html>