Wednesday Dec 13, 2006

Virtual Hosting Features in GlassFish

Virtual Hosting Features in GlassFish

Virtual Hosting Features in GlassFish

  1. Introduction
  2. This document describes the virtual hosting features available in GlassFish v2.

    Virtual hosting refers to the ability to run several web sites (domains) from a single physical server machine with a single IP address. Each web site is identified by its domain (host) name. HTTP requests are routed to the appropriate domain based on their host name. In order for this name-based form of virtual hosting (also known as shared IP hosting) to work, the DNS must be configured in such a way that each hosted domain name resolves to the server's IP address. Virtual hosting enables ISP/ASP business models.

  3. Isolation levels
  4. In name-based virtual hosting, virtual servers are isolated by their host (domain) names. Each virtual server is assigned a unique host (domain) name, and may also be assigned one or more alias names. The web container will route a request to a virtual server based on the host name in the request URL.

    GlassFish provides one additional level of isolation between virtual servers: at the HTTP port level, which allows virtual servers to be assigned HTTP ports for their exclusive use.

    In GlassFish, it is possible to associate a virtual server with only a subset of the configured HTTP listeners: A virtual server will receive only those requests that were received on any of the HTTP listeners listed in its http-listeners attribute. As a result of this, virtual servers, or groups of them, may be isolated from each other at the HTTP port level by configuring their http-listeners attributes with mutually exclusive sets of HTTP listeners.

    Isolation at the HTTP port level is not supported by Tomcat, where a virtual server is always bound to all HTTP listeners that belong to the same <Service> unit as the <Engine> unit to which the virtual server belongs. (In Tomcat, a <Service> element represents the combination of one or more <Connector> components that share a single <Engine> component for processing incoming requests, where an <Engine> contains one or more <Host> children, each with one or more <Context> children.)

    Example:

    Consider the following request mapping table:

    Protocol

    Domain Name

    Port Number

    URL Prefix

    Target Virtual Server

    http

    mydomain.com

    1111

    http://mydomain.com:1111

    vs-1

    https

    mydomain.com

    2222

    https://mydomain.com:2222

    vs-1

    http

    yourdomain.com

    3333

    http://yourdomain.com:3333

    vs-2

    https

    yourdomain.com

    4444

    https://yourdomain.com:4444

    vs-2



    The above request mapping requirements, which isolate virtual servers vs-1 and vs-2 at both the domain name and HTTP port levels, can be configured very easily in GlassFish, by leveraging the http-listeners attribute of <virtual-server>, as follows:
    
      <http-listener id="http-listener-1" port="1111"/>
    
      <http-listener id="http-listener-2" port="2222" security-enabled="true">
        <ssl cert-nickname="nickname-1"/>
      </http-listener>
    
      <http-listener id="http-listener-3" port="3333"/>
    
      <http-listener id="http-listener-4" port="4444" security-enabled="true">
        <ssl cert-nickname="nickname-2"/>
      </http-listener>
    
      <virtual-server id="vs-1" hosts="mydomain.com"
                      http-listeners="http-listener-1,http-listener-2"/>
    
      <virtual-server id="vs-2" hosts="yourdomain.com"
                      http-listeners="http-listener-3,http-listener-4"/>
    

  5. Root context configuration choices
  6. A virtual server's root context is defined as the context with the empty path (/). Any requests that cannot be mapped to any of the web modules deployed on a virtual server are mapped to the virtual server's root context.

    The physical location of a virtual server's root context is given by the virtual server's docroot property. Each virtual server may be configured with its own individual docroot.

    In GlassFish, it is possible to map a virtual server's root context to one of the virtual server's web modules, by adding a default-web-module attribute to the virtual server's <virtual-server> entry and having its value reference the selected web module.

    A virtual server's default web module "shadows" the virtual server's docroot, with the effect that any requests that cannot be mapped to any of the web modules deployed on the virtual server will now be mapped to the virtual server's default web module instead of the virtual server's docroot. In other words, a web module that has been designated as a virtual server's default web module will serve any requests that match its context path plus any requests that map to the virtual server's root context.

    A virtual server's docroot remains shadowed for as long as the virtual server declares a default web module. Once a virtual server's default-web-module attribute has been removed, the virtual server's docroot will be reinstantiated as the virtual server's root context.

    The default-web-module mechanism is a convenient way for having a single web module occupy both its designated context path as well as the virtual server's root context.

  7. Alternate docroots
  8. In GlassFish, a virtual server may specify alternate docroots in addition to its main docroot. Each alternate docroot is associated with one or more URI patterns. An alternate docroot is selected over the main docroot if the request matches one of its URI patterns. Both path (prefix) and extension matches are supported.

    For example, it is possible to configure a virtual server in such a way that any requests (with an empty context path) whose URI starts with /images/\* will be mapped to one alternate docroot, whereas any requests (with an empty context path) whose URI ends in \*.jsp will be mapped to a different alternate docroot. All other requests (with an empty context path) will be mapped to the virtual server's main docroot.

    If a request matches multiple alternate docroot URI patterns, the following precedence order is used:

    • Exact match
    • Longest path match
    • Extension match

    Alternate docroots allow virtual servers to share a subset of their docroot resources.

    See my blog for additional details and examples.

  9. Security
    1. Single Sign On
    2. Single Sign On (SSO) enables web applications to share client authentication state. SSO is enabled at the virtual server level (and configured as a virtual server property). With SSO, a user who successfully authenticates to one web application becomes implicitly logged in to any other web application (deployed on the same virtual server) that shares the same authentication realm.

    3. Security realm
    4. In many cases, it is useful to configure a security realm at the virtual server level, with the expectation that this security realm apply to all web modules deployed on the virtual server.

      GlassFish supports this requirement, by defining a property named authRealm at the <virtual-server> level, whose value must be the name of an authentication realm declared in domain.xml.

      Standalone web modules (that is, those not bundled in an EAR file) inherit the realm referenced by the virtual server on which they are deployed, unless they specify a realm name in their web.xml deployment descriptor, which takes precedence.

      See my blog for additional details.

    5. Security credentials
    6. GlassFish allows HTTP(S) listeners to be assigned to a virtual server (or group of virtual servers) for its (their) exclusive use (see the earlier section that talks about isolation levels). Ideally, the HTTPS listeners assigned to one group of virtual servers will have their security credentials (i.e., private keys and supporting certificate chains) separated from the security credentials of a different set of HTTPS listeners serving a different group of virtual servers.

      GlassFish currently supports only a single keystore per server instance, which means the security credentials of all of the instance's HTTPS listeners must be stored in the same keystore, and may be differentiated by an alias name (cert-nickname) only. There has been an enhancement filed against GlassFish (see Issue 657) to support multiple key- and truststores per server instance.

  10. Dynamic reconfiguration
  11. Virtual servers, including their attributes and properties, are dynamically reconfigurable, that is, the creation or deletion of a virtual server, or any changes to its attributes or properties, do not require a server restart in order to take effect.

