OpenSubsystems

Business Components for Java Applications

Open Core

Tutorial

Documentation
Last modified

$Author: bastafidli $
$Date: 2007/03/11 06:30:45 $
$Revision: 1.12 $
$RCSfile: tutorial_deployment.html,v $

Configuration, packaging and deployment

The development of our application is finished. It is time to correctly configure it so that all the pieces work together out of the box. As the last step, we will package it to make it easily deployable on other machines. The format of web application deployment packages is standardized and we just need to follow the set rules. We will package the application as a WAR (web application archive) file to make it easily deployable in any servlet container and as an EAR (enterprise application archive) file to allow an easy deployment in J2EE application servers. The EAR archive is required if we want to deploy our business logic using EJBs.

Open Core makes the packaging of the application easy since the common build targets will do most of the work for us based on the build properties we will set and the configuration files we will create. Once the packages are generated, the deployment can be done in most cases by dropping the appropriate package to a specified folder on a server or by following one of our J2EE application server setup guides.

Our tasks

We will create configuration files for both, Open Core and a servlet container and a application server. We will then use the Open Core based build process to create the deployment and distribution packages. Finally we will deploy and test the application.

oss.properties - the default configuration file used during normal operation of Open Core or application that includes it. This file should contain all the properties needed for correct functioning of Open Core and the application. It may also include other configuration files using oss.config.dependent.file property. It is possible to instruct Open Core to use different file using configuration property oss.config.file.

osstest.properties - the default configuration file used by Open Core JUnit tests. If your JUnit tests derive from the base classes provided by Open Core, this file will be used to configure your test environment during the test execution. This allows to have separate configuration just for testing without affecting the deployment properties. To use different configuration file, the JUnit tests should use call

   Config.getInstance().setPropertyFileName(
      "name of your config file");
                  

osslog.properties - the default configuration file to setup logging levels of Open Core based application. Property java.util.logging.config.file can be used to specify different file to use.

OpenChronicle configuration

OpenChronicle is using Open Core configuration files, which are simple property files that can be easily read and modified on any platform. The documentation contains description of complete set of properties. For this application we have reused the default configuration files shipped with Open Core and modified them to fit our needs.

In the oss.properties View source file we have defined values for the two new properties required by BlogEditServlet View source to perform user authentication

   blogedit.login.username=basta
   blogedit.login.password=fidli
               

Next we have reconfigured Open Core to work without user having to do any additional setup after installation. We have decided to use HSQLDB as our default database because this DBMS is packaged with Open Core and can be used out of the box without any special installation.

   oss.datasource.driver=org.hsqldb.jdbcDriver
   oss.datasource.url=jdbc:hsqldb:generated/test/hsqldb/OSS
   oss.datasource.user=basta
   oss.datasource.password=fidli
   oss.datasource.adminuser=sa
   oss.datasource.adminpassword=
               

Notice that the database our application will use is setup to be /test/hsqldb/OSS. This database will be created in the location from which the application will be started.

We can now modify the way Open Core accesses this database. Open Core has the ability to detect, if it runs inside of a J2EE application server and use its connection pool and transaction manager. As our J2EE application server setup guides demonstrate, this setup might be too complicated for some novice users. For OpenChronicle we have decided to always use the bundled connection pool and transaction manager that do not require any additional configuration and will work exactly the same way regardless of what servlet container or application server is used to run our application.

   org.opensubsystems.core.persist.db.DatabaseConnectionFactory=org.opensubsystems.core.persist.db.connectionpool.DBCPDatabaseConnectionFactoryImpl
   org.opensubsystems.core.util.TransactionFactory=org.opensubsystems.core.persist.db.transaction.SimpleLocalTransactionFactoryImpl
               

Out of the multiple connection pools and transaction managers supported by Open Core we have chosen Jakarta project Commons-DBCP connection pool and Open Core SimpleLocalTransactionFactoryImpl as our default database connectivity layer.

