Web Contexts

This chapter describes how to package, deploy, and monitor JEUS web applications.

1. Overview

Web contexts are created when web applications are deployed to web engines. Since web applications and web contexts are practically synonymous, the terms 'web context' will be mainly used to signify 'web application'.

2. Basic Structure

This section describes the content and structure of web contexts.

2.1. Web Context Contents

Web applications consist of static and dynamic contents that are required to run web-based services requested by clients.

  • Static content

    Static content is any kind of data that will be returned without being processed by the web engine. The following are the available static content types.

    • HTML pages

    • Text files

    • Image files

    • Videos

    • Others

  • Dynamic content

    Contents that are created as responses to user requests such as servlets and JSPs.

2.2. Web Context Structure (WAR File Structure)

Before being deployed to web engines, a web context must be packaged into a JAR file, a compressed file with the extension '.war'. The packaged file is called a WAR (Web ARchive) file.

The following is the structure of a WAR file.

WEB WAR
   |--[T]index.html
   |--static
   |    |--[T].html
   |--jsp
   |    |--.jsp
   |--images
   |    |--[T].jpg, .gif
   |--META-IMF
   |    |--[T]MAINFEST.MF
   |--WEB-IMF
        |--[X]web.xml
        |--[X]jeus-web-dd.xml
        |--[X]ebj-jar.xml
        |--[X]jeus-ejb-dd.xml
        |--classes
        |    |--[C]Servlet.class
        |    |--[C]EJB.class
        |--lib
        |    |--[J]Library JAR
        |--tlds
             |--[T].tld

* Legend
- [01]: binary or executable file
- [X] : XML document
- [J] : JAR file
- [T] : Text file
- [C] : Class file
- [V] : java source file
- [DD] : deployment descriptor
META-INF/

This directory is optional. If this directory is used, it contains the "MANIFEST.MF" file, a descriptor file defined in the JAR format.

WEB-INF/

This directory is required. It contains servlets, filters, listener classes, and libraries. The following components are in this directory.

Component Description

web.xml

Jakarta EE web application deployment descriptor file. It contains meta-information about the web application.

Starting from Servlet 3.0, web.xml is not necessarily required. Instead, servlets, filters, and listeners can be added using annotations and the registration API.

jeus-web-dd.xml

JEUS web application deployment descriptor. For more information, refer to jeus-web-dd.xml Configuration.

ejb-jar.xml

jeus-ejb-dd.xml

From Java EE 6 onwards, EJBs can be included in a WAR file. EJBs can also be defined as an annotation like servlets. For more information, refer to the EJB standards or JEUS EJB Guide.

classes/

Contains servlet classes and utility classes in its subdirectories.

It is organized into a standard Java package structure.

lib/

Contains the Java libraries that are required for web applications.

The libraries are packaged into JAR files and stored in this path. The files are automatically added to the classpaths of all servlets.

tlds/

Contains custom tag library descriptors for JSP pages.

Others

Directories that contain contents such as JSP, HTML, and image files.

3. Deploying Web Contexts

This section describes how to deploy web contexts. Deployment is the process that creates web contexts and prepares them to run on JEUS web engines.

Logically, web contexts exist on a virtual host. For more information about virtual hosts, refer to Virtual Hosts.

3.1. jeus-web-dd.xml Configuration

The web.xml and jeus-web-dd.xml files should be created under the 'WEB-INF/' directory only when necessary.

The following is a sample jeus-web-dd.xml file. It shows only a specific part of the file. To see the full file with all configuration items, refer to "13. Configuration of jeus-web-dd.xml" in "JEUS XML Reference".

Web Context Configuration File: <jeus-web-dd.xml>
<jeus-web-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9">
    <context-path>/examples</context-path>
    <enable-jsp>true</enable-jsp>
    <auto-reload>
        <enable-reload>true</enable-reload>
        <check-on-demand>true</check-on-demand>
    </auto-reload>
    <added-classpath>
        <class-path>/home/user1/libs/lib.jar</class-path>
    </added-classpath>
    <session-config>
        . . .
    </session-config>
    <thread-pool>
        <base>
            <name>base</name>
            <min>1</min>
            <max>5</max>
        </base>
        <service-group>
            <name>svcg1</name>
            <uri>/service1,/service2</uri>
            <min>10</min>
            <max>20</max>
        </service-group>
        <service-group>
            <name>longJsp</name>
            <uri>/jsp/servlet/asyncContext.jsp</uri>
            <min>5</min>
            <max>10</max>
        </service-group>
        <service-group>
            <name>Jsp</name>
            <uri>/jsp/servlet</uri>
            <min>1</min>
            <max>5</max>
        </service-group>
    </thread-pool>
    <upgrade>
        <upgrade-executor>
            <min>0</min>
            <max>30</max>
            <keep-alive-time>60000</keep-alive-time>
            <queue-size>4096</queue-size>
        </upgrade-executor>
    </upgrade>
    <async-config>
        <async-timeout-millis>600000</async-timeout-millis>
        <background-thread-pool>
            <min>0</min>
            <max>10</max>
        </background-thread-pool>
        <dispatch-thread-pool>
            <min>0</min>
            <max>10</max>
        </dispatch-thread-pool>
    </async-config>
    <properties>
        <property>
            <key>jeus.servlet.jsp.modern</key>
            <value>true</value>
        </property>
    </properties>