Wednesday Nov 29, 2006

New Support for Virtual Server Realms

New Support for Virtual Server Realms

New Support for Virtual Server Realms

In an ISP/ASP environment, it is often useful to be able to configure a security realm at the virtual server level, with the expectation that this security realm apply to all web applications deployed on the virtual server.

GlassFish v2-b26 supports this requirement, by introducing a new property named "authRealm" at the <virtual-server> level, whose value must be the name of an authentication realm declared in domain.xml.

Standalone web applications (that is, those not bundled in an EAR file) now inherit the realm referenced by the "authRealm" property (if any) of the virtual server on which they are deployed, unless they specify a realm in their web.xml deployment descriptor, which takes precedence.

Thursday Oct 05, 2006

New Support for Virtual Directory Mappings

New Support for Virtual Directory Mappings

New Support for Virtual Directory Mappings

In GlassFish, every virtual server has a docroot property, which points to the local directory that will be used to serve resources for requests that cannot be mapped to any of the web contexts deployed on the virtual server.

Alternatively, a virtual server may designate one of its deployed web modules as its default web module, by specifying a default-web-module attribute whose value refers to one of the deployed web modules by its name. In this case, any requests that cannot be mapped to any of the web modules deployed on the virtual server will be mapped to the virtual server's default web module.

By default, a virtual server's docroot points to the ${com.sun.aas.instanceRoot}/docroot directory, as can be seen from this domain.xml snippet:

  <virtual-server id="server" [...]>
    <property name="docroot" value="${com.sun.aas.instanceRoot}/docroot"/>
  </virtual-server>

This means that when you access this URL:

  http://<host>:<port>/index.html
the contents of the ${com.sun.aas.instanceRoot}/docroot/index.html resource will be served.

By default, all virtual servers share the same docroot directory, but since the docroot property is configurable, each virtual server may be configured with its own, individual docroot.