Even though we have instrumented OpenChronicle business logic using XDoclet so that it can be deployed and used as EJBs when Open Core detects it is running inside of J2EE application server, it doesn't make much sense for our little application to use this option. We will therefore instruct Open Core to always invoke our business logic directly as simple java classes. This will give us better performance and smaller footprint. We do so by specifying what controller manager will Open Core use.

   org.opensubsystems.core.logic.ControllerManager = org.opensubsystems.core.logic.ControllerManager               
               

We will use the default settings for the rest of the properties in this and the other two configuration files (osstest.properties View source and osslog.properties View source).

Web application configuration

Since we have based the OpenChronicle build process on the Open Core provided Ant build files, it will automatically build the WAR application archive for us when it finds out that the application contains the standard web application configuration file web.xml View source in the config directory. The web.xml file follows the standard format with some elements used for Open Core specific purpose.

Many of the application wide configuration settings that define look & feel and behavior of the application are specified using context-param elements. Following fragment specifies that user doesn't have to be logged in to access the application. If we change the property oss.webserver.login.required to true user will be always redirected to the login page specified by property oss.webserver.login.url and forced to login before being able to access any other page of the application.

   <context-param>
      <param-name>oss.webserver.login.required</param-name>
      <param-value>false</param-value>
   </context-param>
   <context-param>
      <param-name>oss.webserver.login.url</param-name>
      <param-value>/login.html</param-value>
   </context-param>  
               

Open Core allows to assemble applications from modules and subsystems dynamically without hardcoding the dependencies in the code. This way the user interface decides how are the individual subsystems connected while the backend is assembled and initialized dynamically. This also applies to the application persistence layer. For OpenChronicle we have only one database schema that needs to be initialized.

   <context-param>
      <param-name>oss.database.schema.0</param-name>
      <param-value>org.opensubsystems.blog.persist.db.BlogDatabaseSchema</param-value>
   </context-param>      
               

Since we are using relational database for our persistence layer, we need to include DatabaseContextListener in our web.xml to initialize the database when the application starts.

   <listener>
      <listener-class>org.opensubsystems.core.www.DatabaseContextListener</listener-class>
   </listener>
               

OpenChronicle is using only a single servlet that allows both, browsing and modifying the data. The BlogEditServlet View source is configured in the web.xml the same way as any other servlet. In addition to the required attributes we also specify all the different pages the servlet is using to display the data using init-param elements. These are read and initialized using the cacheUIPath as discussed earlier and allow for separation of processing logic and user interface.

   <servlet>
      <servlet-name>blogedit</servlet-name>
      <servlet-class>org.opensubsystems.blog.www.BlogEditServlet</servlet-class>
      <init-param>
         <param-name>blogedit.login.page</param-name>
         <param-value>/blog/jsp/page/login.jsp</param-value>
      </init-param>
      <init-param>
         <param-name>blogedit.logout.page</param-name>
         <param-value>/blog/jsp/page/logout.jsp</param-value>
      </init-param>
      ...
      <init-param>
         <param-name>blogedit.entry.new.page</param-name>
         <param-value>/blog/jsp/page/newblogentry.jsp</param-value>
      </init-param>
      <init-param>
         <param-name>blogedit.entry.confirmdelete.page</param-name>
         <param-value>/blog/jsp/page/confirmdeleteblogentry.jsp</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>
               

To conclude the servlet configuration we need to map the servlet to URLs it should handle. Our requirement was to make the application look like set of static pages and therefore we will map the servlet to handle any request to HTML files.

   <servlet-mapping>
      <servlet-name>blogedit</servlet-name>
      <url-pattern>*.html</url-pattern>
   </servlet-mapping>
               

In order to provide better user experience in situations when users mistype URLs, we will need to configure the error page we have developed. This page will be displayed every time a user types URL that invokes our application, but doesn't resolve to a valid chronicle or entry.

   <error-page>
      <error-code>404</error-code>
      <location>/blog/jsp/page/missingpageerror.jsp</location>
   </error-page>
               

Finally, notice the marker

   @WEBINC@
               

in between servlet and servlet-mapping sections. Open Core automatically precompiles the application JSP pages if you configure this option in build.properties View source. The build process will replace this marker with the references to the precompiled JSP pages.