</jeus-web-dd>

The following describes each configuration tag.

Tag Description

<context-path>

Context root path. Must begin with a "/" and be unique in the virtual host.

In the URL "http://www.foo.com/examples/index.html", the context path is "/examples".

<enable-jsp>

If set to false, JSP will not be used. By default, JSP is supported.

<user-log>

User logs that are created by web applications through the servlet context’s log method. For more information, refer to Configuring User Logs.

<auto-reload>

Option to automatically reload servlet classes and custom tag classes when they are modified. For more information, refer to Reloading Classes at Runtime.

<added-classpath>

List of libraries that are referenced when a servlet program is compiled or executed.

Can use directories.

<allow-indexing>

Displays the list of URLs where the directory list is displayed upon client request. The directory list is displayed when the file requested by a client does not exist.

Clicking on a file in the directory list will show the file contents.

<deny-download>

Filter that defines resources that cannot be accessed or downloaded directly. These filters are file name extensions. You can use paths that include file names.

File names and directories are specified as relative paths to the directory context document base.

<aliasing>

Directory mapping for custom URL paths.

This can be used to map a directory that is in a different location from the URL request path.

<file-caching>

Determines the static contents that will be cached in the runtime memory to improve response times.

Child configurations include the maximum size of cache memory in megabytes, the maximum size of static content in cache, and the path to the contents that will be cached.

<jsp-engine>

Setting for JSP pages that are included in the web contexts. For more information about <jsp-engine>, refer to Configuring jeus-web-dd.xml.

<session-config>

Sessions that are used in the context.

This has a higher priority than the web engine configurations. For more information about configuring sessions, refer to Sessions.

<webinf-first>

Option for class loading priority. If this is set to 'true', classes in WEB-INF will be loaded first for this application.

If this is set to 'true', a specific package or class can be excluded when class loading related collision occurs as follows from JEUS 7 Fix#4 onwards.

<webinf-first>
    <enabled>true</enabled>
    <excluded-package>package.name.</excluded-package>
    ...
</webinf-first>

<attach-stacktrace-on-error>

Option to display the error details in the browser if an error occurs on the server. The message can be helpful in a development environment, but it is not recommend for use in a production environment.

<keep-alive-error-response-codes>

Error code that will send a Keep-Alive response instead of a Connection: Close. It is applied when the error is sent by the web application itself, but not when the engine decides that the connection needs to be terminated internally.

For example, it is applied when a servlet implements a response.sendError(500) but not applied when the engine sends the 500 error because an exception occurred in the servlet. If multiple response codes need to be configured, separate them with a "," like "404, 503".

<encoding>

Encoding configuration for requests and responses. This is the same as <encoding> in domain.xml. If encoding configuration is set in both jeus-web-dd.xml and domain.xml, <request-encoding> and <response-encoding> in jeus-web-dd.xml has priority. For more information, refer to Encoding.

  • Request Encoding: URL Query String, application/x-www-form-urlencoded Body, getReader(). From JEUS 7 Fix #4, <request-encoding><url-mapping> is added to use encoding mapped to a specific Servlet path. However, it will be ignored if <forced> or <client-override> is set.

  • Response Encoding: Encoding for response HTTP bodies.

<cookie-policy>

Policy that is applied when reading cookies from an HTTP request header or adding new cookies to an HTTP response header according to the application request. For more information, refer to Cookie Policy.

<async-config>

Async processing that was added in Servlet 3.0. Child configurations such as async timeout, background thread pool, and dispatch thread pool can be configured. For more information, refer to the servlet standards.

<upgrade>

Tread pool configuration internally used by the container to process Upgrade inbound messages.

<web-security>

Configuration group of security policies that are limited to web applications including the policy configuration of address validation when using sendRedirect.

<websocket>

Configuration about the web application’s WebSocket Container. For more information, refer to Configuring WebSocket Container.

<properties>

Properties that apply to the web application. These properties only apply to the application that they are configured for.