As of GlassFish v2-b20, it is possible to configure a virtual server's docroot with finer granularity, based on the URL pattern of the request.

For example, it is now possible to configure a virtual server so that all requests with a URI that starts with /images/\* will be served from one directory, whereas all requests whose URI ends in \*.jsp will be served from a different directory. Each mapping from URL pattern to directory path constitutes an alternate docroot.

In GlassFish v2, a virtual server's alternate docroots are configured using the <property> subelement of <virtual-server> (this is mainly for historical reasons), as in the following sample domain.xml snippet:

  <virtual-server id="server" [...]>
    <property name="alternatedocroot_1" value="from=/images/\* dir=/usr/gifs"/>
    <property name="alternatedocroot_2" value="from=\*.jpg dir=/usr/gifs"/>
    <property name="alternatedocroot_3" value="from=\*.jsp dir=/usr/jsps"/>
    <property name="docroot" value="${com.sun.aas.instanceRoot}/docroot"/>
  </virtual-server>

A future version of GlassFish will add proper configuration support for alternate docroots by defining a <virtual-directory-mapping> element under <virtual-server> in domain.xml, with <local-path> and <url-pattern> subelements. The above configuration, while still supported, could then be represented more cleanly, as follows:

  <virtual-server id="server" [...]>
    <virtual-directory-mapping>
      <local-path>/usr/gifs</local-path>
      <url-pattern>/images/\*</url-pattern>
      <url-pattern>\*.jpg</url-pattern>
    </virtual-directory-mapping>
    <virtual-directory-mapping>
      <local-path>/usr/jsps</local-path>
      <url-pattern>\*.jsp</url-pattern>
    </virtual-directory-mapping>
    <property name="docroot" value="${com.sun.aas.instanceRoot}/docroot"/>
  </virtual-server>

If a request matches multiple alternate docroot URL patterns, the following precedence order is used:

  1. Exact match
  2. Longest path match
  3. Extension match

Any request that cannot be mapped to any of the web modules deployed on the virtual server, and whose URI does not match any of the virtual server's alternate docroot URL patterns, will continue to be served from the directory indicated by the virtual server's docroot property.

You may use the GlassFish admingui or command-line interface (asadmin) to add alternatedocroot_ properties to a virtual server. Please note that GlassFish does not support multi-valued properties in domain.xml. Therefore, if you want to specify multiple alternate docroots for a given virtual server, you need to make sure that each alternate docroot has a distinct property name that starts with alternatedocroot_.

A future enhancement will be to support alternate docroots for web modules. This will, amongst other things, allow web modules to share certain kinds of resources available on the server, instead of requiring every web module to bundle such resources. For example, by each defining alternate docroots with URI patterns of the form /images/\* and \*.jpg and a target directory of /usr/gifs, web modules would be able to share any \*.jpg resources available under /usr/gifs (provided they have read access to this directory).

Monday Aug 14, 2006

Jetty has integrated the JSP compiler from GlassFish

Jetty has integrated the JSP compiler from GlassFish

Jetty has integrated the JSP compiler from GlassFish

The folks at Jetty report that they have switched to leveraging the JSP compiler from GlassFish and are about to release with it in the next couple of days.

They mention the quality and stability of the GlassFish code, the support they've received from the GlassFish community during their transition, as well as the receptiveness of the GlassFish community to new ideas and contributions, as the main reasons for switching. See Jan Bartel's blog for details.

Congratulations to the Jetty folks, and welcome on board!

Friday Aug 11, 2006

Greater flexibility in configuring your web application's class path

Greater flexibility in configuring your web application's class path

Greater flexibility in configuring your web application's class path

If you've ever had to augment your web application's classpath in the past, you're probably familiar with the extra-class-path attribute of the class-loader element in sun-web.xml.