Open Core based build process generates all archive files using the name of the application's main package. In our case the main package is called blog and the build process therefore generates the web application archive as blog.war and blog-app.war. The first one will be used later on to construct the enterprise application archive. The second one can be directly deployed in your servlet container or application server.

Most servers will use the name of the WAR file as a portion of the URL using which user accesses the application. If you deploy blog-app.war, the URL to access the front page may be http://yourserver/blog-app/index.html. Since we call our application OpenChronicle we want the URL to reflect this. For the first version we want to use url http://yourserver/chroniclev1/index.html. There is no standard how to setup the context portion of the URL for web applications and every servlet container and application server is using its own method. Most of them allow to include an additional configuration file in the WAR archive to setup context and other non standard parameters. You can find several of those files in the config directory.

  • context.xml View source - Tomcat 5.5x servlet container configuration file
  • jboss-web.xml View source - JBoss application server configuration file
  • jetty-web.xml View source - Jetty servlet container configuration file
  • jonas-web.xml View source - JOnAS application server configuration file
  • weblogic.xml View source - WebLogic application server configuration file

Enterprise application configuration

In a similar fashion as with the WAR application archives, the build process will automatically build the EAR application archive for us when it finds out that the application contains the standard enterprise application configuration file application.xml View source in the config directory. The application.xml file follows the standard format.

   <?xml version="1.0" encoding="UTF-8"?>
   <!DOCTYPE application PUBLIC 
    "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
    "http://java.sun.com/dtd/application_1_3.dtd">
   <application>
   <!--
      This is commented because there is an error occured while application
      is deployed under BEA WebLogic 8.1. There is unknown 'xmlns' parameter.

   <application xmlns="http://java.sun.com/xml/ns/j2ee"
   			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   		 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
		   	 http://java.sun.com/xml/ns/j2ee/application_1_4.xsd"
			    version="1.4">
   -->
      <display-name>OpenChronicle v1</display-name>
      <description>OpenChronicle application v1</description> 
   
      <module> 
         <ejb>blog-ejb.jar</ejb> 
      </module> 

      <module> 
         <web> 
            <web-uri>blog.war</web-uri> 
            <context-root>chroniclev1</context-root> 
         </web> 
      </module> 
   
   </application>
               

The content of the file is simple, it includes the references to the web application archive and the EJB archive built for us by the build process. Notice that we have specified to use the blog.war instead of blog-app.war (both flavors, one with the libraries and other without them are built during the build process), since the java libraries are in the EAR file shared among all modules. The built process includes the shared libraries at the correct location in the EAR file. Enterprise application archive format support setting up the application context directly and therefore there is no need for application server specific files in this case.

Packaging and deployment

Open Core based build process provides two convenient targets to package the application. The build target will compile the code, generate documentation and create all reusable libraries, web application archives and enterprise application archive. As soon as the application is built we can run it directly from your IDE if we follow these simple instructions. The distribute target creates three distribution packages that we can give to our audience.

src package contains all the source code required to build the application. In order to make the package smaller it doesn't contain the required external libraries, those can be obtained from the bin package.

bin package contains the reusable libraries created as part of our application. It also includes any external libraries referenced by the application and any build and configuration files needed to reuse these libraries. This package can be distributed to developers who want to integrate with or embed our application.

app package contains the application in a user friendly format. We will distribute this package to our users who will run the application. The webapp folder contains the WAR and EAR files suitable for deployment in the desired servlet container or application server. These are usually deployed using server management application or by dropping them to a specified folder of the server. In certain cases the server may not contain all the required libraries that should be present and therefore they were not included in the WAR or EAR archives. In such case the user may need to manually copy these libraries from the external folder to a folder in the server where they will be recognized. For example, some versions of Tomcat may require to copy files jta.jar and jts.jar into commons\lib folder.

Accessing the application

Once the application is deployed, lets open a browser and go to url http://yourserver/chroniclev1/index.html (or http://yourserver/blog-app/index.html if the server doesn't support the context configuration) and start chronicle our world.

OpenChronicle is finished, lets summarize what we have accomplished and how did Open Core helped us to do it.

Next: Summary
Previous: Securing the web application