The default value of <async-config><async-timeout-millis> is 30 seconds. If an error occurs because an operation performed by a background thread is taking too long, set this value in the jeus-web-dd.xml or adjust the timeout in the program code by using the jakarta.servlet.AsyncContext#setTimeout() method.

The following describes each tag for the thread pool configuration.

Tag Description

<base>

Default thread pool to handle requests without matching URIs within the service group. Do not set this tag if requests are to be processed by higher-level thread pools, such as the Virtual Host or Web-Connection thread pool.

<service-group>

Thread pool used to handle requests for services with matching URIs.

<name>

Name to identify the base and service-groups.

<uri>

URIs to match requests that will be processed in the specified service-group thread pool. Multiple resources can be provided with comma separators, and each URI must start with '/'.

3.2. Web Context Redeployment (Graceful Redeployment)

Redeployment of web context is omitted in this guide. For more information, refer to Graceful Redeployment in JEUS Applications & Deployment Guide.

3.3. Adding Shared Library References

Shared libraries can be added to the 'JEUS_HOME/lib/shared' directory instead of the 'WEB-INF/lib' directory so that they can be shared by multiple applications. When modifying the libraries.xml file and redeploying the module, the updated libraries will be applied without restarting JEUS.

To add a shared library, add the <library> tag and configure the JAR files to share in the 'JEUS_HOME\lib\shared\libraries.xml' file as in the following example. The specification version and the implementation class version can each be configured.

Adding Shared Library References: <libraries.xml>
<libraries xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <!-- DO NOT MODIFY OUR SYSTEM libraries!!! -->
    <library>
        <library-name>jsf</library-name>
        <specification-version>1.2</specification-version>
        <implementation-version>1.2.15</implementation-version>
        <files dir="jsf_ri_1.2"/>
    </library>
    <library>
        <library-name>jsf</library-name>
        <specification-version>2.2</specification-version>
        <implementation-version>2.2.13</implementation-version>
        <files dir="jsf_ri_2.2"/>
    </library>
    <library>
        <library-name>jsf-jeusport</library-name>
        <files dir=".">
            <include name="jsf-injection-provider.jar"/>
    </library>
    <library>
        <library-name>jsf-weld-integration</library-name>
        <files dir=".">
            <include name="jsf-weld-integration.jar"/>
    </library>
    <library>
        <library-name>jstl</library-name>
        <specification-version>1.2</specification-version>
        <implementation-version>1.2</implementation-version>
        <files dir="jstl_1.2"/>
    </library>
    <library>
        <library-name>jstl</library-name>
        <specification-version>1.2</specification-version>
        <implementation-version>1.2</implementation-version>
        <files dir="jstl_1.2"/>
    </library>
    <library>
        <library-name>spring-support</library-name>
        <specification-version>4.2.0.RELEASE</specification-version>
        <implementation-version>4.2.0.RELEASE</implementation-version>
        <files dir="spring-support/4.2.0.RELEASE"/>
    </library>
    <library>
        <library-name>spring-support</library-name>
        <specification-version>4.0.0.RELEASE</specification-version>
        <implementation-version>4.0.0.RELEASE</implementation-version>
        <files dir="spring-support/4.0.0.RELEASE"/>
    </library>

    <!-- Add user libraries from here -->
    <library>
        <library-name>myLibrary</library-name>
        <specification-version>2.0</specification-version>
        <implementation-version>2.1</implementation-version>
        <files dir=".">
            <include name="commons-logging.jar"/>
            <include name="commons-util.jar"/>
        </files>
        <files dir="myLib-2.1"/>
    </library>
</libraries>

To reference the configured shared libraries, set <library-ref> in jeus-web-dd.xml as in the following. If the version is not specified, the highest version of the library that is registered in libraries.xml will be referenced.

   <library-ref>
       <library-name>myLibrary</library-name>
       <specification-version>
          <value>2.0</value>
       </specification-version>
   </library-ref>

Configuring JSF and JSTL Libraries

In the libraries.xml file described in Adding Shared Library References: <libraries.xml>, JSF and JSTL are added as shared libraries. Since the Jakarta EE standard includes JSF and JSTL, they are provided in JEUS by default.

The libraries can be provided by JEUS, but this will only allow one each of JSF and JSTL implementation class to be used. Since JSF implementation class has multiple versions besides 2.0, including 1.2, Apache myfaces, and SUN RI, JEUS provides the JSF and JSTL as shared libraries so that multiple implementations can be used.

The implementation classes are classified by their locations and types as in the following.

  • JSF or JSTL implementation class in WEB-INF/lib.

  • Implementation classes in shared library. (This has a lower priority)