For those who aren't: This attribute takes a colon or semi-colon separated list of paths that are added to the list of repositories that your web application's classloader will consider when asked to load a particular resource (by default, a web application's classloader is required to consider only resources located in the WEB-INF/lib and WEB-INF/classes directories of a web application).

The documentation of the extra-class-path attribute has failed to specify how relative paths listed in this attribute's value are to be resolved. Up until recently, GlassFish has interpreted relative paths as relative to the application server's current directory, which is set to your domain's $INSTANCE_ROOT/config during startup. For example, a path of the form WEB-INF/lib/extra/extra.jar used to be resolved to $INSTANCE_ROOT/config/WEB-INF/lib/extra/extra.jar. Not very useful!

As of GlassFish Promoted Build v2 12, we've changed the interpretation of any relative paths listed in the value of the extra-class-path attribute so they are resolved relative to a web application's context root, which will serve developers' needs much better.

For example, if you want your web application's classloader to also consider resources in WEB-INF/lib/extra/extra.jar and WEB-INF/extra-classes bundled with your web application, you specify the extra-class-path attribute in your web application's sun-web.xml, as follows:


  <sun-web-app>
    <class-loader extra-class-path="WEB-INF/lib/extra/extra.jar:WEB-INF/extra-classes"/>
  </sun-web-app>

Tuesday Jul 11, 2006

How to enable Eclipse's JDT Compiler for JSP compilations in GlassFish

How to enable Eclipse's JDT Compiler for JSP compilations in GlassFish

How to enable Eclipse's JDT Compiler for JSP compilations in GlassFish

A repeated request heard on the GlassFish developer forums has been the ability to use the Eclipse Java Development Tools (JDT) Compiler (instead of the javac from Sun's SDK) for JSP compilations.

The Eclipse JDT Compiler is used as the default compiler in Tomcat 5.5, and included with Tomcat's binary distribution.

This blog lists the steps required to use the JDT Compiler for JSP compilataions in GlassFish. Starting with the upcoming GlassFish Promoted Build v2 10 (which will be available from the GlassFish download page), it will be possible to enable the JDT compiler from Eclipse for JSP compilations in GlassFish, by adding the following two JAR files to your ${GF_HOME}/lib directory:

  1. jasper-compiler-jdt.jar: This JAR file has been taken unmodified from a Tomcat 5.5 binary distribution.

  2. jasper-compiler-jdt-ext.jar: This JAR file contains a version of Tomcat's org.apache.jasper.compiler.JDTCompiler which has been recompiled against the com-sun-commons-logging.jar from GlassFish.

    This recompilation step has been necessary because Tomcat's org.apache.jasper.compiler.JDTCompiler extends org.apache.jasper.compiler.Compiler and accesses the log instance variable of its superclass. Notice that while the type of the log instance variable in Tomcat is org.apache.commons.logging.Log, it was changed to com.sun.org.apache.commons.logging.Log in GlassFish, for the reasons explained here.

Notice that when using the default ant/javac based compiler in GlassFish, the fork initialization parameter of the org.apache.jasper.servlet.JspServlet defined in your domain's default-web.xml is used to specify whether javac compilations are to be performed in process or forked to a separate process. By default, fork is set to TRUE, to avoid memory leak and file locking problems that have been observed with javac. The fork init parameter is ignored by the JDTCompiler, which always runs in process.

Friday May 12, 2006

More Efficient Request Mapping with the Ad-Hoc Mechanism in GlassFish

More Efficient Request Mapping with the Ad-Hoc Mechanism in GlassFish

More Efficient Request Mapping with the Ad-Hoc Mechanism in GlassFish

Ever wondered how a request for an EJB webservice endpoint is routed to its target EJB endpoint in GlassFish?

Join me for a look behind the covers ...

Let's start by taking a look at how requests for servlet webservice endpoints are routed to their target in GlassFish. As you may already have figured out, requests for JAXWS endpoints are mapped to the com.sun.enterprise.webservice.JAXWSServlet, and requests for JAXRPC endpoints are mapped to the com.sun.enterprise.webservice.JAXRPCServlet. These two servlets are responsible for forwarding the mapped requests to their intended targets.

For this approach to work, the web.xml deployment descriptor of a WAR file containing servlet endpoints is augmented with servlet mappings of each endpoint address to the com.sun.enterprise.webservice.JAXWSServlet or com.sun.enterprise.webservice.JAXRPCServlet, respectively, depending on the endpoint type. The generated mappings can be seen by deploying a WAR file containing servlet endpoints and checking the contents of the rewritten web.xml in install-dir/domains/domain1/generated/xml/j2ee-modules/<module-name>/WEB-INF/web.xml.

For EJB webservice endpoints, no such transformation of the web.xml needs to take place! Instead, the web container's ad-hoc mechanism is used to map and route requests for EJB webservice endpoints to their intended targets. What is this ad-hoc mechanism, and how does it work?

The web container's ad-hoc mechanism allows any interested GlassFish component to have a URI, or an entire URI subtree, serviced by an ad-hoc servlet that is registered programmatically via the ad-hoc registration API, instead of declaratively in the web.xml. The ad-hoc mechanism is convenient when it is impossible to declare all of a web application's servlet mappings at the time the web application is assembled or deployed, because the exact form of these mappings may not be known in advance.

A URI that is mapped to an ad-hoc servlet is referred to as an ad-hoc path. Likewise, a URI subtree mapped to an ad-hoc servlet is referred to as an ad-hoc subtree.

com.sun.enterprise.web.WebContainer provides the following ad-hoc registration API for turning a URI into an ad-hoc path, by mapping it to an ad-hoc servlet:


  public void registerAdHocPath(String path,
                                String ctxtRoot,
                                String appName,
                                AdHocServletInfo servletInfo)

and this API for turning a URI and an entire subtree beneath it into an ad-hoc path and subtree:


  public void registerAdHocPathAndSubtree(String path,
                                          String subtree,
                                          String ctxtRoot,
                                          String appName,
                                          AdHocServletInfo servletInfo)

The corresponding unregistration APIs are defined as follows:


  public void unregisterAdHocPath(String path, String ctxtRoot)

  public void unregisterAdHocPathAndSubtree(String path,
                                            String subtree,
                                            String ctxtRoot)

The com.sun.enterprise.web.AdHocServletInfo parameter contains information about the ad-hoc servlet that is to receive any requests on its associated ad-hoc path or subtree. More specifically, it contains the fully-qualified servlet class name, the servlet name, and the servlet's init parameters.

The ctxtRoot parameter specifies the context root component of the ad-hoc path being registered. When an ad-hoc path is registered, the web container will first check if a web context at the given context root already exists. If so, it will add the ad-hoc servlet built and initialized from the com.sun.enterprise.web.AdHocServletInfo parameter to it. Otherwise, the web container creates a new web context, registers it at the specified context root, and adds the ad-hoc servlet as its child.

A web context all of whose children are ad-hoc servlets is referred to as an ad-hoc context. If an ad-hoc context has been created and registered, and a user webapp is deployed to the same context root later on, the ad-hoc context will be unregistered in order to make room for the user web context, and all of the children of the ad-hoc context will be transferred over to the user web context. When the user webapp is unregistered, and some of its ad-hoc servlets are still active, the ad-hoc context is restored, and the ad-hoc servlets transferred back to it.

Currently, an ad-hoc path takes precedence over any user-defined servlet mappings declared in a user webapp. Based on feedback from the GlassFish community, we may want to consider aborting deployment of a user webapp if its intended context root has already been occupied by an ad-hoc context, and reject the registration of an ad-hoc path if its context root conflicts with that of an already deployed user webapp.

The web container's ad-hoc mechanism provides its own request processing pipeline, which means that even if an ad-hoc servlet has been added to a user context, any request mapped to the ad-hoc servlet will not be processed by the user context's regular request processing pipeline. This means that an ad-hoc servlet will never inherit any of the security settings of the user context it may have been added to.

In the case of EJB webservice endpoints, we've implemented an com.sun.enterprise.web.EjbWebServiceRegistryListener for EJB webservice registration and unregistration events emitted by the webservice engine. Upon receiving an EJB webservice registration event, this listener parses the endpoint's address into its context root and endpoint path components, which are then registered as an ad-hoc path, along with information describing the ad-hoc servlet that is to receive the requests. In this case, the ad-hoc servlet is an instance of com.sun.enterprise.webservice.EjbWebServiceServlet, which dispatches an incoming request to the target EJB webservice endpoint.

The big advantage of the ad-hoc mechanism is that it enables the web container to determine, by examining the request URL, which requests are targeted for EJB webservice endpoints, and which ones aren't. In previous implementations, the web container had to delegate this decision to the EJB webservice registry, making any and all HTTP requests suffer from the extra lookup. The extra lookup used to be necessary because EJB webservice endpoints are declared in EJB-specific deployment descriptors and are not reflected in the deployment descriptors of regular web applications. With the ad-hoc mechanism, the extra lookup is no longer needed.

In addition to supporting EJB webservice endpoints, the web container's ad-hoc mechanism is currently also being leveraged by the Java Web Start support for app clients in GlassFish. See Tim Quinn's blog for details.

Wednesday May 10, 2006

JSTL 1.2 Artifacts Available from Maven Repository at java.net

JSTL 1.2 Artifacts Available from Maven Repository at java.net

JSTL 1.2 Artifacts Available from Maven Repository at java.net

The JavaServer Pages(TM) Standard Tag Library (JSTL) 1.2 API and reference implementation from GlassFish, licensed under CDDL, are now available from the java.net Maven repository.

The JSTL 1.2 artifacts are available from this repository URL, and include both binary and source versions of the API and implementation classes.

Thursday Apr 06, 2006

Validate your Tag Library Descriptor files!

Validate your Tag Library Descriptor files!

Validate your Tag Library Descriptor files!

Prior to JSP 2.0, Tag Library Descriptor (TLD) files had to conform to a DTD file (e.g., web-jsptaglibrary_1_2.dtd in JSP 1.2). According to the DTD, a TLD was required to specify the version of the JSP specification it relied upon, by using the <jsp-version> subelement of the <taglib> root element.

For example, the TLD of the JSTL 1.0 Core Library component declares the JSP version as follows:


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>c</short-name>
  <uri>http://java.sun.com/jstl/core</uri>
  <display-name>JSTL core</display-name>
  <description>JSTL 1.0 core library</description>
  ....
</taglib>

As of JSP 2.0, TLDs must conform to a schema (web-jsptaglibrary_2_0.xsd in JSP 2.0, and web-jsptaglibrary_2_1.xsd in JSP 2.1). One of the subtle changes between the transition from a DTD to a schema has affected the way the JSP specification version must be declared: The TLD schemas no longer define any <jsp-version> element. Instead, they require the JSP version to be declared as an attribute of the <taglib> root element!

For example, the TLD of the JSTL 1.1 Core Library component, which leverages JSP 2.1 features, declares the JSP version as follows:


<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">

  <description>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>c</short-name>
  <uri>http://java.sun.com/jsp/jstl/core</uri>
  ....
</taglib>

As some tag library developers have upgraded their JSP 1.2 based tag libraries to take advantage of JSP 2.0 or JSP 2.1 features, they forget to remove the <jsp-version> element from their TLDs. This error has gone unnoticed when deploying those tag libraries onto GlassFish, because by default, schema validation of tag libraries has been disabled in GlassFish.

Starting with GlassFish b42, you can enable schema validation of TLDs in several ways:

  • By using the ${glassfish.home}/bin/jspc precompilation tool and specifying its new -validate option.

  • By specifying the enableTldValidation property in your sun-web.xml, as follows:
    
    <?xml version="1.0" encoding="UTF-8"?>
    <sun-web-app>
        <property name="enableTldValidation" value="true" />
    </sun-web-app>
    

I recommend you validate your TLDs as a sanity check. We've found that some of the TLDs we've been using for testing were not schema compliant!

TLD schema validation in GlassFish leverages the schema validation framework provided by JAXP 1.3.

Notice that with GlassFish b42, only TLDs that reference a schema will be validated: If your TLD references a DTD, it will not be validated. This is because JAXP's javax.xml.parsers.DocumentBuilderFactory does not support the http://apache.org/xml/features/validation/dynamic feature. In any environment (such as JSP compilation) where an XML document (in this case: a TLD) may be DTD or schema based, and the parser does not have any advance knowledge of the type of document definition used, the lack of support for the http://apache.org/xml/features/validation/dynamic feature would require any document that needs to be validated against a DTD to be parsed twice: The first time in order to determine whether the XML document references a DTD or schema, and the second time to parse it with DTD validation enabled, by calling setValidating(true) on the javax.xml.parsers.DocumentBuilderFactory.

I've submitted a bug against JAXP to add support for the http://apache.org/xml/features/validation/dynamic feature to javax.xml.parsers.DocumentBuilderFactory. Once this feature is supported, enabling DTD validation of TLDs will be as simple as adding a single line to the TLD validation logic of the JSP compiler.

Friday Feb 17, 2006

Why is org.apache.commons.digester.Digester not finding my classes?!

Why is <code>org.apache.commons.digester.Digester</code> not finding my classes?!

Why is org.apache.commons.digester.Digester not finding my classes?!

As people have tried to deploy the Roller Blog web application to Glassfish, they have run into a mystifying ClassNotFoundException, where the class that was not being found (in this case: org.roller.presentation.tags.menu.MenuImpl) was bundled with the Roller Blog web application itself.

The ClassNotFoundException has come with this stack trace:


java.lang.ClassNotFoundException: org.roller.presentation.tags.menu.MenuImpl
        at org.apache.commons.digester.Digester.createSAXException(Digester.java:2540)
        at org.apache.commons.digester.Digester.createSAXException(Digester.java:2566)
        at org.apache.commons.digester.Digester.startElement(Digester.java:1276)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:533)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:878)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1693)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:368)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:834)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1242)
        at org.apache.commons.digester.Digester.parse(Digester.java:1567)

