[undertow-dev] Embedding undertow into Red5

Stuart Douglas sdouglas at redhat.com
Thu Feb 6 03:33:06 EST 2014


----- Original Message -----

> From: "Mondain" <mondain at gmail.com>
> To: undertow-dev at 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

> --
> http://gregoire.org/
> http://code.google.com/p/red5/

> _______________________________________________
> undertow-dev mailing list
> undertow-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/undertow-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/undertow-dev/attachments/20140206/9f240bcc/attachment-0001.html 


More information about the undertow-dev mailing list