Application Deployment

To run an application you must deploy it first, this consists of two phases

The simplest way to deploy an application is to place it in the server/xxx/deploy directory, the deployment scanner scans this directory to see if any new or updated applications have been changed of put into this directory, if there are then it deploys them, if the deployment scanner is not running then you must restart JBoss. If you have updated an application with a more recent timestamp, then the server will undeploy it, then redeploy it, this will cause all current session state for active users to be lost.

To undeploy an application simply remove it from the server/xxx/deploy directory, when the scanner notices it has gone, it will undeploy the application.

You can of course use the JMX console or twiddle to deploy and undeploy applications.

Use twiddle to deploy an application

twiddle invoke "jboss.system:service=MainDeployer" deploy /some/path/myapp.ear

Note: apon a restart the application will not be deployed as it needs to be in server/xxx/deploy

Application Packages

When you deploy an application, you always deploy the applications package, a package can either be an archive file or an exploded directory. An archive file would be a Web Archive (WAR) or Enterprise Archive (EAR) file, an exploded directory will be a directory structure containing any JARs and other files required for the package

So which one is better, like everything in life there are advantages and disadvantages, with a single file there is only one file to deal with, which means you don't get partially deployed problems (maybe one file was deleted in the directory). With an exploded directory everything is in plain view and accessible, also if you edit a primary descriptor for an application, such as the application.xml within an EAR, then the hot deployer redeployes the application (see table below for all primary descriptors and files), if you change any JSPs or text files the application can start to use them, also you can add files easily.

Application Type Primary descriptor
WAR WEB-INF/web.xml
EAR META-INF/application.xml
SAR META-INF/jboss-service.xml
JAR META-INF/ejb-jar.xml
RAR META-INF/ra.xml

If you deploy an archive file the server unpacks the EAR file in the server/xxx/tmp/deploy directory using a generated name based on the filename, but if you are thinking that you can have the best of both worlds and use this directory then think again because this directory is deleted when JBoss is restarted.

The are two types of applications business applications and services, business applications provides a business function to end users where as a service provides functionality that supports other applications (database access).

JBoss supports a large number of application types, it uses the suffix or directory name to distinguish between them

Suffix Application Type
.deployer
-deployer-beans.xml
Defines an application deployer, which is used to deploy a specific type of application. These applications types show up only in server/xxx/deployers directory
.aop
-aop.xml
Defines aspects to apply to classes that extend or add functionality to those classes
.sar
-service.xml
Defines a service, which add functionality to the application server
-jboss-beans.xml Defines POJOs for the microcontainer
.rar Defines a resource adaptor, which is used to connect to enterprise information systems using the Java Connector Architecture (JCA)
-ds.xml Defines a data source, which is used to access data in a database
.har Defines a Hibernate archive, which is used to access a database using Hibernate (I have an example of this below)
.jar Defines a collection of EJBs that provides business logic for an application or could be a class library
.zip The deployer examines the contents of the zip file to find what type of application it is and uses the proper deployer to deploy it
.war Defines a web application, which provides a web interface for an application or web service
.wsr A JBoss specific archive that defines a web service, use this suffix to deploy the web services after all the WAR files have been deployed
.ear Defines a Java EE application, which is a collection of EJBs, WAR files and class libraries
.bsh Defines a service using a bean shell script
.last Treated as a directory (or archive file) of applications to be deployed, the contained applications are deployed last, in the order given by their suffixes.

The above table is in order of deployment, so the .deployer is first and the .last is last to be deployed, so for instance if you want an application to be deployed last, name the directory doit.last.

Applications themselves can be nested, you could have a JAR in the application that contains a SAR which contains a JAR and so on, this is like a russian doll (one inside another), JBoss handles this by deploying the inner most first based on the ordering in the above table, you can also change the order by using the descriptor file for that particular application, for instance you could use the META-INF/application.xml file if it were a EAR deployment.

Deployers

Deployers are configured in the deployers.xml and profile.xml descriptor files, both are found in server/xxx/conf/bootstrap directory. These files contain several POJOs that manage various deployment responsibilities.

Bean Property Description
MainDeployer structuralDeployers A list of beans that define the high-level classification of the kinds of things that can be deployed, for example a number of file types are packed archives and are listed for the JarStructure bean
deployers A list of various deployers, these deployers handle the files that were identified by the structuralDeployers. Think of this way, the structuralDeployers property identifies all the file types that are of interest, whereas the deployers property identifies the service that deploy each of those file types.
DeploymentFilter prefixes
suffixes
matches
identifies which files or directories can be ignored by the deployer, the match property matches a full, simple directory or filename.
VFSDeploymentScanner URIList A list of locations that the deployer scans for applications to deploy
URIs Same as URIList but the list is provided as a single comma-separated string of values
recursiveSearch Indicates whether the scanner should recursively search subdirectories for applications to deploy (true (default) or false)
VFSBootstrapScanner (same as for VFSDeploymentScanner) Locations to be scanned during the bootstrap process
VFSDeployerScanner (same as for VFSDeploymentScanner) Locations to be scanned for various deployers
HDScanner scanEnabled set to true for HOT deployment or false to turn it off
scanPeriod The number of milliseconds the hot deployer waits between performing scans
scanThreadName You can change the default HDScanner thread name

Sometimes you may want to use a different deploy directory, so you would update profile.xml to point to the new location, you might want to turn off hot deployment in a Production environment.

Class Loading

I have already discussed classloading in my Tomcat section, so I am not going to do into too much detail here, JBoss uses many class loaders each of which load a specific set of classes, the reason for this is to separate the various applications that are deployed, this allows different applications to load its own class version, its the class loader that gives applications visibility to classes.

The classloader structure can be seen in the diagram below

At the lowest level are the classes in the classpath and those in the lib directory which in include the boot classes. The next level are those in the applications lib directory and at the top level are those classes in the WAR file.

You can specify that a particular application should have its own class loader repository and prefer using its own classes over those available in other applications, this is known as scoping. You do this by defining a class loader repository in one of the JBoss specific configuration files.

There are two items that you can configure

Class Loader  
Class Repository  

Deploying Miscellaneous Applications

Although there are many applications there are two common applications that are generally deployed in most configurations data sources (database) and Hibernate archives.

At somepoint in time, you will want to connect to a database and you will require a mechanism to do this, normally you would use JDBC within your application but this is a very expensive operation, so you try to do this infrequently, the best way around this is to let the application server perform this for you, which is what it does then creating a data source (I have already discussed a similar topic in my Tomcat section under JDBC). The application server then can manage the database connections by pooling them and providing connections to the database when it needs them. To create a data source you deploy a *-ds.xml file, the one below is the example oracle-ds.xml file (taken from docs/examples/jca directory) and modified for my own environment.

You also need to copy the Oracle JDBC driver (ojdbc14.jar) to the server/XXX/lib directory.

One note I will make is that I had to put the @ in front of the localhost (missing @ in the example oracle-ds.xml), it produced a funny error regarding the TNSname could not be found, which I know that I obtained the right information from JNDI, it kept using "username:password:orcl" instead of "jboss:jboss:D01"

Oracle Data Source <datasources>
  <local-tx-datasource>
    <jndi-name>jdbc/OracleDS</jndi-name>
    <connection-url>jdbc:oracle:thin:@localhost:1521:D01</connection-url>

    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
    <user-name>jboss</user-name>
    <password>jboss</password>
    <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
    <!-- Checks the Oracle error codes and messages for fatal errors -->
    <exception-sorter-classname>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
    -->

    <!-- sql to call on an existing pooled connection when it is obtained from pool - the     OracleValidConnectionChecker is prefered-->
    <check-valid-connection-sql>select * from dual;</check-valid-connection-sql>

    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
    <metadata>
      <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

There are three different data source types available

<local-tx-datasource> Identifies a data source that uses transactions, even distributed transactions within the local application server but does not use distributed transactions among multiple application servers
<no-tx-datasource> Identifies a data source that does not use transactions, use this if you only read from a database
<xa-datasource> Identifies a data source that uses distributed transactions among multiple applications servers.

Here are the options available but I am only going to list the one which are not self explaining

