Showing posts with label mapping external directories. Show all posts
Showing posts with label mapping external directories. Show all posts

Saturday, August 29, 2009

Map an external directory into your application directory in Tomcat

This article will explain how to map an external directory into your application directory (i.e. how to create a virtual directory) using Tomcat.
Let me first describe why you may need to create a virtual directory in your application. Suppose your application allows a user to upload images and there is no restriction on the total number of images that can be uploaded in your application. The folder in which the images are loaded will keep on growing in size from KBs to MBs to GBs, eventually the size of the application will also grow which will hamper the speed of your application.

Creating a virtual directory inside your context in Glassfish v3 Preview is straight forward as discussed in my previous post. While setting up the same in tomcat you need to make sure if you are using Tomcat 6 then it is version 6.0.18 or higher. The method that I had followed from the Tomcat manual does not works in version 6.0.16.

You might know that you can create a virtual host in tomcat and run your application by placing it anywhere outside of the "webapps" folder. Basically you are creating a new context which is outside the "webapps" folder. What I will be talking about is having something like "/yourContext/images", where the "images" folder is anywhere outside the "yourContext" folder which is inside "webapps" i.e. "images" can be anywhere other than "/webapps/yourContext/images".

Let us begin with what the Tomcat documentation says here,

The Context element represents a web application, which is run within a particular virtual host. Each web application is based on a Web Application Archive (WAR) file, or a corresponding directory containing the corresponding unpacked contents, as described in the Servlet Specification (version 2.2 or later).
You may define as many Context elements as you wish. Each such Context MUST have a unique context path. In addition, a Context must be present with a context path equal to a zero-length string. This Context becomes the default web application for this virtual host, and is used to process all requests that do not match any other Context's context path.

For Tomcat 6, unlike Tomcat 4.x, it is NOT recommended to place elements directly in the server.xml file. This is because it makes modifing the Context configuration more invasive since the main conf/server.xml file cannot be reloaded without restarting Tomcat.

Context elements may be explicitly defined:
  • In the $CATALINA_BASE/conf/context.xml file: the Context element information will be loaded by all webapps.
  • In the $CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default file: the Context element information will be loaded by all webapps of that host.
  • In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml extension) will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar. The default web application may be defined by using a file called ROOT.xml.
  • Only if a context file does not exist for the application in the $CATALINA_BASE/conf/[enginename]/[hostname]/, in an individual file at /META-INF/context.xml inside the application files. If the web application is packaged as a WAR then /META-INF/context.xml will be copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to match the application's context path. Once this file exists, it will not be replaced if a new WAR with a newer /META-INF/context.xml is placed in the host's appBase.
  • Inside a Host element in the main conf/server.xml.
With the exception of server.xml, files that define Context elements may only define a single Context element.

Let us concentrate on the bullet point:
  • In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml extension) will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar. The default web application may be defined by using a file called ROOT.xml.
It tells you how to create a multilevel context path, in other words how to create a virtual directory inside your context.

The method is simple, which involves the following steps:

1. Open the CATALINA_HOME location which is where you have installed tomcat.
2. Locate and change directory to "conf"
3. Now create a directory called "Catalina".
4. Now create another directory "localhost" inside the newly created directory "Catalina".
5. Inside "localhost" create a file called "yourContext#images.xml", replacing "yourContext" with your context name.
6. Now inside the above xml file put the following line:
<context docbase="d:/images"></context>
7. Now restart Tomcat server.

Now, when you load the Tomcat Manager you will find a new entry for the context "yourContext/images". Now this will point to the "images" directory in D drive as in the above example.

All the request made to "/yourContext/images" will be mapped to your directory "d:\images".

Now, you have an external directory mapped into your context which can be used to upload files or images.

Friday, August 7, 2009

Map an external directory into Glassfish

In this article I'll try to explain how to map an external directory into the Glassfish application server. Until you have experienced the need for mapping an external directory into Glassfish, the first thing that will come to your mind what is the need to do so.

The reason to map an external directory into the server may be different for different kind of applications. One of the situations may be when an application has to upload lots of files on the server which may be images, text documents, PDFs, Word Documents or other format of files. The files uploaded on a daily basis will eat up disk space and make the context of the application grow in size may be on a daily basis or even hourly basis. A best example of such an application may be an application which allows users to upload images. An inventory management system may also allow the user to upload images of the inventory items. And in cases where all the inventory items has at least one image attached to it the size of the folder storing the images may easily go beyond 2GB. Imagine a growing inventory of more than 24,000 items with an option to add two images for an item. If the server is running on Windows with FAT32 file system then there will be another problem when the folder size grows to 2GB. FAT32 does not supports folder size of more than 2GB. So, while uploading files on the server you should be careful and have to manage the files by segregating them into different folders, which may be by date and time.

Now getting back to the main topic of creating virtual directories. This can be easily done using the Glassfish application server. GlassFish v2 Build 40 adds support for alternate docroots to web applications. Previously, support for alternate docroots was limited to virtual servers.

Alternate docroots allow web applications to serve requests for certain resources from outside their own docroot, based on whether those requests match one (or more) of the URI patterns of the web application's alternate docroots.

This means that web applications no longer need to bundle all their resources. Instead, part of their resources may be outsourced into server directories outside the web application's docroot, so-called alternate docroots, where they may be shared with other web applications.
If a request matches an alternate docroot's URI pattern, it will be mapped to the alternate docroot by appending the request URI (minus the web application's context root!) to the alternate docroot's physical location (directory).

The URI patterns of alternate docroots of web applications support exact, path prefix, and extension matches, just like their counterparts for virtual servers. If a request matches multiple URI patterns, the alternate docroot is determined according to the following precedence order:
  • Exact match
  • Longest path match
  • Extension match
Alternate docroots of web applications are configured as sun-web.xml properties, using the same syntax as alternate docroots for virtual servers.

Example: The following sun-web.xml specifies 3 alternate docroots:

<sun-web-app>
     <property name="alternatedocroot_1" value="from=/my.jpg dir=/srv/images/jpg"/>
     <property name="alternatedocroot_2" value="from=*.jpg dir=/srv/images/jpg"/>
     <property name="alternatedocroot_3" value="from=/jpg/* dir=/src/images"/>
</sun-web-app>


The value of each alternate docroot has two name-value components: The first component (with name from) specifies the alternate docroot's URI pattern as its value, and the second component (with name dir) specifies the alternate docroot's physical location (directory) as its value.

In this example, the URI pattern of the first alternate docroot uses an exact match, whereas the URI patterns of the 2nd and 3rd alternate docroots use extension and path prefix matches, respectively.

Assume the above sun-web.xml belongs to a web application deployed at http://{hostName}:{portNumber}/myapp.

The first alternate docroot will cause any requests with this URL:

http://{hostName}:{portNumber}/myapp/my.jpg
to be mapped to this resource:

/svr/images/jpg/my.jpg

while the 2nd alternate docroot will cause any requests with a *.jpg suffix, as in:

http://{hostName}:{portNumber}/myapp/*.jpg

to be served from this physical location:

/svr/images/jpg

whereas the 3rd alternate docroot will cause any requests whose URI starts with /myapp/jpg/, as in:

http://{hostName}:{portNumber}/myapp/jpg/*

to be served from the same directory as the 2nd alternate docroot.

For example, the 2nd alternate docroot maps this request:

http://{hostName}:{portNumber}/myapp/abc/def/my.jpg

to:

/srv/images/jpg/abc/def/my.jpg

and the 3rd alternate docroot maps:

http://{hostName}:{portNumber}/myapp/jpg/abc/resource

to:

/srv/images/jpg/abc/resource

If a request does not match any of the target web application's alternate docroots, or if the target web application does not specify any alternate docroots, the request will be served from the web application's standard docroot, as usual.

One point to note is that the physical path and the one in the 'sun-web.xml' should match. For example in
<property name="alternatedocroot_3" value="from=/jpg/* dir=/src/images"/>

The above will map to /src/images/jpg. So, you need to make sure that whatever is after "from=" matches to a path inside the "images" folder. In the above examples the path is from Unix/Linux systems. To use on a Windows machine use something like "d:/src/images".