Looks as if org.apache.commons.digester.Digester is having problems with processing rules that reference locally bundled classes (i.e., classes located in WEB-INF/classes or WEB-INF/lib/[\*.jar|\*.zip]).

This problem is not specific to the Roller Blog web application: All web applications that are using the commons-digester package from Apache with a version equal to or greater than 1.1 are suffering from it. So what is going on?!

The ClassNotFoundException is caused by a regression in commons-digester, which was introduced between versions 1.0 and 1.1 of this package.

As of commons-digester version 1.1, org.apache.commons.digester.Digester no longer uses the context classloader (obtained via a call to Thread.currentThread().getContextClassLoader()) by default to resolve or load any classes referenced by any rules it processes. Remember that in a Java EE environment, the web container sets a web application's classloader as the context classloader before invoking any of the web application's components, which means that when any code in your web application calls Thread.currentThread().getContextClassLoader(), it will receive a reference to its own classloader.

Instead, as of commons-digester version 1.1, org.apache.commons.digester.Digester uses the classloader by which it was loaded (i.e., the classloader returned by digester_instance.getClass().getClassLoader()) by default. In order to restore the 1.0 behaviour of using the context classloader, you must set the useContextClassLoader property of your org.apache.commons.digester.Digester instance to TRUE, as follows:


  digester.setUseContextClassLoader(true);

