[undertow-dev] Embedding undertow into Red5

Stuart Douglas sdouglas at redhat.com
Fri Feb 7 06:42:10 EST 2014


You need to add the filter mapping directly to the DeploymentInfo structure using addFilterUrlMapping or addFilterServletNameMapping.

This is because there is a global ordering of filter mappings that determines the order filters get invoked in, while there is no such concept for Servlets.

Stuart

----- Original Message -----
> From: "Mondain" <mondain at gmail.com>
> To: undertow-dev at lists.jboss.org
> Sent: Thursday, 6 February, 2014 7:45:51 PM
> Subject: Re: [undertow-dev] Embedding undertow into Red5
> 
> I've got a first rev of my web.xml parser now and I've run into a curious
> thing regarding filters. How do I add the url-pattern to a FilterInfo
> mapping as I do with a ServletInfo mapping?
> 
> 
> 
> 
> 
> On Thu, Feb 6, 2014 at 7:35 AM, Mondain < mondain at gmail.com > wrote:
> 
> 
> 
> Thanks for the reply, now I know I have more work to do.
> 
> 
> On Thu, Feb 6, 2014 at 12:33 AM, Stuart Douglas < sdouglas at redhat.com >
> wrote:
> 
> 
> 
> 
> 
> 
> 
> 
> 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
> 
> 
> 
> --
> http://gregoire.org/
> http://code.google.com/p/red5/
> 
> 
> 
> --
> 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


More information about the undertow-dev mailing list