Loose applications
Loose applications are applications that are composed from multiple physical locations, which are provided to the run time via an XML file. Loose applications are supported for Java EE and OSGi applications and are particularly beneficial in a development environment.
Normal application
Normally an application is contained under one directory (or in one archive), with its content, modules, resources, classdata, and metadata at known locations within that directory. For example: the location of resources for a web application is as follows:
- Library Java archive (JAR) files are stored in WEB-INF/lib
- Classes are either in library JAR files or in WEB-INF/classes
- The deployment descriptor is in WEB-INF/web.xml
- Content to be served is located from the root of the directory
Loose application
A loose application is described as a virtual directory that represents the application, where information might be in any location
. It enables development tools, such as WebSphere Application Server Developer Tools, to run applications where the associated files are loaded directly from the workspace, rather than being exported. Examples of associated files are Java classes, JavaServer Pages, or images. If we load the associated files directly from the workspace, it results in a faster build-run-debugging cycle. The content is not present under one directory, but can come from other locations. These locations are specified in an XML configuration file. There are two ways we can provide the XML file to the run time:
- By placing the XML file in the location attribute in an application configuration element with an appended .xml suffix
- By placing the XML file directly into the application dropins folder
For example, if we specify <application location="myapp.war" />, the run time looks for a file called myapp.war.xml. The search rules are the same as for an application directory or archive. If the application files and the .xml loose application configuration files are both found, then the loose application configuration file is ignored. For example, if we have myapp.war and myapp.war.xml, the Liberty server uses myapp.war to run the application. We can also deploy loose applications directly into the dropins folder. To use the dropins folder, follow the naming conventions defined for the folder and append .xml to the end of the file name.
Avoid trouble: When we run the server package command with a loose application my_app.war.xml file that uses server variable substitution, those parts of the loose application having variable substitution are not packaged. The server is not started at the time of packaging and has no way to access the needed variable information. Variable substitution does not take place when we use the server package command .
Loose application configuration file
The Liberty server uses the loose application configuration file to obtain the application content, rather than locating it from a root directory or single archive. Use the appropriate XML, we can take the following actions:
- Map any physical directory to any location within the application
- Map any physical file to any location within the application
- Map any physical JAR file or directory to any location as a nested archive
- Map multiple physical sources to a single target location (merging)
For example:
- Map the root of the archive to one location on disk, such as a folder in an Eclipse project.
- Map a Java bin/output folder that is not in the
usual
location into the WEB-INF/classes folder. This location might be in a different folder due to your workspace preferences, corporate guidelines, source control project layout guidelines, and so on. We might have multiple Java source and output locations in the same project, and want to map them both to WEB-INF/classes. - Map an
external
JAR file into the application. Thisexternal
JAR file might be one of the following:- A separate Java project we want to treat like a JAR file in WEB-INF/lib
- A utility JAR file somewhere else on your hard disk drive that you built the .war file against, and need to include in WEB-INF/lib at run time
Loose application configuration file examples
You can configure three different elements in the loose application configuration file:- <archive> for archives
- <file> for files
- <dir> for directories
- Archives
- The <archive> element is always used as the root of the loose application configuration file. It is also the root of the virtual file system that is represented in the XML. We can nest any of the three elements under the root <archive> element. The root <archive> element does not have any attributes.
- Archive elements can be nested recursively. For <archive> elements nested under the root <archive> element, we can set the targetInArchive attribute. The targetInArchive attribute defines the path where the archive appears within the loose defined enclosing archive. We cannot map an archive on the file system as an archive in the application with an <archive> element. To use loose application configuration to map an archive on disk,
use a <file> element instead.
Note that the targetInArchive attribute value is an absolute path with a leading forward slash (/).
- The following code is an example of the root <archive> element with another <archive> element nested under it:
<archive> <archive targetInArchive="/jarName.jar"> <!-- more objects can be embedded here--> </archive> </archive>
- targetInArchive defines the path where the archive appears within the loose defined enclosing archive.
- sourceOnDisk defines the actual location of the file on your file system.
Note that the sourceOnDisk attribute value is an absolute location. We can use Liberty variables such as ${example.dir}, which are resolved correctly.
<file targetInArchive="/apps/webApplication.war" sourceOnDisk="C:/devFolder/myApplication.zip" />
<archive targetInArchive="/apps/webApplication.war"> <file targetInArchive="/applications/myApplications/jarName.jar" sourceOnDisk="C:/devFolder/myApplication.zip" /> </archive>
<dir targetInArchive="/META-INF" sourceOnDisk="${example.dir}/applicationData/myApplication" />
<archive targetInArchive="/apps/jarName.jar"> <dir targetInArchive="/META-INF" sourceOnDisk="${example.dir}/applicationData/myApplication" /> </archive>
Virtual paths and file names
If we add <file> or <dir> elements to an archive, the name of the file or directory in the loose archive does not need to be the same as the actual name on disk. The following code is an example of how we can configure ${example.dir}/applicationFiles/newfile.txt to appear in the archive as /application.txt:
<archive> <file targetInArchive="/application.txt" sourceOnDisk="${example.dir}/applicationFiles/newfile.txt"/> </archive>
The same concept also holds true for the path of any added file or directory. The physical resource on disk does not need to be in a directory hierarchy that corresponds to the one being declared. The following code is an example of how we can make ${example.dir}/applicationFiles/newfile.txt appear in the archive as /only/available/in/application.txt:
<archive> <file targetInArchive="/only/available/in/application.txt" sourceOnDisk=""${example.dir}/applicationFiles/newfile.txt"/> </archive>
In each case, the Liberty server sees the resource by the name and path declared by the targetInArchive attribute. The Liberty server can navigate the directory hierarchy declared, even if the hierarchy contains only virtual elements, as in the previous example.
<archive> <file targetInArchive="/only/available/in/red.txt" sourceOnDisk="${example.dir}/applicationFiles/newfile.txt" /> <archive targetInArchive="/apps/jarName.jar"> <dir targetInArchive="/META-INF" sourceOnDisk="${example.dir}/applicationData/myApplication" /> </arhive> </archive>
Folders and files with the same name
If we have two folders with the same name in the same virtual location in the loose application configuration, the folders are merged, and the contents of both folders are available. If we have two files with the same target location in the loose archive, the first occurrence of the file is used. The first occurrence is based on a top-down approach to reading the elements of the loose application configuration file.
If the first file found is the wrong file, reorder the XML so that the element containing the version of the file we want is processed first. The first occurrence applies to files defined in <dir> elements and files defined in <file> elements. The first occurrence of a file with the same name and virtual location is the one returned from the virtual file system.
Considerations for loose applications
For all loose configured applications, the files are not on disk in the hierarchy that they are declared to be. If the applications directly access their own resources, and expect them to be arranged on disk as they would be with an expanded war or ear layout, they might exhibit unexpected behavior.
We can use ServletContext.getRealPath in the applications to discover physical resource paths. ServletContext.getRealPath can discover file paths to open to read or write data, and obtain directories.
However, if we use ServletContext.getRealPath in web applications to obtain a path for /
, we cannot use this path to navigate the application on disk.
ServletContext.getRealPath allows only a single physical path to be returned, and the loose application might have merged multiple directories to form one path visible to the application. Consider the following configuration:
<archive> <dir targetInArchive="/" sourceOnDisk="c:\myapplication" /> <dir targetInArchive="/web/pages" sourceOnDisk="c:\webpagesforapplication" /> </archive>
An application that directly accesses /web/pages and then navigates up the directory hierarchy, finds that the parent of the physical path of /web/pages is c:\ and not /web. c:\ has no pages directory and no parent directory.
These considerations apply only if the applications attempt to directly access the content on disk, and perform their own path navigation based on an assumption of a corresponding hierarchical layout on disk. The same applications also encounter issues if they are deployed as an archive. These applications generally experience issues with portability.
Complex example
The following code is a more complex example of loose application configuration. This example uses all of the elements and creates a complex mapping of files and directories:<archive> <dir targetInArchive="/appResources" sourceOnDisk="${example.dir}/applicationFiles" /> <archive targetInArchive="application.jar"> <dir targetInArchive="/src" sourceOnDisk="${example.dir}/applicationCode/src" /> </archive> <archive targetInArchive="webApp.war"> <dir targetInArchive="/META-INF" sourceOnDisk="${example.dir}/manifestFiles/" /> <dir targetInArchive="/WEB-INF" sourceOnDisk="c:/myWorkspace/webAppProject/web-inf" /> <archive targetInArchive="/WEB-INF/lib/myUtility.jar"> <dir targetInArchive="/" sourceOnDisk="c:/myWorkspace/myUtilityProject/src" /> <file targetInArchive="/someJar.jar" sourceOnDisk="c:/myWorkspace/myUtilityProject/aJar.jar" /> </archive> </archive> <file targetInArchive="/myjar.jar" sourceOnDisk="${example.dir}/apps/application.zip" /> </archive>
Parent topic: Deploy applications in Liberty