This regression does not cause any problems if a web application bundles its own commons-digester (as has been the case with the Roller Blog web application), as long as there is no commons-digester further up in the classloader delegation chain: In this case, digester_instance.getClass().getClassLoader() will return your web application's classloader, giving digester_instance access to all of its classes.

However, if there is a commons-digester higher up in the classloader delegation chain (as is the case with Glassfish!), the web application classloader will delegate to it by default, giving the commons-digester package higher up in the chain preference over the locally bundled version, resulting in the ClassNotFoundException seen above.

We are going to address this package conflict by renaming all commons packages bundled with Glassfish from org.apache to com.sun.org.apache.

In the meantime, you can work around this problem by instructing your web application's classloader to resolve and load classes locally before delegating to its parent. You do this by adding the following element to your web application's WEB-INF/sun-web.xml resource (if your web application does not already contain this resource, you need to create one):


  <sun-web-app>
    <class-loader delegate="false"/>
  </sun-web-app>

Alternatively, if your code has access to the org.apache.commons.digester.Digester instance that is processing your rules, you can try setting its useContextClassLoader property to TRUE, as described above.

I am going to update you as soon as the package renaming effort has been completed, which will eliminate the need for any of these workarounds.

Thursday Feb 16, 2006

Implicit Tag Libraries require (and finally have!) a JSP Version Number