Starting from JEUS 7 Fix#2, the Oracle JSF RI is not automatically added to the 'JEUS_HOME/lib/shared' directory. To use it, explicitly configure the <library-ref> setting in jeus-web-dd.xml.

Use the following declaration to use the libraries included in the 'JEUS_HOME/lib/shared' directory.

<library-ref>
    <library-name>jsf</library-name>
</library-ref>

Also, JEUS has been modified to not automatically add the web listener included in Oracle JSF RI 2.x. It must be configured in the <listener> setting of web.xml.

<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

To share the same JSF or JSTL libraries in multiple applications, manually configure the <library> setting in 'JEUS_HOME/lib/shared/libraries.xml' and that <library-ref> setting in jeus-web-dd.xml.

For JSF, the resources provided by WAS must be accessible from managed beans by using annotations such as @EJB and @Resource and WAS must be able to inject the resources that are specified by the annotations.

JEUS provides 'jsf-injection-provider.jar' as a shared library to support the injection of JEUS to JSF RI. The shared library exists in the following directory.

JEUS_HOME/lib/shared

The library is automatically included if web.xml contains the jakarta.faces.webapp.FacesServlet class.

Configuring Spring Support Library

The Spring support library is added in the libraries.xml file described in Adding Shared Library References: <libraries.xml>.

The Spring Support library is required for applications developed with the Spring framework to use JEUS functions. The following only describes WebSocket-related functions.

When implementing the WebSocket function by using the Spring framework, the spring-websocket module is used. Since this module does not support JEUS WebSocket Handshake, the function does not work normally. To use the function normally, use the Spring support library.

To use the WebSocket function in the Spring support library, set <library-ref> in jeus-web-dd.xml and add a related bean to Spring settings as follows:

<beans ...>
    <websocket:handlers>
        <websocket:mapping .../>
        <websocket:handshake-handler ref="handshakeHandler"/>
    </websocket:handlers>

    <bean id="handshakeHandler" class="org.springframework.web.socket.server.support.DefaultHandshakeHandler">
        <constructor-arg ref="upgradeStrategy"/>
    </bean>
    <bean id="upgradeStrategy" class="jeus.spring.websocket.JeusRequestUpgradeStrategy"/>
</beans>

Set as follows when using 4.2.0.RELEASE version library.

<beans ...>
    <websocket:handlers>
        <websocket:mapping .../>
        <websocket:handshake-handler ref="handshakeHandler"/>
    </websocket:handlers>

    <bean id="handshakeHandler" class="jeus.spring.websocket.JeusHandshakeHandler"/>
</beans>

3.4. Configuring Web Contexts for Compatibility

A web context can be configured to resolve compatibility issues with previous versions JEUS or another WAS.

Compatibility with Previous Versions of JEUS

Prior to Servlet 2.4, many standards were not described properly. They were supplemented over the course of servlet 2.4 and 2.5 releases and this naturally resulted in restrictions being created in JEUS. To resolve these issues, JEUS started supporting non-standard operations. Due to such reasons, JEUS 4 web applications may not be compatible with JEUS 6.

JEUS must comply with servlet and JSP standards, and also ensure compatibility with the existing applications, but these requirements can cause conflicts. Usually when the jakarta.servlet standard API or internal operation is modified to comply with the standard, problems may arise if there are applications that were created based on the previous faulty operation. In this situation, the applications must be modified since compliance requirements have a higher precedence. Otherwise, the applications cannot run in other containers, and they may conflict with frameworks that comply with the servlet standards when the applications are upgraded.

If such issues are not identified in advance until the official start of the services, this may require the modification of JEUS operations instead of user applications. To resolve this, JEUS provides properties that can be configured for compatibility with previous versions.

For more information about the compatibility of JSP engines and JEUS properties, refer to Web Context Options for JSP Backward Compatibility and Properties for Compatibility, respectively.

Compatibility with Other WASs

Before Servlet 2.4, web applications were developed using servlets and JSPs directly, but a web framework is now being used. Starting from Java EE 5, JSF and JSTL libraries have been added to the standard web frameworks. Most web frameworks use Tomcat, a reference implementation class for servlet and JSP specifications, for development and testing. This may cause compatibility issues if the web frameworks support non-standard functions.

Compatibility can be configured selectively in jeus-web-dd.xml when there is a compatibility problem. For more information about configuring jeus-web-dd.xml, refer to Web Engine Properties in JEUS Reference Guide.

3.5. Configuring Additional Features

