This chapter describes the steps for integrating a third party Web container into the JBoss application server framework. A Web container is a J2EE server component that enables access to servlets and JSP pages. The most widely used servlet container is Tomcat, and this is the default web container used by JBoss.
Integrating a servlet container into JBoss consists of mapping web-app.xml JNDI information into the JBoss JNDI namespace using an optional jboss-web.xml descriptor as well as delegating authentication and authorization to the JBoss security layer. The org.jboss.web.AbstractWebContainer class exists to simplify these tasks. The focus of the first part of this chapter is how to integrate a Web container using the AbstractWebContainer class. The chapter concludes with a discussion on configuration topices like the use of secure socket layer (SSL) encryption with the JBoss/Tomcat bundle, as well as how to configure Apache with the JBoss/Tomcat bundle.
The org.jboss.web.AbstractWebContainer class is an implementation of a template pattern for web container integration into JBoss. Web container providers wishing to integrate their container into a JBoss server should create a subclass of AbstractWebContainer and provide the web container specific setup and war deployment steps. The AbstractWebContainer provides support for parsing the standard J2EE web.xml web application deployment descriptor JNDI and security elements as well as support for parsing the JBoss specific jboss-web.xml descriptor. Parsing of these deployment descriptors is performed to generate an integrated JNDI environment and security context. We have already seen the most of the elements of the jboss-web.xml descriptor in other chapters. See The complete jboss-web.xml descriptor DTD.. provides an overview of the jboss-web.xml descriptor DTD for reference. The complete DTD with comments can be found in the JBOSS_DIST/docs/dtd.
The two elements that have not been discussed are the context-root and virtual-host. The context-root element allows one to specify the prefix under which web application is located. This is only applicable to stand-alone web application deployment as a WAR file. Web applications included as part of an EAR must set the root using the context-root element of the EAR application.xml descriptor. The sample jboss-web.xml descriptor shown in See A sample jboss-web.xml descriptor for mapping a war to the root context. illustrates mapping a war to the root context.
<!-- An empty context root map the war to the root context,
e.g., http://localhost:8080/ -->
The virtual-host element specifies the DNS name of the virtual host to which the web application should be deployed. The details of setting up virtual hosts for servlet contexts depends on the particular servlet container. We will look at examples of using the virtual-host element when we look at the Tomcat servlet containers later in this chapter.
The AbstractWebContainer is an abstract class that implements the org.jboss.web.AbstractWebContainerMBea n interface used by the JBoss J2EE deployer to delegate the task of installing war files needing to be deployed. See Key methods of the AbstractWebContainer class.. presents some of the key AbstractWebContainer methods.
149:public abstract class AbstractWebContainer
150: extends SubDeployerSupport
151: implements AbstractWebContainerMBean
153: public static interface WebDescriptorParser
175: public void parseWebAppDescriptors(ClassLoader loader, WebMetaData metaData) throws Exception;
183: public DeploymentInfo getDeploymentInfo();
267: public boolean accepts(DeploymentInfo sdi)
269: String warFile = sdi.url.getFile();
270: return warFile.endsWith("war") || warFile.endsWith("war/");
396: public synchronized void start(DeploymentInfo di) throws DeploymentException
398: Thread thread = Thread.currentThread();
399: ClassLoader appClassLoader = thread.getContextClassLoader();
402: // Create a classloader for the war to ensure a unique ENC
404: URLClassLoader warLoader = URLClassLoader.newInstance(empty, di.ucl);
405: thread.setContextClassLoader(warLoader);
406: WebDescriptorParser webAppParser = new DescriptorParser(di);
407: String webContext = di.webContext;
410: if( webContext.length() > 0 && webContext.charAt(0) != '/' )
411: webContext = "/" + webContext;
414: URL warURL = di.localUrl != null ? di.localUrl : di.url;
416: if (log.isDebugEnabled())
418: log.debug("webContext: " + webContext);
419: log.debug("warURL: " + warURL);
420: log.debug("webAppParser: " + webAppParser);
423: // Parse the web.xml and jboss-web.xml descriptors
424: WebMetaData metaData = (WebMetaData) di.metaData;
425: parseMetaData(webContext, warURL, di.shortName, metaData);
426: WebApplication warInfo = new WebApplication(metaData);
427: warInfo.setDeploymentInfo(di);
428: performDeploy(warInfo, warURL.toString(), webAppParser);
429: deploymentMap.put(warURL.toString(), warInfo);
431: // Generate an event for the startup
434: catch(DeploymentException e)
440: throw new DeploymentException("Error during deploy", e);
444: thread.setContextClassLoader(appClassLoader);
461: protected abstract void performDeploy(WebApplication webApp, String warUrl,
462: WebDescriptorParser webAppParser) throws Exception;
469: public synchronized void stop(DeploymentInfo di)
470: throws DeploymentException
472: URL warURL = di.localUrl != null ? di.localUrl : di.url;
473: String warUrl = warURL.toString();
477: // Remove the web application ENC...
478: deploymentMap.remove(warUrl);
480: // Generate an event for the stop
483: catch(DeploymentException e)
489: throw new DeploymentException("Error during deploy", e);
496: protected abstract void performUndeploy(String warUrl) throws Exception;
540: public void setConfig(Element config)
551: protected void parseWebAppDescriptors(DeploymentInfo di, ClassLoader loader,
555: log.debug("AbstractWebContainer.parseWebAppDescriptors, Begin");
556: InitialContext iniCtx = new InitialContext();
558: Thread currentThread = Thread.currentThread();
559: ClassLoader currentLoader = currentThread.getContextClassLoader();
562: // Create a java:comp/env environment unique for the web application
563: log.debug("Creating ENC using ClassLoader: "+loader);
564: ClassLoader parent = loader.getParent();
568: parent = parent.getParent();
570: currentThread.setContextClassLoader(loader);
571: metaData.setENCLoader(loader);
572: envCtx = (Context) iniCtx.lookup("java:comp");
574: // Add a link to the global transaction manager
575: envCtx.bind("UserTransaction", new LinkRef("UserTransaction"));
576: log.debug("Linked java:comp/UserTransaction to JNDI name: UserTransaction");
577: envCtx = envCtx.createSubcontext("env");
581: currentThread.setContextClassLoader(currentLoader);
584: Iterator envEntries = metaData.getEnvironmentEntries();
585: log.debug("addEnvEntries");
586: addEnvEntries(envEntries, envCtx);
587: Iterator resourceEnvRefs = metaData.getResourceEnvReferences();
588: log.debug("linkResourceEnvRefs");
589: linkResourceEnvRefs(resourceEnvRefs, envCtx);
590: Iterator resourceRefs = metaData.getResourceReferences();
591: log.debug("linkResourceRefs");
592: linkResourceRefs(resourceRefs, envCtx);
593: Iterator ejbRefs = metaData.getEjbReferences();
594: log.debug("linkEjbRefs");
595: linkEjbRefs(ejbRefs, envCtx, di);
596: Iterator ejbLocalRefs = metaData.getEjbLocalReferences();
597: log.debug("linkEjbLocalRefs");
598: linkEjbLocalRefs(ejbLocalRefs, envCtx, di);
599: String securityDomain = metaData.getSecurityDomain();
600: log.debug("linkSecurityDomain");
601: linkSecurityDomain(securityDomain, envCtx);
602: log.debug("AbstractWebContainer.parseWebAppDescriptors, End");
605: protected void addEnvEntries(Iterator envEntries, Context envCtx)
606: throws ClassNotFoundException, NamingException
617: protected void linkResourceEnvRefs(Iterator resourceEnvRefs, Context envCtx)
651: protected void linkResourceRefs(Iterator resourceRefs, Context envCtx)
685: protected void linkEjbRefs(Iterator ejbRefs, Context envCtx, DeploymentInfo di)
719: protected void linkEjbLocalRefs(Iterator ejbRefs, Context envCtx, DeploymentInfo di)
774: protected void linkSecurityDomain(String securityDomain, Context envCtx)
840: public String[] getCompileClasspath(ClassLoader loader)
Lines 267-271 correspond to the accepts method implemented by JBoss deployers to indicate which type of deployments they accepts. The AbstractWebContainer handles the deployments of WARs as jars or unpacked directories.
Lines 396-446 correspond to the start method. This method is a template pattern method implementation. The argument to the deploy method is the WAR deployment info object. This contains the URL to the WAR, the UnifiedClassLoader for the WAR, the parent archive such as an EAR, and the J2EE application.xml context-root if the WAR is part of an EAR.
The first step of the start method is to save the current thread context ClassLoader and then create another URLClassCloader (warLoader) using the WAR UnifiedClassLoader as its parent. This warLoader is used to ensure a unique JNDI ENC (enterprise naming context) for the WAR will be created. This is done by the code on lines 403-404. Chapter 3 mentioned that the java:comp context's uniqueness was determined by the ClassLoader that created the java:comp context. The warLoader ClassLoader is set as the current thread context ClassLoader , on line 405, before the performDeploy call is made. Next, the web.xml and jboss-web.xml descriptors are parsed by calling parseMetaData on line 425. Next, the Web container-specific subclass is asked to perform the actual deployment of the WAR through the performDeploy call on line 429. The WebApplication object for this deployment is stored in the deployed application map using the warUrl as the key on line 429. The final step at line 444 is to restore the thread context ClassLoader to the one that existed at the start of the method.
Lines 461-462 give the signature for the abstract performDeploy method. This method is called by the start method and must be overridden by subclasses to perform the Web container specific deployment steps. A WebApplication is provided as an argument, and this contains the metadata from the web.xml descriptor, and the jboss-web.xml descriptor. The metadata contains the context-root value for the web module from the J2EE application.xml descriptor, or if this is a stand-alone deployment, the jboss-web.xml descriptor. The metadata also contains any jboss-web.xml descriptor virtual-host value. On return from performDeploy , the WebApplication must be populated with the ClassLoader of the servlet context for the deployment. The warUrl argument is the string for the URL of the Web application WAR to deploy. The webAppParser argument is a callback handle the subclass must use to invoke the parseWebAppDescriptors method to set up the Web application JNDI environment. This callback provides a hook for the subclass to establish the Web application JNDI environment before any servlets are created that are to be loaded on startup of the WAR. A subclass' performDeploy method implementation needs to be arranged so that it can call the parseWebAppDescriptors before starting any servlets that need to access JNDI for JBoss resources like EJBs, resource factories, and so on. One important setup detail that needs to be handled by a subclass implementation is to use the current thread context ClassLoader as the parent ClassLoader for any Web container-specific ClassLoader created. Failure to do this results in problems for Web applications that attempt to access EJBs or JBoss resources through the JNDI ENC.
Lines 469-717 correspond to the stop method. This is a template pattern method implementation. Line 476 of this method calls the subclass performUndeploy method to perform the container-specific undeployment steps. Next, at line 478, the warUrl is unregistered from the deployment map. The warUrl argument is the string URL of the WAR as originally passed to the performDeploy method.
Line 496 gives the signature of the abstract performUndeploy method. This method is called as part of the stop method template as shown on line 476. A call to performUndeploy asks the subclass to perform the Web container-specific undeployment steps.
Lines 540-542 correspond to the setConfig method. This method is a stub method that subclasses can override if they want to support an arbitrary extended configuration beyond that which is possible through MBean attributes. The config argument is the parent DOM element for an arbitrary hierarchy given by the child element of the Config attribute in the mbean element specification of the jboss-service.xml descriptor of the web container service. You'll see an example use of this method and config value when you look at the MBean that supports embedding Tomcat into JBoss.
Lines 551- 603 correspond to the parseWebAppDescriptors method. This is invoked from within the subclass performDeploy method when it invokes the webAppParser.parseWebAppDescriptors callback to setup Web application ENC (java:comp/env) env-entry, resource-env-ref, resource-ref, local-ejb-ref and ejb-ref element values declared in the web.xml descriptor. The creation of the env-entry values does not require a jboss-web.xml descriptor. The creation of the resource-env-ref, resource-ref, and ejb-ref elements does require a jboss-web.xml descriptor for the JNDI name of the deployed resources/EJBs. Because the ENC context is private to the Web application, the Web application ClassLoader is used to identify the ENC. The loader argument is the ClassLoader for the Web application, and may not be null. The metaData argument is the WebMetaData argument passed to the subclass performDeploy method. The implementation of the parseWebAppDescriptors uses the metadata information from the WAR deployment descriptors and then creates the JNDI ENC bindings by calling methods shown on lines 584-601.
The addEnvEntries method on lines 605-615 creates the java:comp/env Web application env-entry bindings that were specified in the web.xml descriptor.
The linkResourceEnvRefs method on lines 617-649 maps the java:comp/env/xxx Web application JNDI ENC resource-env-ref web.xml descriptor elements onto the deployed JNDI names using the mappings specified in the jboss-web.xml descriptor.
The linkResourceRefs method on lines 651-683 maps the java:comp/env/xxx Web application JNDI ENC resource-ref web.xml descriptor elements onto the deployed JNDI names using the mappings specified in the jboss-web.xml descriptor.
The linkEjbRefs method on lines 685-717 maps the java:comp/env/ejb Web application JNDI ENC ejb-ref web.xml descriptor elements onto the deployed JNDI names using the mappings specified in the jboss-web.xml descriptor.
The linkEjbLocalRefs method on lines 719-763 maps the java:comp/env/ejb Web application JNDI ENC ejb-local-ref web.xml descriptor elements onto the deployed JNDI names using the ejb-link mappings specified in the web.xml descriptor.
The linkSecurityDomain method on lines 774-794 creates a java:comp/env/security context that contains a securityMgr binding pointing to the AuthenticationManager implementation and a realmMapping binding pointing to the RealmMapping implementation that is associated with the security domain for the Web application. Also created is a subject binding that provides dynamic access to the authenticated Subject associated with the request thread. If the jboss-web.xml descriptor contained a security-domain element, the bindings are javax.naming.LinkRef s to the JNDI name specified by the security-domain element, or subcontexts of this name. If there was no security-domain element, the bindings are to org.jboss.security.plugins.NullSecurityManager instance that simply allows all authentication and authorization checks.
Lines 840-864 correspond to the getCompileClasspath method. This is a utility method available for Web containers to generate a classpath that walks up the ClassLoader chain starting at the given loader and queries each ClassLoader for the URLs it serves to build a complete classpath of URL strings. This is needed by some JSP compiler implementations (Jasper for one) that expect to be given a complete classpath for compilation.
To integrate a web container into JBoss you need to create a subclass of AbstractWebContainer and implement the required performDeploy(WebApplication, String, WebDescriptorParser) and performUndeploy(String) methods as described in the preceding section. The following additional integration points should be considered as well.
Although this issue was noted in the performDeploy method description, we'll repeat it here since it is such a critical detail. During the setup of a WAR container, the current thread context ClassLoader must be used as the parent ClassLoader for any web container specific ClassLoader that is created. Failure to do this will result in problems for web applications that attempt to access EJBs or JBoss resources through the JNDI ENC.
JBoss uses the Apache log4j logging API as its internal logging API. For a web container to integrate well with JBoss it needs to provide a mapping between the web container logging abstraction to the log4j API. As a subclass of AbstractWebContainer , your integration class has access to the log4j interface via the super.log instance variable or equivalently, the superclass getLog method. This is an instance of the org.jboss.logging.Logger class that wraps the log4j category. The name of the log4j category is the name of the container subclass.
Ideally both web application and EJB authentication and authorization are handled by the same security manager. To enable this for your web container you must hook into the JBoss security layer. This typically requires a request interceptor that maps from the web container security callouts to the JBoss security API. Integration with the JBossSX security framework is based on the establishment of a "java:comp/env/security" context as described in the linkSecurityDomain method comments in the previous section. The security context provides access to the JBossSX security manager interface implementations associated with the web application for use by subclass request interceptors. An outline of the steps for authenticating a user using the security context is presented in See A pseudo-code description of authenticating a user via the JBossSX API and the java:comp/env/security JNDI context.. in quasi pseudo-code. See A pseudo-code description of authorization a user via the JBossSX API and the java:comp/env/security JNDI context.. provides the equivalent process for the authorization of a user.
// Get the username and password from the request context...
HttpServletRequest request = ...;
String username = getUsername(request);
String password = getPassword(request);
// Get the JBoss security manager from the ENC context
InitialContext iniCtx = new InitialContext();
AuthenticationManager securityMgr = (AuthenticationManager)
iniCtx.lookup("java:comp/env/security/securityMgr");
SimplePrincipal principal = new SimplePrincipal(username);
if( securityMgr.isValid(principal, password) )
// Indicate the user is allowed access to the web content...
// Propagate the user info to JBoss for any calls into made by the servlet
SecurityAssociation.setPrincipal(principal);
SecurityAssociation.setCredential(password.toCharArray());
// Get the username & required roles from the request context...
HttpServletRequest request = ...;
String username = getUsername(request);
String[] roles = getContentRoles(request);
// Get the JBoss security manager from the ENC context
InitialContext iniCtx = new InitialContext();
RealmMapping securityMgr = (RealmMapping)
iniCtx.lookup("java:comp/env/security/realmMapping");
SimplePrincipal principal = new SimplePrincipal(username);
Set requiredRoles = new HashSet(java.util.Arrays.asList(roles));
if( securityMgr.doesUserHaveRole(principal, requiredRoles) )
// Indicate user has the required roles for the web content...
In this section we'll discuss configuration issues specific to the JBoss/Tomcat-4.x integration bundle. The Tomcat-4.1.x release, which is also known by the name Catalina, is the latest Apache Java servlet container. It supports the Servlet 2.3 and JSP 1.2 specifications. The JBoss/Tomcat integration layer is controlled by the JBoss MBean service configuration. The MBean used to embed the Tomcat-4.1.x series of web containers is the org.jboss.web.tomcat.tc4.EmbeddedTomcatService service, and it is a subclass of the AbstractWebContainer class. Its configurable attributes include:
The integration of Tomcat with JBoss depends on the jboss-service.xml descriptor found in the deploy/jbossweb-tomcat.sar/META-INF directories of the default and all configuration file sets. You will only find this descriptor in the bundled release of JBoss/Tomcat. This bundle also include the Tomcat distribution as the jbossweb-tomcat41.sar directory. Currently this is the jakarta-tomcat-4.1.29-LE-jdk14 distribution.
This section provides an overview of the Tomcat configuration elements that may appear as child elements of the EmbeddedTomcatService Config attribute.
The Server element is the root element of the Tomcat servlet container configuration. There are no attributes of this element that are supported by the embedded service.
A Service is a container of one or more Connectors and a single Engine. The only supported attribute is:
A Connector element configures a transport mechanism that allows clients to send requests and receive responses from the Service it is associated with. Connectors forward requests to the Service Engine and return the results to the requesting client. There are currently three connector implementations, HTTP, AJP and Warp. All connectors support these attributes:
The HTTP connector is an HTTP 1.1 protocol connector that allows Tomcat to function as a stand-alone web server. This is now deprecated in favor of the Coyote connector, but this is the only connector which currently works with the JBoss SSL socket factory that integrates with the JBossSecurityDomain service. The key attributes specific to this connector are:
proxyName: If this Connector is being used in a proxy configuration, configure this attribute to specify the server name to be returned for calls to request.getServerName(). See Proxy Support for more information.
Additional attribute descriptions may be found in the Tomcat website document: http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/http11.html
The CoyoteConnector is the default HTTP/1.1 connector that enables Catalina to function as a stand-alone web server, in addition to its ability to execute servlets and JSP pages. In addition, it can be configured to handle the AJP 1.3 protocols uses with the Apache mod_jk and mod_jk2 modules. The supported attributes are:
Additional information on the Coyote connector may be found on the this Tomcat site page: http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/coyote.html .
Each Service must have a single Engine configuration. An Engine handles the requests submitted to a Service via the configured connectors. The child elements supported by the embedded service include Host, Logger, DefaultContext, Valve and Listener. The supported attributes include:
Additional information on the Engine element may be found in the Tomcat website document http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/engine.html .
A Host element represents a virtual host configuration. It is a container for web applications with a specified DNS hostname. The child elements supported by the embedded service include Alias , Logger , DefaultContext , Valve and Listener . The supported attributes include:
Additional information on the Host element may be found in the Tomcat website document http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/host.html .
The DefaultContext element is a configuration template for web application contexts. It may be defined at the Engine or Host level. The child elements supported by the embedded service include WrapperLifecycle , InstanceListener , WrapperListener , and Manager . The supported attributes include:
The Logger element specifies a logging configuration for Engine , Host s, and DefaultContext s. The supported attributes include:
A Valve element configures a request pipeline element. A Valve is an implementation of the org.apache.catalina.Valve interface, and several standard Valve s are available for use. The most commonly used Valve allows one to log access requests. Its supported attributes include:
Additional information on the Valve element and the available valve implementations may be found in the Tomcat website document http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/valve.html .
A Listener element configures a component life-cycle listener. You add a life-cycle listener using a Listener element with a className attribute giving the fully qualified name of the org.apache.catalina.LifecycleListener interface along with any additional properties supported by the listener implementation.
There are a few ways one can configure HTTP over SSL for the embedded Tomcat servlet container.The main difference is whether or not you use the JBoss specific connector socket factory that allows one to obtain the JSSE server certificate information from a JBossSX SecurityDomain. This requires establishing a SecurityDomain using the org.jboss.security.plugins.JaasSecurityDomain MBean. These two steps are similar to the procedure we used in Chapter 8 to enable RMI with SSL encryption. A jbossweb-tomcat41.sar/META-INF/jboss-service.xml configuration file that illustrates the setup of only an SSL connector via this approach is given in See The JaasSecurityDoman and EmbeddedCatalinaSX MBean configurations for setting up Tomcat-4.x to use SSL as its primary connector protocol...This configuration includes the same JaasSecurityDomain setup as Chapter 8, but since the descriptor is not being deployed as part of a SAR that includes the chap8.keystore, you need to copy the chap8.keystore to the server/default/conf directory.
<?xml version="1.0" encoding="UTF-8"?>
<!-- An example tomcat config that only uses SSL connectors.
<!-- The service configuration for the embedded Tomcat4 web container
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
name="Security:name=JaasSecurityDomain,domain=RMI+SSL">
<arg type="java.lang.String" value="RMI+SSL"/>
<attribute name="KeyStoreURL">chap8.keystore</attribute>
<attribute name="KeyStorePass">rmi+ssl</attribute>
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<!-- Get the flag indicating if the normal Java2 parent first class
loading model should be used over the servlet 2.3 web container first
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<!-- A flag indicating if the JBoss Loader should be used. This loader
uses a unified class loader as the class loader rather than the tomcat
<attribute name="UseJBossWebLoader">true</attribute>
<!-- The name of the request attribute under with the authenticated JAAS
Subject is stored on successful authentication. If null or empty then
the Subject will not be stored.
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="localhost">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="localhost_access" suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<!-- This valve clears any caller identity set by the realm
and provides access to the realm about the existence of an
authenticated caller to allow a web app to run with a realm
that support unauthenticated identities. It also establishes
any run-as principal for the servlet being accessed.
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<!-- SSL/TLS Connector configuration using the SSL domain keystore -->
<Connector className = "org.apache.catalina.connector.http.HttpConnector"
port = "443" scheme = "https" secure = "true">
<Factory className = "org.jboss.web.tomcat.security.SSLServerSocketFactory"
securityDomainName = "java:/jaas/RMI+SSL" clientAuth = "false"
A quick test of this config can be made by accessing the JMX console web application using this URL https://localhost/jmx-console/index.jsp .
Note: if your running on a *nix system (Linux, Solaris, OS X) that only allows root to open ports below 1024 you will need to change the port number above to something like 8443.
Alternatively, if one wants to support both access using non-SSL and SSL, you can do this by adding another connector configuration to the EmbeddedCatalinaService41 MBean. A jboss-service.xml configuration file that illustrates such a setup of SSL is given in See The JaasSecurityDoman and EmbeddedCatalinaSX MBean configurations for setting up Tomcat-4.x to use both non-SSL and SSL enabled HTTP connectors...
<?xml version="1.0" encoding="UTF-8"?>
<!-- An example tomcat config that only uses both non-SSL and SSL connectors.
<!-- The service configuration for the embedded Tomcat4 web container
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
name="Security:name=JaasSecurityDomain,domain=RMI+SSL">
<arg type="java.lang.String" value="RMI+SSL"/>
<attribute name="KeyStoreURL">chap8.keystore</attribute>
<attribute name="KeyStorePass">rmi+ssl</attribute>
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<!-- Get the flag indicating if the normal Java2 parent first class
loading model should be used over the servlet 2.3 web container first
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<!-- A flag indicating if the JBoss Loader should be used. This loader
uses a unified class loader as the class loader rather than the tomcat
<attribute name="UseJBossWebLoader">true</attribute>
<!-- The name of the request attribute under with the authenticated JAAS
Subject is stored on successful authentication. If null or empty then
the Subject will not be stored.
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="localhost">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="localhost_access" suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<!-- This valve clears any caller identity set by the realm
and provides access to the realm about the existence of an
authenticated caller to allow a web app to run with a realm
that support unauthenticated identities. It also establishes
any run-as principal for the servlet being accessed.
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<!-- HTTP Connector configuration -->
<Connector className = "org.apache.catalina.connector.http.HttpConnector"
port = "8080" redirectPort = "443"/>
<!-- SSL/TLS Connector configuration using the SSL domain keystore -->
<Connector className = "org.apache.catalina.connector.http.HttpConnector"
port = "443" scheme = "https" secure = "true">
<Factory className = "org.jboss.web.catalina.security.SSLServerSocketFactory"
securityDomainName = "java:/jaas/RMI+SSL" clientAuth = "false"
You can also setup SSL using the standard Coyote connector. This connector does not support custom SSL socket factories well however and the org.jboss.web.catalina.security.SSLServerSocketFactory cannot be used. Instead you need to add a Factory element to the Coyote Connector, to set up the required SSL socket factory. The Factory element supports the following attributes:
A jboss-service.xml configuration file that illustrates such a setup of SSL is given in See An EmbeddedCatalinaService41 MBean configurations for setting up Tomcat-4.1.x to use SSL enabled HTTP with the Coyote connector...
<?xml version="1.0" encoding="UTF-8"?>
<!-- An embedded Tomcat4.1.x web container that uses only an SSL/Coyote connector -->
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<!-- Get the flag indicating if the normal Java2 parent first class
loading model should be used over the servlet 2.3 web container first
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<!-- A flag indicating if the JBoss Loader should be used. This loader
uses a unified class loader as the class loader rather than the tomcat
<attribute name="UseJBossWebLoader">true</attribute>
<!-- The name of the request attribute under with the authenticated JAAS
Subject is stored on successful authentication. If null or empty then
the Subject will not be stored.
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="localhost">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="localhost_access" suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<!-- This valve clears any caller identity set by the realm
and provides access to the realm about the existence of an
authenticated caller to allow a web app to run with a realm
that support unauthenticated identities. It also establishes
any run-as principal for the servlet being accessed.
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<!-- SSL/TLS Connector configuration -->
<Connector className = "org.apache.coyote.tomcat4.CoyoteConnector"
address="${jboss.bind.address}" port = "8443" scheme = "https" secure = "true">
<Factory className = "org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
<depends>jboss:service=TransactionManager</depends>
All approaches work so which you choose is a matter of preference, with the caveat that the CoyoteConnector is the preferred and more performant connector at this point. Note that if you try to test this configuration using the self-signed certificate from the Chapter 8 chap8.keystore and attempt to access content over an https connection, your browser should display a warning dialog indicating that it does not trust the certificate authority that signed the certificate of the server you are connecting to. For example, when the first configuration example was tested, IE 5.5 showed the initial security alert dialog listed in See The Internet Explorer 5.5 security alert dialog... See The Internet Explorer 5.5 SSL certificate details dialog.. shows the server certificate details. This is the expected behavior as anyone can generate a self-signed certificate with any information they want, and a web browser should warn you when such a secure site is encountered.
As of the 2.4.5 release, support for virtual hosts has been added to the servlet container layer. Virtual hosts allow you to group web applications according to the various DNS names by which the machine running JBoss is known. As an example, consider the jbossweb-tomcat41.sar/META-INF/jboss-service.xml configuration file given in See An example virtual host configuration... This configuration defines a default host named localhost and a second host named vhost1.mydot.com. The vhost2.mydot.com also has the alias www.mydot.com associated with it.
<?xml version="1.0" encoding="UTF-8"?>
<!-- An example vhost configuration -->
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<!-- Get the flag indicating if the normal Java2 parent first class
loading model should be used over the servlet 2.3 web container first
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<!-- A flag indicating if the JBoss Loader should be used. This loader
uses a unified class loader as the class loader rather than the tomcat
<attribute name="UseJBossWebLoader">true</attribute>
<!-- The name of the request attribute under with the authenticated JAAS
Subject is stored on successful authentication. If null or empty then
the Subject will not be stored.
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="vhost1">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Alias>vhost1.mydot.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<Alias>vhost2.mydot.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<!-- A HTTP/1.1 Connector on port 8080 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
address="${jboss.bind.address}" port="8080" minProcessors="5"
maxProcessors="100" enableLookups="true" acceptCount="10" debug="0"
connectionTimeout="20000" useURIValidationHack="false"/>
<depends>jboss:service=TransactionManager</depends>
When a WAR is deployed, it will be by default associated with the virtual host whose name matches the defaultHost attribute of the containing Engine . To deploy a WAR to a specific virtual host you need to use the jboss-web.xml descriptor and the virtual-host element. For example, to deploy a WAR to the virtual host www.mydot.com virtual host alias, the following jboss-web.xml descriptor would be need to be included in the WAR WEB-INF directory. This demonstrates that an alias of the virtual host can be used in addition to the Host name attribute value.
<context-root>/</context-root>
You can serve external static files from web apps by adding an external directory content to the Tomcat configuration. For example, to serve shared images from a C:/tmp/images directory, edit jbossweb-tomcat41.sar/META-INF/jboss-service.xml and add a Context entry to the Config element as shown in See An example configuration for including external static content..
<?xml version="1.0" encoding="UTF-8"?>
<!-- An example tomcat config that includes an external context.
With this you can reference the /images path from any war deployed
to the Host. For example, a test-ex.war index.html page accessible
at http://localhost/test-ex/index.html that includes images from
<li><img src="/images/img1.jpg" alt="Image1"></li>
<li><img src="/images/img1.jpg" alt="Image2"></li>
<li><img src="/images/img1.jpg" alt="Image3"></li>
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<attribute name="UseJBossWebLoader">true</attribute>
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="localhost">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="localhost_access" suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<!-- This valve clears any caller identity set by the realm
and provides access to the realm about the existence of an
authenticated caller to allow a web app to run with a realm
that support unauthenticated identities. It also establishes
any run-as principal for the servlet being accessed.
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true">
<!-- Add a static context /images using directory /tmp/images -->
<Context path="/images" docBase="/tmp/images" debug="1"
reloadable="true" crossContext="true">
<!-- A HTTP/1.1 Connector on port 8080 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
address="${jboss.bind.address}" port="8080" minProcessors="5"
maxProcessors="100" enableLookups="true" acceptCount="10" debug="0"
connectionTimeout="20000" useURIValidationHack="false"/>
<depends>jboss:service=TransactionManager</depends>
One thing to note about the docBase attribute on the Context element. This must be seen as an absolute path by the java.io.File object on the platform. This means on win32 platforms that the path must begin with the drive spec, for example, "C:/tmp/images".
To enable the use of Apache as a front-end web server that delegates servlet requests to a JBoss/Tomcat bundle, you need to configure an appropriate connector in the EmbeddedTomcatService MBean definition. For example, to configure the use of the Ajpv13 protocol connector with the Apache mod_jk module, you would use a configuration like that given in See An example EmbeddedTomcatService MBean configuration that supports integration with Apache using the Ajpv13 protocol connector...
<?xml version="1.0" encoding="UTF-8"?>
<!-- An example AJP configuration -->
<mbean code="org.jboss.web.tomcat.tc4.EmbeddedTomcatService"
name="jboss.web:service=WebServer">
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="LenientEjbLink">true</attribute>
<attribute name="UseJBossWebLoader">true</attribute>
<attribute name="SubjectAttributeName">j_subject</attribute>
<Engine name="MainEngine" defaultHost="localhost">
<Logger className="org.jboss.web.tomcat.Log4jLogger"
verbosityLevel="debug" category="org.jboss.web.localhost.Engine"/>
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="localhost_access" suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"/>
<Valve className="org.jboss.web.tomcat.security.SecurityAssociationValve"/>
<!-- Default context parameters -->
<DefaultContext cookies="true" crossContext="true" override="true"/>
<!-- A AJP 1.3 Connector on port 8009 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
address="${jboss.bind.address}" port="8009" minProcessors="5"
maxProcessors="75" enableLookups="true" redirectPort="8443"
acceptCount="10" debug="0" connectionTimeout="20000"
protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"/>
<depends>jboss:service=TransactionManager</depends>
The configuration of the Apache side proceeds as it normally would as bundling Tomcat inside of JBoss does not affect the how Apache interacts with Tomcat. For example, a fragment of an httpd.conf configuration to test the See An example EmbeddedTomcatService MBean configuration that supports integration with Apache using the Ajpv13 protocol connector.. setup with a WAR deployed with a context root of "/jbosstest" might look like:
LoadModule jk_module libexec/mod_jk.so
JkWorkersFile /tmp/workers.properties
Other Apache to Tomcat configurations would follow the same pattern. All that would change it the Connector element definition that is placed into the EmbeddedTomcatService MBean configuration.
As of the JBoss 3.0.1 release, there is support for clustering in the Tomcat embedded service. The steps to setup clustering of Tomcat embedded containers is: