$Author: bastafidli $
$Date: 2007/03/11 06:30:45 $
$Revision: 1.12 $
$RCSfile: tutorial_deployment.html,v $
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.
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 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
file we have defined values for the two
new properties required by
BlogEditServlet
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
and osslog.properties
).
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
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
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
. 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
jboss-web.xml
jetty-web.xml
jonas-web.xml
weblogic.xml
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
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.
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.
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