Separate configurations are required to use the following additional functions provided by JEUS.

  • Servlet Mapping for Static Resources

    The servlet standard specifies that the default servlet, which is provided by WAS, is used for a request that is neither a servlet nor JSP. The default servlet is referred to as ResourceServlet.

    Map jeus.servlet.servlets.ResourceServlet to the <servlet-mapping> setting in web.xml as in the following.

    Servlet Mapping for Static Resources: <web.xml>
    <servlet-mapping>
        <servlet-name>jeus.servlet.servlets.ResourceServlet</servlet-name>
        <url-pattern>/static/*</url-pattern>
    </servlet-mapping>
  • Registering mvc:default-servlet-handler in Spring 3.0 or Later

    From JEUS 9 onwards, the mvc:default-servlet-handler does not need to be registered in Spring 3.0 or later. Like Tomcat, the JEUS default servlet is provided in the name of "default".

  • Registering ProgressListener when Servlet 3.0 Multipart Function is Used

    Starting from Servlet 3.0, the multipart-config can be configured per servlet to assign the web container to process multipart/form-data of the POST request. A progressListener must be registered to trigger an event about the processing progress.

    1. The jeus.servlet.engine.multipart.ProgressListener , which is included in the jeus-servlet.jar file, must be implemented. For information about the interface, refer to the Servlet API document.

    2. Add the instance of the previous interface implementation class to the HttpServletRequest attribute using the same name as the interface, jeus.servlet.engine.multipart.ProgressListener. Note that this must be done before getPart(), getParts(), or getParameter() is called.

3.6. Configuring Web Security

This section describes configuring web security for each application in jeus-web-dd.xml.

Redirect Location Security Configuration

Applications can send the 302 Found response message by using the standard API jakarta.servlet.http.HttpServletResponse.sendRedirect (String location). In this case, the location parameter value will be converted to URL and set to the location header without checking the value. This allows users with malicious intent to use attacks like CRLF injection. To prevent this, applications can implement the jeus.servlet.security.RedirectStrategy interface and configure it in jeus-web-dd.xml.

The following is an example of configuring the jeus.servlet.security.RedirectStrategy interface.

Redirect Location Security Configuration Interface
package jeus.servlet.security;

import jakarta.servlet.http.HttpServletRequest;

public interface RedirectStrategy {
    /**
     * Makes the redirect URL.
     *
     * @param location the target URL to redirect to, for example "/login"
     */
    String makeRedirectURL(HttpServletRequest request, String location)
        throws IllegalArgumentException;
}

This interface can be implemented as follows:

Redirect Location Security Configuration Implementation
package jeus.servlet.security;
import jakarta.servlet.http.HttpServletRequest;

public class RejectCrlfRedirectStrategy implements RedirectStrategy {
    private Pattern CR_OR_LF = Pattern.compile("\\r|\\n");

    @Override
    String String makeRedirectURL(HttpServletRequest request, String location)
       throws IllegalArgumentException {
        if (CR_OR_LF.matcher(location).find()) {
           throw new IllegalArgumentException("invalid characters (CR/LF) in redirect location");
        }
       return makeAbsolute(location);
    }

    private String makeAbsolute(String location) {
       // make code for make absolute path
    }
}

Jeus-web-dd.xml can be configured as follows:

Redirect Location Security Configuration: <jeus-web-dd.xml>
...
<web-security>
    <redirect-strategy-ref>
    jeus.servlet.security.RejectCrlfRedirectStrategy
    </redirect-strategy-ref>
</web-security>
..

The <redirect-strategy-ref> setting is set to an implementation class of the jeus.servlet.security.RedirectStrategy interface. This class must be included in the web application class path. The jeus.servlet.security.RejectCrlfRedirectStrategy class is a default RedirectStrategy provided. If a location that contains CR, LF, or CRLF character is sent to the sendRedirect API, an HTTP 500 error will occur.

In addition, the jeus.servlet.security.RemoveCrlfRedirectStrategy method that replaces CR, LF, or CRLF with an empty string is provided.

3.7. Mapping Security Roles

The security roles defined in web.xml must be mapped to system users and groups. This mapping is described in jeus-web-dd.xml.

The following is a sample web.xml file.

Mapping Security Roles: <web.xml>
<web-app>
    <security-role>
        <role-name>manager</role-name>
    </security-role>
    <security-role>
        <role-name>developer</role-name>
    </security-role>
    <servlet>
        . . .
    </servlet>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>
                MyResource
            </web-resource-name>
            <url-pattern>/jsp/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>
</web-app>

In the previous example, two security roles are declared in bold. The third bold element shows how the manager role is used in the <security-constraint> tag.

The previous mapping can be defined in jeus-web-dd.xml as follows:

Mapping Security Roles: <jeus-web-dd.xml>
<jeus-web-dd  xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9">
     . . .
     <role-mapping>
         <role-permission>
             <principal>Peter</principal>
             <role>manager</role>
         </role-permission>
         <role-permission>
             <principal>Linda</principal>
             <role>developer</role>
         </role-permission>
     </role-mapping>
     . . .
</jeus-web-dd>

When applications are deployed in a production environment, the manager and developer roles must be bound to a special user in the system. This mapping is defined in the <context><role-mapping> setting. The <role-mapping> tag contains the <role-permission> tag which can be used to define the <principal-to-role> mapping.

The following child tags are also bound. In the previous example, two roles, "manager" and "developer", are mapped to "Peter" and "Linda", respectively.

Tag Description

<role>(1, required)

<role-name> value defined in web.xml. The <role-name> is "manager" in the previous example.

<principal>(0 or more)

User name linked to the <role-name> and managed by JEUS.

For more information, refer to Configuring Web Module Security in JEUS Security Guide.

3.8. Mapping Symbolic References

Since the roles are mapped to the actual users, EJB references, resource references, and managed object references must also be mapped to the actual system resources.

The following is an example of symbolic reference mapping.

Mapping Symbolic References: <web.xml>
<web-app>
    . . .
    <ejb-ref>
        <ejb-ref-name>ejb/account</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>com.mycompany.AccountHome</home>
        <remote>com.mycompany.Account</remote>
    </ejb-ref>
    <resource-ref>
        <res-ref-name>jdbc/EmployeeAppDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
    <resource-env-ref>
        <resource-env-ref-name>
            jms/StockQueue
        </resource-env-ref-name>
        <resource-env-ref-type>
            jakarta.jms.Queue
        </resource-env-ref-type>
    </resource-env-ref>
    . . .
</web-app>

To register the web application, all symbolic reference names used in the <ejb-ref>, <resource-ref>, <resource-env-ref> settings of web.xml must be mapped to the JNDI names of the corresponding resources. To map them, add the corresponding <ejb-ref>, <res-ref>, and <res-env-ref> tags in jeus-web-dd.xml.

These tags contain the following child tags.

  • <jndi-info>

    Tag Description

    <ref-name>

    Reference name is the same as those defined in web.xml and the servlets.

    <export-name>

    JNDI export name that is the actual export name of the resource that <ref-name> refers to.

The following example of jeus-web-dd.xml maps the JNDI names to the aforementioned three references.

Mapping Symbolic References: <jeus-web-dd.xml>
<jeus-web-dd  xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9">
    . . .
    <ejb-ref>
        <jndi-info>
            <ref-name>ejb/account</ref-name>
            <export-name>AccountEJB</export-name>
        </jndi-info>
    </ejb-ref>
    <res-ref>
        <jndi-info>
            <ref-name>jdbc/EmployeeAppDB</ref-name>
            <export-name>EmployeeDB</export-name>
        </jndi-info>
    </res-ref>
    <res-env-ref>
        <jndi-info>
            <ref-name>jms/StockQueue</ref-name>
            <export-name>StockQueue</export-name>
        </jndi-info>
    </res-env-ref>
    . . .
</jeus-web-dd>

4. Monitoring Web Contexts

Monitoring refers to checking information about web contexts. A list of web contexts that are deployed to the web engine and their current states can be checked in the console tool.

Using the Console Tool

Executing the application-info command displays all information about deployed web contexts. For more information about the command, refer to application-info in JEUS Reference Guide.

application-info -type WAR

To display information about a specific web context, execute the command with the -id <application-id> option as follows:

application-info -id <application-id>

5. Controlling Web Contexts

Controlling a web context refers to changing the state of the web context to modify the service. The console tool can be used to reload, suspend, and resume web contexts.

5.1. Reloading Web Contexts

If a deployed web context is changed or the context needs to be reset, the web context can be reloaded instead of being deleted and redeployed. The console tool can be used to reload web contexts.

Using the Console Tool

Execute the reload-web-context command as in the following. For more information about the command, refer to reload-web-context in JEUS Reference Guide.

reload-web-context -ctx <context-name>
seccessfully reloaded

5.2. Monitoring a Thread Pool for Asynchronous Requests in a Web Context

To use thread pools provided by JEUS when web contexts are processing asynchronous requests, the relevant information needs to be configured in the <async-config> element of jeus-web-dd.xml. After configuring the <async-config> element, asynchronous thread pool information can be monitored.

The following is an example of configuring jeus-web-dd.xml. The async thread pool information can be checked using commands in the console tool.

