Jboss Admin Tutorial: Web Application Administration

7. Web Application Administration

7.1. Web Technologies

../../static/bookshelf/common/images/web_application_technologies.png

CGI - Common Gateway Interface

  • CGI scripts executed in a separate process by the web server (e.g. Apache HTTPD)
  • Used since the early days because of its simplicity (minimal requirements). Still popular.
  • Language independent, but mostly used in conjunction with Perl and Python
  • Inefficient, as interpreters had to be reloaded and scripts re-parsed on every single request

Cold Fusion - ColdFusion Markup Language (CFML)

  • Developed and controlled by Macromedia
  • Easy to learn and powerful
  • Still widely used, although many shops are switching to other technologies

PHP - PHP Hypertext Preprocessor

  • Scripting language that runs within PHP-enabled web servers, like Apache
  • Very popular for developing smaller-scale web applications, especially in the open-source community
  • Easy to learn and powerful

ASP - Active Server Pages

  • Developed and controlled by Microsoft
  • Runs on Microsoft IIS web server
  • Dynamic content written in VBScript, JavaScript, VisualBasic, or C# (part of ASP.NET)

Servlet / JSP - JavaServer Pages

  • Developed through the Java Community Process (part of Java EE)
  • Based on Java: OO, rich library, powerful environment, platform independent, efficient (run in-memory), scalable
  • Easy to separate presentation from logic

7.2. CGI vs. Servlets/JSPs

../common/images/cgi_vs_servlet.png

Servlets/JSPs are executed in the same Java Virtual Machine process in separate threads. This leads to very optimized and efficient system utilization.

CGI scripts on the other hand also utilize the system, but very inefficiently. Many CPU cycles are spent on starting/scheduling new processes, re-loading the interpreter, and re-parsing the scripts. Sharing of data is achieved through some external system, like RDBMS, file system, or another process.

7.3. Tomcat Web Container

  • Apache Tomcat (6.x) is a free and open source Servlet (2.5) and JSP (2.1) Container
  • Embedded in JBoss AS as deploy/jbossweb.sar
  • JBoss AS configuration for Tomcat integration in each application are located in META-INF/jboss-web.xml

    • Default JAAS Security Domain
    • Class Loading and Sharing
    • Session Management and Caching
    • Clustering and Load Balancing (in all config)
<jboss-web>
  <security-domain>java:/jaas/simple-security-domain</security-domain>
</jboss-web>

7.4. Tomcat’s server.xml

  • Tomcat’s own configuration file: deploy/jbossweb.sar/server.xml
  • Configures

    • Connectors (HTTP, HTTPS, AJP)
    • Security Realms (Inherits from JBoss)
    • Logging (Tomcat Service)
    • Valves (Request/Response interceptors)
    • Virtual Hosts (Name-based)
    • Web application contexts (Per-app configuration)
<Server>
   <!-- Optional listener which ensures correct init and shutdown of APR,
        and provides information if it is not installed -->
   <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
   <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
   <Listener className="org.apache.catalina.core.JasperListener" />

   <Service name="jboss.web">
    <!-- A HTTP/1.1 Connector on port 8080 -->
    <Connector protocol="HTTP/1.1" port="8080" address="${jboss.bind.address}"
      connectionTimeout="20000" redirectPort="8443" />
    ...
    <!-- A AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3" port="8009" address="${jboss.bind.address}"
      redirectPort="8443" />
    ...
    <Engine name="jboss.web" defaultHost="localhost">
      ...
      <Realm className="org.jboss.web.tomcat.security.JBossWebRealm"
        certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping"
        allRolesMode="authOnly"
      />
      ...
      <Host name="localhost">
        ...
        <Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve"
          cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager"
          transactionManagerObjectName="jboss:service=TransactionManager" />
      </Host>
    </Engine>
  </Service>
</Server>

7.5. Tomcat’s web.xml

  • Default web descriptor for all web apps deployers/jbossweb.deployer/web.xml
  • Configures
  • Common Filters
  • Servlets for handling static content (DefaultServlet), JSPs, SSI, CGI scripts, invokers, etc.
  • Default session timeout
  • MIME Type mappings
  • Welcome file list: /bookshelf/jboss_admin_tutorial/index, index.jsp, etc.
[Note]Note