Implicit Tag Libraries require (and finally have!) a JSP Version Number

Implicit Tag Libraries require (and finally have!) a JSP Version Number

This blog describes a deficiency related to the JSP versioning of Implicit Tag Library Descriptor (TLD) files introduced in JSP 2.0, and how JSP 2.1, now in Proposed Final Draft 2 and implemented in Glassfish build 37, has decided to address it.

Background

One of the goals of JSP 2.0 has been to simplify JSP development. To address this goal, JSP 2.0 introduced the tag file facility, which allows page authors to create tag libraries using JSP syntax. This means that page authors no longer need to know Java to write a tag extension.

Tag files may be referenced from a TLD just as any tag handler implemented in Java, by using the <tag-file> element.

JSP 2.0 went one step further and also eliminated the need for creating TLD files for tag libraries that consisted exclusively of tag files. In order to take advantage of this feature, tag files must be placed in a web application's /WEB-INF/tags directory, or a subdirectory of it. The JSP container interprets the /WEB-INF/tags directory, and each subdirectory under it, as another implicitly defined tag library containing tag handlers defined by the tag files that appear in that directory. For example, the following web application contains 3 implicit tag libraries:

  /WEB-INF/tags/
  /WEB-INF/tags/a.tag
  /WEB-INF/tags/b.tag
  /WEB-INF/tags/foo/
  /WEB-INF/tags/foo/c.tagx
  /WEB-INF/tags/bar/barr/
  /WEB-INF/tags/bar/barr/d.tag