<async-config> Configuration : <jeus-web-dd.xml>
...
<async-config>
    <dispatch-thread-pool>
        <min>5</min>
        <max>20</max>
    </dispatch-thread-pool>
    <background-thread-pool>
        <min>5</min>
        <max>20</max>
    </background-thread-pool>
    <async-timeout-millis>120000</async-timeout-millis>
</async-config>
...

The following describes each configuration tag.

Tag Description

<dispatch-thread-pool>

Minimum and maximum thread pool sizes that are used when AsyncContext#dispatch is invoked.

<background-thread-pool>

Minimum and the maximum thread pool sizes that are used when AsyncContext#start is invoked.

<async-timeout-millis>

Standard time for when the web container processes timeout during an asynchronous task execution. This value is returned when an application calls AsyncContext#getTimeout without calling AsyncContext#setTimeout.

(Default value: 30000, Unit: ms)

Using the Console Tool

To check the thread information of web contexts using the console tool, execute the thread-info command as in the following. For more information about the thread-info command, refer to thread-info in JEUS Reference Guide.

thread-info -server <server-name>

5.3. uspending Web Contexts

For a specific reason, administrators can suspend a deployed web context that is running, and resume it later. For more information, refer to Resuming Web Contexts.

Using the Console Tool

Execute the suspend-web-component command as in the following. For more information about the command, refer to suspend-web-component in JEUS Reference Guide.

suspend-web-component -server <server-name> -ctx <context> -svl <servlet>

or

suspend-web-component -cluster <cluster-name> -ctx <context> -svl <servlet>

5.4. Resuming Web Contexts

Suspended web contexts can be resumed using the console tool.

Using the Console Tool

Execute the resume-web-component command as in the following. For more information about the command, refer to resume-web-component in JEUS Reference Guide.

resume-web-component -server <server-name> -ctx <context> -svl <servlet>

or

resume-web-component -cluster <cluster-name> -ctx <context> -svl <servlet>

6. Tuning Web Contexts

Consider the following when tuning web context configurations (jeus-web-dd.xml) for optimal performance.

  • Increase the user log size and refrain from using "stdout".

  • Disable the JSP engine when not in use.

  • Always disable the <enable-reload> and <check-on-demand> options. These options are intended for a development environment where classes are frequently modified.

  • If possible, use caching. Set as many static content directories in the caching tags as possible. Use a large value for the <max-idle-time> and <max-cache-memory> settings of the cache. They can be set to infinity.

7. Asynchronous Processing Programming

This section describes what application developers must understand about asynchronous processing that has been added starting from servlet 3.0.

7.1. Precautions for Using Servlet Standards

Application developers must directly handle the threads due to the nature of asynchronous processing programming, and this may trigger the following errors.

Some of these errors cannot be detected during testing, but they may occur when too much load is incurred in the production environment. Note that the application developers, and not JEUS, are responsible for preventing these errors.

This section is written based on the servlet standard. (It is applicable to other products as well, besides JEUS.)

Creating Too Many Threads

Creating too many threads reduces the performance of the JVM or causes an OutOfMemoryError to occur. Following is an example of a faulty asynchronous processing programing that creates too many threads.

Example of Faulty Asynchronous Processing Program (1) : <WrongAsyncServlet1.java>
import jakarta.servlet.AsyncContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/WrongAsyncServlet1", asyncSupported = true)
public class WrongAsyncServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        AsyncContext asyncContext = req.startAsync();
        Thread thread = new Thread(new TestRunnable(asyncContext));
        thread.start();
    }

    private class TestRunnable implements Runnable {
        private final AsyncContext asyncContext;

        public TestRunnable(AsyncContext asyncContext) {
            this.asyncContext = asyncContext;
        }

        @Override
        public void run() {
        }
    }
}

There can be more than thousands of concurrent asynchronous requests, which creates thousands of concurrent threads. This can greatly reduce the performance of the JVM or cause an "OutOfMemoryError: unable to create new native thread" to occur. Therefore, it is recommended to use the jakarta.servlet.AsyncContext#start(Runnable) method or a thread pool that can be directly managed.

AsyncContext asyncContext = req.startAsync();
asyncContext.start(new TestRunnable(asyncContext));
Sharing Unsafe Objects with Other Threads

Sharing unsafe objects that are not supposed to be shared with other threads can reduce the performance, result in a deadlock, or violate data integrity.

The following is an example of a faulty asynchronous program that allows different threads to share unsafe objects.