While most of the settings in this file can be left as default, the JSP servlet has a number of options (http://tomcat.apache.org/tomcat-6.0-doc/jasper-howto.html) that we may wish to change before putting JBoss in production. These include: development, modificationTestInterval, checkInterval, classdebuginfo, suppressSmap, mappedfile, trimSpaces, and genStrAsCharArray.

[Note]Note

While the deployment descriptors are usually the responsibility of developers and application assemblers, this web.xml file is global to the entire web container and as such it is owned by the administrators.

7.6. Defining and Mapping Servlets

  • In WEB-INF/web.xml file:

    • Define a servlet with <servlet> where <servlet-name> points to a fully qualified <servlet-class>

      • Optionally initialize with <init-param>-s
      • Optionally <load-on-startup>
    • Map a defined servlet with <servlet-mapping> where <url-pattern> points to previously specified <servlet-name>

      • Map under multiple <url-pattern>-s if needed

        <servlet>
         <servlet-name>IPLoggerServlet</servlet-name>
         <servlet-class>example.servlet.IPLoggerServlet</servlet-class>
          <init-param>
           <param-name>file</param-name>
           <param-value>/WEB-INF/ip.log</param-value>
          </init-param>
          <load-on-startup>2</load-on-startup>
        </servlet>
        
        <servlet-mapping>
         <servlet-name>IPLoggerServlet</servlet-name>
         <url-pattern>/ip</url-pattern>
        </servlet-mapping>
        
        <servlet-mapping>
         <servlet-name>IPLoggerServlet</servlet-name>
         <url-pattern>/logmyip</url-pattern>
        </servlet-mapping>
[Note]Note

While web.xml files are now defined with schemas, prior to J2EE 1.4 they were defined with DTDs. These are often easier to read by humans:

<!ELEMENT servlet (icon?, servlet-name, display-name?, description?,(servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)>
<!ELEMENT servlet-mapping (servlet-name, url-pattern)>

7.7. Defining and Mapping Filters

  • In WEB-INF/web.xml file:

    • Define a filter with <filter> where <filter-name> points to a fully qualified <filter-class>

      • Optionally initialize with <init-param>-s
    • Map a defined filter with <filter-mapping> where <url-pattern> points to previously specified <filter-name>

      • Map under multiple <url-pattern>-s if needed
      • Map with /* to apply to all requests

        <!ELEMENT filter (icon?, filter-name, display-name?, description?, filter-class, init-param*)>
        <filter>
          <filter-name>Logger</filter-name>
          <filter-class>example.servlet.AccessLogFilter</filter-class>
        </filter>
        
        <!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name))>
        <filter-mapping>
          <filter-name>Logger</filter-name>
          <url-pattern>/*</url-pattern>
        </filter-mapping>

7.8. Session Configuration

  • Configure <session-timeout> in the <session-config> element
  • The value (in minutes) indicates how long the servlet container will maintain an idle session (in memory or on disk) before timing out
  • Value ⇐ 0 indicates that sessions never expire - unless destroyed explicitly (through users logouts)
  • Significant impact on server memory usage and end users dissatisfaction with time outs

    <session-config>
      <session-timeout>30</session-timeout>
    </session-config>

7.9. Welcome File List

  • Configured through <welcome-file-list> in WEB-INF/web.xml file
  • Defines the files to be served when an end-user makes a request for a directory on the server (e.g. http://host.com/dir/)
  • Defined globally, but can be overridden in individual applications (replaces global)
  • The first matched file is served
  • If no match is made, directory listing is returned, or (if disabled) an HTTP 404

    <!ELEMENT welcome-file-list (welcome-file+)>
    <welcome-file-list>
      <welcome-file>/bookshelf/jboss_admin_tutorial/index</welcome-file>
      <welcome-file>index.htm</welcome-file>
      <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

7.10. Error Documents

  • Configured through web.xml's <error-page> elements
  • Define mapping between an <error-code> (or <exception-type>) and a <location> of the error document to be served on those errors
  • Exception-type is somewhat unreliable as Java EE app servers wrap exceptions

    <!ELEMENT error-page ((error-code | exception-type), location)>
    <error-page>
      <error-code>404</error-code>
      <location>/FileNotFoundError.html</location>
    </error-page>
    
    <error-page>
      <exception-type>
        java.lang.IllegalArgumentException
      </exception-type>
      <location>/IllegalInputError.html</location>
    </error-page>
    [Note]Note

    The <location> is relative to the root of the application and it must start with a slash (/) character.

[Note]Note

Browsers such as Microsoft’s Internet Explorer and Google’s Chrome do not show server error pages (instead they show friendly error pages) unless those pages are either styled (e.g. contain references to style sheets, images, etc.) or exceed 512 bytes

7.11. Serving Static Content

  • Tomcat serves static content via its DefaultServlet (configured in Tomcat’s web.xml file)

    • Any file under an application’s structure (but outside WEB-INF and META-INF directories) is considered static content
  • Application deploy/ROOT.war/ is considered special - it has no context path

    • Serves all content not served by any other application
  • Returns a HTTP 404 response if the requested static content does not exist
  • ROOT.war also provides support for http://localhost:8080/status servlet (see its WEB-INF/web.xml)
[Note]Note

For example, to share images across multiple applications, create a directory deploy/ROOT.war/images/ and place your images there. A request for http://localhost:8080/images/cool.png would be served from ROOT.war/images/cool.png

7.12. Virtual Hosting with Tomcat

  • Add hosts and aliases to server.xml:

    <Host name="myhost.com">
      <Alias>www.myhost.com</Alias>
    </Host>
  • Register applications for virtual hosts in their WEB-INF/jboss-web.xml files:

    <jboss-web>
      <context-root>/myapp</context-root>
      <virtual-host>myhost.com</virtual-host>
    </jboss-web>
  • Applications default to host specified by <Engine>'s defaultHost attribute

    server.xml

    <Server>
      <Service>
        <Connector .../>
        <Engine>
         <Host name="myhost.com">
           <Alias>www.myhost.com</Alias>
         </Host>
         <Host name="anotherhost.com"/>
        </Engine>
      </Service>
    </Server>

    myapp.war/WEB-INF/jboss-web.xml: 

    <jboss-web>
      <context-root>/myapp</context-root>
      <virtual-host>myhost.com</virtual-host>
    </jboss-web>

    ROOT-another.war/WEB-INF/jboss-web.xml: 

    <jboss-web>
      <context-root>/</context-root>
      <virtual-host>anotherhost.com</virtual-host>
    </jboss-web>

7.13. Web Access Logging

  • In server.xml define a <Valve> in

    • <Engine> - global for the entire server
    • <Host> - per virtual host
    • <Context> - per application

      • Store as WEB-INF/context.xml
  • Automatic rotation of logs (daily/hourly)
  • Supports customizable and standard patterns
  • Conditional logging

    <Valve className="org.apache.catalina.valves.AccessLogValve"
      prefix="localhost_access_log." suffix=".log"
      pattern="common" directory="${jboss.server.home.url}/log"
      resolveHosts="false" />

In addition to common and combined, pattern can also be set to a mix of:

  • %a - Remote IP address
  • %A - Local IP address
  • %b - Bytes sent, excluding HTTP headers, or - if zero
  • %B - Bytes sent, excluding HTTP headers
  • %h - Remote host name (or IP address if resolveHosts is false)
  • %H - Request protocol
  • %l - Remote logical username from identd (always returns -)
  • %m - Request method (GET, POST, etc.)
  • %p - Local port on which this request was received
  • %q - Query string (prepended with a ? if it exists)
  • %r - First line of the request (method and request URI)
  • %s - HTTP status code of the response
  • %S - User session ID
  • %t - Date and time, in Common Log Format
  • %u - Remote user that was authenticated (if any), else -
  • %U - Requested URL path
  • %v - Local server name
  • %D - Time taken to process the request, in millis
  • %T - Time taken to process the request, in seconds

See http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html

7.14. Lab: Tomcat

  • Define a HTTP 404 error handler for the ROOT.war web application and test it (You can find help here)

    • A simple 404.html error document could look like:

      <html>
        <head><title>File Not Found</title></head>
        <body>
          <h2>The file you requested has not been found</h2>
          <p><a href="http://google.com">Search for it?</a></p>
        </body>
      </html>
      [Note]Note

      Internet Explorer will not show the error document (it will use its own error page) if the content is smaller than 512 bytes. Either add more content to your error page or use a different browser, like Firefox.

  • Configure two virtual hosts

    • Use localhost and the name of your machine or
    • Invent new hostnames and add them to hosts file

      • The location of this file is dependent on the operating system:

        • /etc/hosts (on most UNIX-type operating systems)
        • C:\Windows\System32\drivers\etc\hosts (on Windows)
      • Alternatively, use vhost1.marakana.com and vhost2.marakana.com which simply point back to 127.0.0.1. In fact, www.vhost1.marakana.com and www.vhost2.marakana.com also point to the same loop-back address.
  • Deploy some static content and test that you get retrieve it through your browser
  • Set up web access logging

    • Separate for each host
    • Use a different pattern on each