Problem

Tag libraries must specify the version of the JSP specification that they depends on. TLDs that depend on JSP 1.2 or earlier specification versions must specifiy the JSP version in their <jsp-version> element. Starting from JSP 2.0, the JSP version must be specified as the value of the mandatory "version" attribute of the <taglib> root element.

The JSP 2.0 specification did not specify how the JSP version of an implicit TLD was derived, and most containers (including Glassfish) have hard-coded the JSP version of an implicit TLD at "2.0".

The Unified Expression Language (EL), which has been one of the most important feature additions to JSP 2.1, introduces the concept of deferred expressions, which are indicated by the #{expr} syntax. In order to remain backwards compatible with JSP 2.0, which has no notion of deferred expressions, the JSP 2.1 specification requires that when used as a tag attribute value inside a tag invocation, the #{expr} syntax must be evaluated by the container only if the JSP version of the tag handler's underlying TLD has a value of "2.1" or higher. See Kin-Man's blog for more information about the Unified EL, and how backwards compatibility was temporarily broken in one of the earlier Glassfish builds.

Since it is impossible to configure the JSP version of an implicit TLD, and since most containers have hard-coded the JSP version of an implicit TLD to be "2.0", the concept of deferred expressions introduced in JSP 2.1 cannot be applied to invocations of tag handlers supported by tag files referenced by an implicit TLD: a very severe limitation, especially in light of all the attention that tag files have attracted since JSP 2.0!

Solution

In order to address the above shortcoming, JSP 2.1 PFD2 allows certain aspects of an implicit TLD, such as its JSP version number, to be configured by placing a TLD file with the reserved name implicit.tld into the same directory as the implicit tag library's constituent tag files:
  /WEB-INF/tags/
  /WEB-INF/tags/a.tag
  /WEB-INF/tags/b.tag
  /WEB-INF/tags/foo/
  /WEB-INF/tags/foo/c.tagx
  /WEB-INF/tags/bar/barr/
  /WEB-INF/tags/bar/barr/d.tag
  /WEB-INF/tags/bar/barr/implicit.tld

The JSP version specified in an implicit.tld file is used to set the JSP version of an implicit TLD. JSP 2.1 PFD2 has also clarified that the JSP version of an implicit TLD defaults to "2.0".

Example: In order to set the JSP version of an implicit TLD to "2.1", the following implicit.tld could be used:


  <taglib
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    version="2.1">
      <tlib-version>1.0</tlib-version>
  </taglib>

Support for the implicit.tld feature is available in the latest Glassfish build 37 build. Go try it out and let me know if you have any questions!

How to Disable Persisting of Memory-based HTTP Sessions during a Server Restart

How to Disable Persisting of Memory-based HTTP Sessions during a Server Restart

How to Disable Persisting of Memory-based HTTP Sessions during a Server Restart

When stopping your Glassfish server, all memory-based HTTP sessions created by web applications deployed on your server are persisted into files using serialization, and restored from their serialized format during a subsequent restart of the server, after which the files containing the serialized sessions are deleted.

Only those sessions that are still valid (i.e., have not yet expired) at the time the server is stopped are subject to being persisted.

The HTTP sessions are persisted for each web application individually, in this file:

  ${GF_HOME}/domains/domain1/generated/jsp/j2ee-modules/<module_name>/<context_path>_SESSIONS.ser

where ${GF_HOME} points to your Glassfish installation directory, <module_name> is the name of your web application, and <context_path> is the context path at which your web application has been deployed.

If your web application is bundled inside an EAR file, its sessions will be persisted in this file:

  ${GF_HOME}/domains/domain1/generated/jsp/j2ee-apps/<app_name>/<module_name>/<context_path>_SESSIONS.ser

where <app_name> is the name of your EAR-packaged application.

Many folks have wondered if it was possible to disable session persistence for their webapps, and the good news is: Yes, Glassfish makes this possible! All you need to do is specify a sessionFilename property with an empty value in your web application's sun-web.xml resource (located inside your web application's /WEB-INF directory), like this:


  <sun-web-app>
    <session-config>
      <session-manager>
        <manager-properties>
          <property name="sessionFilename" value="" />
        </manager-properties>
      </session-manager>
    </session-config>
  </sun-web-app>

The sessionFilename property may be used to customize the name of the file where persisted sessions are stored for your web application, and an empty value has the special semantics of disabling the persisting of memory-based sessions for your web application during a server restart.

About

jluehe

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today