Example of Faulty Asynchronous Processing Program (2) : <WrongAsyncServlet2.java>
import jakarta.servlet.AsyncContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/WrongAsyncServlet2", asyncSupported = true)
public class WrongAsyncServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        AsyncContext asyncContext = req.startAsync();
        asyncContext.start(new TestRunnable(asyncContext));

        byte[] buffer = new byte[1024];
        ServletInputStream inputStream = req.getInputStream();
        inputStream.read(buffer);

        ServletOutputStream outputStream = resp.getOutputStream();
        outputStream.write(buffer);
    }

    private class TestRunnable implements Runnable {
        private final AsyncContext asyncContext;

        public TestRunnable(AsyncContext asyncContext) {
            this.asyncContext = asyncContext;
        }

        @Override
        public void run() {
            byte[] buffer = new byte[1024];
            try {
              ServletInputStream inputStream = asyncContext.getRequest().getInputStream();
              inputStream.read(buffer);
            } catch (IOException e) {
                //log error
                return;
            }

            ServletOutputStream outputStream;
            try {
                outputStream = asyncContext.getResponse().getOutputStream();
              outputStream.write(buffer);
            } catch (IOException e) {
                //log error
                return;
            }
        }
    }
}

The previous example shows multiple threads sharing the ServletInputStream, Reader object, the ServletOutputStream that can be obtained from the Response object, or the Writer object. According to the servlet standard, JEUS does not take responsibility for security of such operations. If asynchronous processing, which is started in the filter or the servlet, is transferred to another thread, if possible, the thread must handle the operation instead of the filter or the servlet codes. This can help prevent programming errors caused by incorrect multi-thread programming knowledge, including performance reduction, deadlocks, and data integrity violation.

Use the jakarta.servlet.ServletRequest#isAsyncStarted() method to check whether asynchronous processing was started from the servlet or the filter which does not directly call the startAsync() method.

Using jakarta.servlet.RequestDispatcher from Asynchronous Threads

Using the jakarta.servlet.RequestDispatcher class from asynchronous threads can cause the program not to work as intended or an exception to occur.

The following is an example of a faulty asynchronous processing program that uses the jakarta.servlet.RequestDispatcher class from an asynchronous thread.

Example of Faulty Asynchronous Processing Program (3) : <WrongAsyncServlet3.java>
import jakarta.servlet.AsyncContext;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/WrongAsyncServlet3", asyncSupported = true)
public class WrongAsyncServlet3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        AsyncContext asyncContext = req.startAsync();
        asyncContext.start(new TestRunnable(asyncContext));
    }

    private class TestRunnable implements Runnable {
        private final AsyncContext asyncContext;

        public TestRunnable(AsyncContext asyncContext) {
            this.asyncContext = asyncContext;
        }

        @Override
        public void run() {
            // ...... do something
            RequestDispatcher requestDispatcher =
                asyncContext.getRequest().getRequestDispatcher("/views/report.jsp");
            try {
                requestDispatcher.forward(asyncContext.getRequest(),
                 asyncContext.getResponse());
            } catch (ServletException e) {
                // log error
            } catch (IOException e) {
                // log error
            }
        }
    }
}

The jakarta.servlet.AsyncContext class provides a way of dispatching from the asynchronous processing thread to another servlet or JSP.

asyncContext.dispatch("/views/report.jsp");

7.2. Other Considerations

There are other precautions in addition to those for the servlet standard.

  • When java.util.concurrent.RejectedExecutionException occurs in the thread when AsyncContext.start(Runnable) is invoked

    AsyncContext.start represents a new task. A thread is needed to process the task, and a thread pool is used because there are limited thread resources. If there is no available thread in the thread pool that can process the new task, the task will be accumulated in the queue.

    When tasks that require a long time to process cause delays in processing, other tasks are accumulated in the queue. Since the queue has a limited size(Maximum:4096), it may not be able to add a new task when it is full. This will cause java.util.concurrent.RejectedExecutionException to occur. Hence, application developers must consider this issue when programming asynchronous processing.

  • When the listener, which communicates with a Web server such as WebtoB and Apache, performs asynchronous processing

    A WebtoB or AJP13 listener uses a limited number of TCP connections. If multiple HTTP requests are delivered to WAS from the web server simultaneously, the service may hang. This method was designed for the original synchronous processing model. When the web application server receives an HTTP request from the web server, it transfers the ownership of the TCP connection to the servlet. It is assumed that the servlet will return the HTTP response immediately after processing and return the TCP connection.

    But it cannot be assumed that the servlet will immediately return the HTTP response in asynchronous processing. If all the TCP connecctions with the web server are used for asynchronous processing, regular HTTP requests cannot be processed temporarily.

    Consider the following solutions to address this problem.

    • Use reverse proxy through URL mapping for asynchronous requests. The reverse proxy targets an HTTP listener.

    • Specify sufficient number of TCP connections to the web server to avoid any asynchronous processing.

      It is recommended to use WebtoB 4.1.6 or later.