<security-domain> References a security domain that uses an identity login module defined in login-config.xml, you use this instead of the <username> and <password> attributes.
<min-pool-size> minimum number of open connections maintained by the application server.
<max-pool-size> maximum number of open connections maintained by the application server.
<idle-timeout-minutes> if a connection is not used for the specified time then the connection is closed
<blocking-timeout-millis> number of milliseconds a requestor waits for a connection to be available before the wait times out.
<exception-sorter-class-name> identifies a class used to determine if an error number returned by the database is fatal
<check-valid-conection-sql> uses a sql statement to check the validity of the connection
<type-mapping> used by the container-managed persistence (CMP) code to identify the database and adjust its database handling accordingly.
<connection-property> identifies a property to pass to the java.sql.Driver when establishing a database connection
<transaction-isolation> Identifies the transaction isolation level with the database, valid value include

TRANSACTION_READ_UNCOMMITTED
TRANSACTION_READ_COMMITTED
TRANSACTION_REPEATABLE_READ
TRANSACTION_SERIALIZABLE
TRANSACTION_NONE

Once you have your data source file and your JAR driver file, you drop the JAR file into server/xxx/lib then drop the data source in the deploy directory (server/xxx/deploy), its then treated like an application, specifically as a service.

Once deployed several MBeans are created

jboss.jca:name=XXX,service=DataSourceBinding Manages the javax.sql.DataSource objects
jboss.jca:name=XXX,service=LocalTxCM Manages the connection manager, which is responsible for the connection pool , created only for <local-tx-datasource>
jboss.jca:name=XXX,service=XATxCM Manages the connection manager, which is responsible for the connection pool, created only for <xa-datasource>
jboss.jca:name=XXX,service=NoTxCM Manages the connection manager, which is responsible for the connection pool, created only for <no-tx-datasource>
jboss.jca:name=XXX,service=ManagedConnectionFactory Manages the connection factory, which creates database connections
jboss.jca:name=XXX,service=ManagedConnectionPool Manages the pool of database connections, use his monitor and change the min and max connections count
jboss.jdbc:name=XXX,service=metadata,datasource=XXX You can use this Bean to change the type mapping, it does not appear if the data source is defined as a no transaction data source, for example oracle8i or oracle 9i

Deploying a Hibernate Archive

You can use a higher-level construct than SQL statements, which is what you use in JDBC, Hibernate is an object-to-relational mapping (ORM) layer that enables you to use POJOs in your application while Hibernate worries about mapping those objects to tables in the relational database. JBoss provides a simple mechanism to support the use of Hibernate within your applications - The Hibernate Archive. To create a Hibernate archive you need to do the following

Now for an example

Coding the persistent Object (Video.java) # Use a command similar to before to compile the java file
javac -classpath classes;. -d classes Video.java

# Once compiled place in the video.har\org\jbia\har directory

package org.jbia.har;

public class Video {

  private int id;
  private String name;
  private int minutes;
  private float price;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getMinutes() {
    return minutes;
  }

  public void setMinutes(int minutes) {
    this.minutes = minutes;
  }

  public float getPrice() {
    return price;
  }

  public void setPrice(float price) {
    this.price = price;
  }

  public String toString() {
    return "#" + id + ": " + name + " (" + minutes + "), " + price;
  }
}

Coding the mapping file (Video.hbm.xml)

# Place in the video.har\org\jbia\har directory

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="org.jbia.har.Video" table="Video">
    <id name="id" type="integer" column="id">
      <generator class="sequence">
        <param name="sequence">video_seq</param>
      </generator>
    </id>
    <property name="name" type="string" column="name"/>
    <property name="minutes" type="integer" column="runTime"/>
    <property name="price" type="float" column="price"/>
  </class>
</hibernate-mapping>

Note: here we are defining how the contents of the Video class are mapped to the table in the database, I have a sequence in Oracle called "video_seq" defined in Oracle

Coding the Hibernate Archive Configuration file (video-hibernate.xml)

# Place in the video.har/META-INF directory

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-configuration xmlns="urn:jboss:hibernate-deployer:1.0">
<session-factory name="java:/hibernate/jbia/VideoSF" bean="jbia.har:app=Video">
  <property name="datasourceName">java:jdbc/OracleDS</property>
  <property name="dialect">Oracle9idialect</property>
  <property name="hbm2ddlAuto">create-drop</property>
  <property name="showSqlEnabled">true</property>
  <depends>jboss:service=Naming</depends>
  <depends>jboss:service=TransactionManager</depends>
  <depends>jboss.jca:name=jdbc/OracleDS,service=DataSourceBinding</depends>
</session-factory>
</hibernate-configuration>

Note: this is not a data source but builds on the configured Oracle data source, there are number of hibernate properties see the table below

Create the Client
Coding the hibernate client (VideoServlet.java)

# Use a command similar to before to compile the java file
javac -classpath d:/jboss-dev/lib/servlet-api.jar;d:/jboss-dev/lib/hibernate3.jar;classes;. -d classes VideoServlet.java

# Once compiled place in the video.har\org\jbia\har directory

package org.jbia.har;

import java.io.IOException;
import java.util.List;

import javax.naming.InitialContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

/**
* Simple servlet used to illustrate working with a Hibernate archive. The
* servlet accepts user input for a new video, adds the video to the database,
* and then displays to the user all of the videos.
*/
public class VideoServlet extends HttpServlet {

   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                                      throws ServletException, IOException {

     Session hs = null;
     try {
           InitialContext ctx = new InitialContext();
           SessionFactory hsf = (SessionFactory) ctx.lookup("java:/hibernate/jbia/VideoSF");
           hs = hsf.openSession();

           String strName = req.getParameter("name");
           String strMinutes = req.getParameter("minutes");
           String strPrice = req.getParameter("price");
           if ((strName != null) && (strMinutes != null) && (strPrice != null)) {
             Video video = new Video();
             video.setName(strName);
             video.setMinutes(Integer.parseInt(strMinutes));
             video.setPrice(Float.parseFloat(strPrice));
             hs.save(video);
             hs.flush();
           }

           Query qVideo = hs.createQuery("from org.jbia.har.Video order by name");
           List mvVideo = qVideo.list();
           req.setAttribute("videos", mvVideo);

           ServletContext sc = getServletContext();
           RequestDispatcher rd = sc.getRequestDispatcher("/index.jsp");
           rd.forward(req, resp);

     } catch (Throwable e) {
          e.printStackTrace();
          resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
     } finally {
          if (hs != null) {
            hs.close();
          }
     }
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                                       throws ServletException, IOException {
    doGet(req, resp);
  }
}

index.jsp

# place in the video.war directory

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hibernate Archive Example</title>
</head>

<body>  
  <h3>Input data for new video:</h3>
  <form action="video" method="post">
  <table class="input">
  <tr>
    <th>Name:</th>
    <td><input type="text" size="50" name="name" value="Monty Python and the Holy Grail" /></td>
    </tr>
    <tr>
    <th>Minutes:</th>
    <td><input type="text" name="minutes" value="91" /></td>
    </tr>
    <tr>
    <th>Price:</th>
    <td><input type="text" name="price" value="14.99" /></td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td><input type="submit" value="submit" title="Add" /></td>
    </tr>
  </table>
  </form>

  <c:if test="${videos != null}">
    <h3>Available videos:</h3>
    <table class="list">
      <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Minutes</th>
      <th>Price</th>
      </tr>
      <c:forEach var="video" items="${videos}">
        <tr>
        <td class="number">${video.id}</td>
        <%--
           c:out will filter special characters to prevent cross-site scripting
           attacks. We need to do it only for this attribute because it is the
           only one that is a string.
        --%>
        <td><c:out value="${video.name}" /></td>
        <td class="number">${video.minutes}</td>
        <td class="number">${video.price}</td>
        </tr>
      </c:forEach>
    </table>
  </c:if>

</body>
</html>

web.xml # place in the video.war/WEB-INF directory

<web-app 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-app_2_5.xsd"
         version="2.5">

<servlet>
  <servlet-name>Video</servlet-name>
  <servlet-class>org.jbia.har.VideoServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>Video</servlet-name>
  <url-pattern>/video</url-pattern>
</servlet-mapping>

<welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

</web-app>

The File layout
File layout in the server directory
The directory structure should look like sometime below



More Hibernate properties

Hibernate Property
MBean attribute
Special Handling
hibernate.cache.provider_class
CacheProviderClass
defaults to org.hibernate.cache.HashtableCacheProvider
hibernate.transaction.flush_before_completion
-none-
Always set to true
hibernate.transaction.auto_close_completion
-none-
Always set to true
hibernate.connection.agressive_release
-none-
Always set to true
hibernate.connection.release_mode
-none-
Always set to after_statement