11 Replies Latest reply on Aug 17, 2005 2:24 AM by maheshkudva

    ROOT.war, root context, wildcard virtual hosts?

      Working with JBoss 4.0.1 & Tomcat with the 'default' server configuration.

      How can I have a root-context application respond to all hostnames that resolve to an IP address that JBoss/Tomcat is configured to listen on?

      E.g.
      *.domain.name
      *.domain.biz
      *.domain.org

      As you'll see from my detailed explanation below, I've tried the obvious way and ended up with errors that suggest I'm trying to use Java Server Faces when in fact I've just got a simple servlet that handles doGet() and doPost().

      Explanation:

      I am developing a web application that begins with a single "TrafficManager" servlet that returns a database-generated member-profile page in the following circumstances:

      **Preferred URL** (not yet found a way to do this)
      http://username1.domain.name
      http://username2.domain.biz
      http://username3.domain.org

      **Alternate URL** (this works)
      http://domain.name/username1
      http://domain.biz/username2
      http:/domain.org/username3

      This deploys (as ROOT.war) and works for the *Alternate URL* case with a single servlet set as the root (/) context, where there is a WEB-INF/jboss-web.xml containing:

      <?xml version="1.0"?>
      <jboss-web>
       <virtual-host>domain.name</virtual-host>
       <virtual-host>domain.biz</virtual-host>
       <virtual-host>domain.org</virtual-host>
       <context-root>/</context-root>
      </jboss-web>
      

      And jboss-4.0.1\server\default\deploy\jbossweb-tomcat50.sar\server.xml contains:
      <!-- HTTP/1.1 Connector -->
       <Connector port="80" address="x.y.z.245"
       maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
       enableLookups="false" redirectPort="8443" acceptCount="100"
       connectionTimeout="20000" disableUploadTimeout="true"/>
      
       <Host name="domain.name">
       <Alias>www.domain.name</Alias>
       </Host>
      
       <Host name="domain.org">
       <Alias>www.domain.org</Alias>
       </Host>
       <Host name="domain.biz">
       <Alias>www.domain.biz</Alias>
       </Host>
      

      Note: neither the < virtual-host >, < Host > or < Alias > elements appear to support wildcard hostnames such as *.domain.name.

      The Servlet simply contains:
      package net.phwoarrr.servlets;
      
      import java.io.IOException;
      import java.io.PrintWriter;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      public class TrafficManager extends HttpServlet {
      
       public TrafficManager() { super(); }
      
       public void destroy() { super.destroy(); }
      
       public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
       response.setContentType("text/html");
       PrintWriter out = response.getWriter();
       out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
       out.println("<HTML>");
       out.println("<HEAD><TITLE>Member Bio for " + request.getPathInfo() + "</TITLE></HEAD>");
       out.println("<BODY>");
       out.println("<h1>Member Bio for " + request.getPathInfo() + "</h1>");
       out.print("This is ");
       out.print(this.getClass());
       out.println(", using the GET method");
       out.println("</BODY>");
       out.println("</HTML>");
       out.flush();
       out.close();
       }
      
       public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
       response.setContentType("text/html");
       PrintWriter out = response.getWriter();
       out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
       out.println("<HTML>");
       out.println("<HEAD><TITLE>Member Bio for " + request.getPathInfo() + "</TITLE></HEAD>");
       out.println("<BODY>");
       out.println("<h1>Member Bio for " + request.getPathInfo() + "</h1>");
       out.print(this.getClass());
       out.println(", using the POST method");
       out.println("</BODY>");
       out.println("</HTML>");
       out.flush();
       out.close();
       }
      
       public void init() throws ServletException {
       // Put your code here
       }
      }
      

      However, when I aim to have the web application respond to *ALL* root-context HTTP-Requests (no matter what the hostname/IP is) by removing the <virtual-host> tags from jboss-web.xml, the JBoss/Tomcat deployer throws exceptions and cannot deploy the application.

      As you will see from the error report below, there is a suggestion that Java Server Faces is being deployed in the ROOT.war when in fact the ONLY change is to remove the <virtual-host> entries from jboss-web.xml.

      Here is a link to the http://tjworld.net/help/kb/jboss-server.log.txt which contains a lot more detail than I've posted here.

      2005-04-18 02:38:56,121 DEBUG [tomcat.localhost.ROOT.Context] Configuring application event listeners
      2005-04-18 02:38:56,121 DEBUG [tomcat.localhost.ROOT.Context] Configuring event listener class 'com.sun.faces.config.ConfigureListener'
      2005-04-18 02:38:56,137 ERROR [org.jboss.web.localhost.Engine] StandardContext[]Error configuring application listener of class com.sun.faces.config.ConfigureListener
      java.lang.ClassNotFoundException: com.sun.faces.config.ConfigureListener
       at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
       at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3775)
      
      ...
      
       at $Proxy8.deploy(Unknown Source)
       at org.jboss.deployment.scanner.URLDeploymentScanner.deploy(URLDeploymentScanner.java:305)
       at org.jboss.deployment.scanner.URLDeploymentScanner.scan(URLDeploymentScanner.java:463)
       at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.doScan(AbstractDeploymentScanner.java:204)
       at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.loop(AbstractDeploymentScanner.java:215)
       at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.run(AbstractDeploymentScanner.java:194)
      2005-04-18 02:38:56,152 ERROR [tomcat.localhost.ROOT.Context] Skipped installing application listeners due to previous error(s)
      2005-04-18 02:38:56,152 ERROR [tomcat.localhost.ROOT.Context] Error listenerStart
      2005-04-18 02:38:56,152 ERROR [tomcat.localhost.ROOT.Context] Context startup failed due to previous errors
      2005-04-18 02:38:56,152 DEBUG [tomcat.localhost.ROOT.Context] Stopping
      2005-04-18 02:38:56,168 DEBUG [tomcat.localhost.ROOT.Context] Stopping filters
      2005-04-18 02:38:56,168 DEBUG [tomcat.localhost.ROOT.Context] Processing standard container shutdown
      2005-04-18 02:38:56,184 DEBUG [tomcat.localhost.ROOT.Context] Sending application stop events
      2005-04-18 02:38:56,184 DEBUG [tomcat.localhost.ROOT.Context] resetContext jboss.web:j2eeType=WebModule,name=//localhost/,J2EEApplication=none,J2EEServer=none org.jboss.mx.server.MBeanServerImpl@107ebe1
      2005-04-18 02:38:56,184 DEBUG [tomcat.localhost.ROOT.Context] Stopping complete
      

      REMEMBER - Simply adding one or more <virtual-host> elements to the jboss-web.xml and this web application runs perfectly.

      A successful deployment when <virtual-host> elements are used, looks like this:
      2005-04-18 03:15:29,223 DEBUG [tomcat.domain.name.ROOT.Context] Configuring application event listeners
      2005-04-18 03:15:29,223 DEBUG [tomcat.domain.name.ROOT.Context] Sending application start events
      2005-04-18 03:15:29,223 DEBUG [tomcat.domain.name.ROOT.Context] Starting filters
      2005-04-18 03:15:29,223 DEBUG [tomcat.domain.name.ROOT.Context] Starting filter 'CommonHeadersFilter'
      2005-04-18 03:15:29,239 DEBUG [org.jboss.web.tomcat.filters.ReplyHeaderFilter] Adding header name: X-Powered-By='Servlet 2.4; Tomcat-5.0.28/JBoss-4.0.1 (build: CVSTag=JBoss_4_0_1 date=200412230944)'
      2005-04-18 03:15:29,239 DEBUG [tomcat.domain.name.ROOT.Context] Starting completed
      2005-04-18 03:15:29,239 DEBUG [tomcat.domain.name.ROOT.Context] Checking for jboss.web:j2eeType=WebModule,name=//domain.name/,J2EEApplication=none,J2EEServer=none
      2005-04-18 03:15:29,270 DEBUG [org.jboss.web.tomcat.tc5.TomcatDeployer] Initialized: {WebApplication: /D:/Server/Java/jboss-4.0.1/server/default/tmp/deploy/tmp50102ROOT-exp.war/, URL: file:/D:/Server/Java/jboss-4.0.1/server/default/tmp/deploy/tmp50102ROOT-exp.war/, classLoader: java.net.FactoryURLClassLoader@1132e76:18034294} jboss.web:j2eeType=WebModule,name=//domain.name/,J2EEApplication=none,J2EEServer=none
      2005-04-18 03:15:29,270 DEBUG [org.jboss.web.tomcat.tc5.TomcatDeployer] deploy root context=/
      2005-04-18 03:15:29,270 INFO [org.jboss.web.tomcat.tc5.TomcatDeployer] deploy, ctxPath=/, warUrl=file:/D:/Server/Java/jboss-4.0.1/server/default/tmp/deploy/tmp50102ROOT-exp.war/
      2005-04-18 03:15:29,488 DEBUG [org.jboss.web.tomcat.tc5.TomcatDeployer] Using session cookies default setting
      


        • 1. Re: ROOT.war, root context, wildcard virtual hosts?

          I've also tried putting

          <virtual-host>localhost</virtual-host>

          in jboss-web.xml

          but the same ClassNotFoundException is thrown as when there is no virtual-host definition.

          • 2. Re: ROOT.war, root context, wildcard virtual hosts?

            I appear to have fixed my issue simply by including

            jsf-api.jar
            jsf-impl.jar

            in my web-app's

            WEB-INF/lib/

            folder.

            Deployment is now successful and a URL such as:

            http://somethingHere.domain.name/somethingHereToo

            is handled by my web-app.

            This still doesn't explain WHY the JSF libraries are required when my web-app isn't referencing any JSF services (go on, prove me wrong! *blush*)

            • 3. Re: ROOT.war, root context, wildcard virtual hosts?
              darranl

              What does your web.xml look like?

              • 4. Re: ROOT.war, root context, wildcard virtual hosts?

                The web.xml is about 39KB so I've linked to a copy of it to save posting reams of text.

                jboss-4.0.1\server\default\deploy\jbossweb-tomcat50.sar\conf\web.xml

                http://tjworld.net/help/kb/web.xml.txt

                • 5. Re: ROOT.war, root context, wildcard virtual hosts?
                  darranl

                  Does your application contain a web.xml of its own?

                  • 6. Re: ROOT.war, root context, wildcard virtual hosts?

                    Lets try that again... formatting removed some of the content

                    <?xml version="1.0" encoding="UTF-8"?>
                    <web-app version="2.4"
                     xmlns="http://java.sun.com/xml/ns/j2ee"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
                     <servlet>
                     <description>Parses a URL and passes control to relavant servlet</description>
                     <display-name>Traffic Manager</display-name>
                     <servlet-name>TrafficManager</servlet-name>
                     <servlet-class>net.phwoarrr.servlets.TrafficManager</servlet-class>
                     </servlet>
                    
                     <servlet-mapping>
                     <servlet-name>TrafficManager</servlet-name>
                     <url-pattern>/*</url-pattern>
                     </servlet-mapping>
                    
                    </web-app>
                    


                    • 7. Re: ROOT.war, root context, wildcard virtual hosts?

                      Even more interesting...

                      Earlier I placed the JSF libraries in the

                      jboss-4.0.1/server/default/lib/

                      folder, but still got the same deployment error after restarting the JBoss service.

                      I just removed the two JSF libraries from my web-app's WEB-INF/lib/ folder, expecting the deployment to fail but JBoss found the JSF libraries in its own /lib/ folder.

                      2005-04-18 13:30:13,532 DEBUG [tomcat.localhost.ROOT.Context] Configuring event listener class 'com.sun.faces.config.ConfigureListener'
                      2005-04-18 13:30:13,532 DEBUG [tomcat.localhost.ROOT.Context] Sending application start events
                      2005-04-18 13:30:13,532 DEBUG [com.sun.faces.config.ConfigureListener] contextInitialized(null)
                      2005-04-18 13:30:13,532 DEBUG [com.sun.faces.config.ConfigureListener] Initializing this webapp
                      2005-04-18 13:30:13,579 DEBUG [com.sun.faces.config.ConfigureListener] parse(jar:file:/D:/Server/Java/jboss-4.0.1/server/default/lib/jsf-impl.jar!/com/sun/faces/jsf-ri-config.xml)
                      


                      I guess while its working I shouldn't complain, but it would be nice to know WHY this happened.... my code or something to do with JBoss and/or its configuration.


                      • 8. Re: ROOT.war, root context, wildcard virtual hosts?

                        Just to complete the topic for others that want to do the same thing as me, here's the basic code in my Servlet.

                        It looks for usernames first as a sub-domain, then in the path, so the following URLs will all be handled properly.

                        http://username.domain.name/
                        http://domain.name/username

                        http://username.domain.name/somethingElse

                        The last instance allows the Servlet to get the username from the sub-domain and also a path value that could point to a specifc page within the user's profile.

                        I've only posted the code that has been changed or added. Merge this with the full code I published above.

                        import java.net.URL;
                        
                        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                        
                         String profile = "blank";
                         StringBuffer sb = request.getRequestURL();
                         URL url = new URL(sb.toString());
                         String host = url.getHost();
                         String sSplit[] = host.split("\\.");
                         if(sSplit[0].compareTo("domain") == 0) // no sub-domain in hostname
                         profile = request.getPathInfo(); // path should be username
                         else
                         profile = sSplit[0]; // sub-domain should be the username
                        
                        
                         response.setContentType("text/html");
                         PrintWriter out = response.getWriter();
                         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
                         out.println("<HTML>");
                         out.println("<HEAD><TITLE>Member Bio for " + profile + "</TITLE></HEAD>");
                         out.println("<BODY>");
                         out.println("<h1>Member Bio for " + profile + "</h1>");
                         out.println("</BODY>");
                         out.println("</HTML>");
                         out.flush();
                         out.close();
                         }
                        
                         public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                         doGet(request, response);
                         }
                        


                        • 9. Re: ROOT.war, root context, wildcard virtual hosts?
                          maheshkudva

                          Hi Teej
                          I am also having the same problem. Can you let me know if you have any answers to this. In my case, the web apps are WAR files and I want to have the similar action.

                          http://test.com/library (Works perfectly)

                          http://library.test.com (never worked)

                          My DNS points to the correct IP where JBoss 4.0 is hosted.

                          I understand that I need to bind the WAR file to the virtual host and domain library.test.com.


                          But the question is how.

                          My server.xml:

                          <Host name="library"
                           autoDeploy="false" deployOnStartup="false" deployXML="false">
                          <Alias>library.robosoft.co.in</Alias>
                          </Host>
                          



                          My WEB-INF/jboss-web.xml:

                          <virtual-host>library.test.com</virtual-host>
                          <context-root>/library</context-root>
                          



                          This is one set. I need to deploy at least 5 such WAR files.


                          I also placed the jsp files as mentioned in the Web-Apps lib folder and jboss lib folder.

                          Still nothing rather it works in the following fashion:

                          http://test.com/library/library

                          How do I go about to make http://test.com/library work as http://library.test.com


                          Regards
                          Mahesh S Kudva

                          • 10. Re: ROOT.war, root context, wildcard virtual hosts?
                            maheshkudva

                            Hi

                            The domain name is uniqui as test.com. I made some mistake in my earlier post.

                            • 11. Re: ROOT.war, root context, wildcard virtual hosts?
                              maheshkudva

                              Thanks to all.

                              This setup has been tested on Apache2+JBoss+mod_jk-1.2.14_for MacOSX. And am sure it will work on other platforms as well. This setup also handles Apache related webapps..

                              Make the required entries in the DNS

                              webapp.war: Extract the war file using zip and rename the folder
                              with .war extension. Please put it in your deployment folder.

                              mod-jk.so: Obtain the modjk.so library file from www.apache.org and place then in the modules folder.

                              Apache-Virtual Host config
                              ----------------------

                              NameVirtualHost *.*.*.*:80
                              
                              <VirtualHost *.*.*.*:80>
                               ServerName webapp.robosoft.co.in
                               ServerAlias www.webapp.robosoft.co.in
                               ServerAdmin root@localhost
                               DocumentRoot /Volumes/Extra/jboss/server/default/deploy/webapp.war
                               JkMount /* loadbalancer
                               DirectoryIndex index.html index.jsp
                               ErrorLog logs/webapp-error_log
                               CustomLog logs/webapp-access_log common
                              </VirtualHost>
                              

                              -------------------------------------------------------------------------
                              mod-jk.conf
                              ================
                              LoadModule jk_module /opt/apache2/modules/mod_jk.so
                              
                              JkWorkersFile /opt/apache2/conf/workers.properties
                              JkLogFile /opt/apache2/logs/mod_jk.log
                              JkLogLevel info
                              JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
                              JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
                              JkRequestLogFormat "%w %V %T"
                              JkMount /webapp.domain.com/*.jsp loadbalancer
                              JkMountFile /opt/apache2/conf/uriworkermap.properties
                              JkShmFile /opt/apache2/logs/jk.shm
                              <Location /jkstatus/>
                               JkMount status
                               Allow from all
                              </Location>
                              

                              --------------------------------------------------------------------------
                              Server.xml
                              ---------

                              <Host name="webapp.domain.com" debug="0" appBase="deploy"
                              unpackWARs="true">
                               <Alias>www.webapp.domain.com</Alias>
                               <Logger className="org.apache.catalina.logger.FileLogger"
                               directory="logs" prefix="webapp_log1." suffix=".log"
                              timestamp="true"/>
                               <Context path=""
                              docBase="${jboss.server.home.dir}/deploy/webapp.war" debug="0"
                              reloadable="true"/>
                               </Host>
                              

                              --------------------------------------------------------------------------
                              --
                              uriworkermap.properties
                              ================
                              /jmx-console=loadbalancer
                              /jmx-console/*=loadbalancer
                              /web-console=loadbalancer
                              /web-console/*=loadbalancer
                              /webapp.domain.com/*.jsp
                              

                              --------------------------------------------------------------------------
                              --
                              workers.properties
                              ================
                              worker.list=loadbalancer,status
                              
                              worker.webapp.port=8009
                              worker.webapp.host=webapp.domain.com
                              worker.webapp.type=ajp13
                              worker.webapp.lbfactor=1
                              worker.webapp.cachesize=10
                              
                              worker.loadbalancer.type=lb
                              worker.loadbalancer.balance_workers=library
                              worker.loadbalancer.sticky_session=1
                              worker.loadbalancer.local_worker_only=1
                              worker.list=loadbalancer
                              
                              worker.status.type=status
                              


                              Regards & Thanks
                              ================
                              Mahesh S Kudva
                              Network Analyst
                              Robosoft Technologies