From Fedora Project Wiki

< PackagingDrafts

Revision as of 14:13, 24 May 2008 by fp-wiki>ImportUser (Imported from MoinMoin)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Packaging Java Web Applications

Please also read the ["PackagingDrafts/Java"] guidelines.

We really need a separate section for web application policies within Fedora (for all web applications, not just Java related ones)

Web applications can be written in Java to be deployed on a Java web server (for example Tomcat and Jetty). These applications are bundled into what is referred to as a WAR file. Like a JAR file, a WAR file is similar to a zip archive and contains all data needed to run the application, this includes things like images, html pages, servlets, JAR files and configuration files.

The problem with WARs is that they contain JAR files which may already exist on the system. This means that JAR files would have to be maintained in multiple locations on the machine.

Fortunately, most servers can use WAR files in an 'exploded' format. This means that the WAR file is expanded into a directory structure instead of being an archive and we can symbolically link the JAR files as needed.

e.g. package foo which provides foo.war, the package would have:

%{_datadir}/%{name}/foo.war/WEB-INF/lib/bar1.jar -> %{_javadir}/bar1.jar
%{_datadir}/%{name}/foo.war/WEB-INF/lib/bar2.jar -> %{_javadir}/bar2.jar
  • What should the web app be called: foo.war ,foo.war-exploded or just foo? What if foo provides more than just a web app?  %{_datadir}/%{name}/foo/webapp or is specific to a particular server %{_datadir}/%{name}/foo/webapp-tomcat5?

1. In the above example, both, the package and war name are foo. However, that is not a necessity. The war can have any name. Thus multiple webapps within a package is a non issue. With regards to webapp dir name, what about <name>.war-exploded? It will prevent confusion as to whether or not it is a file 2. regarding applications for specific servers, foo can still go in %{_datadir}/%{name}/... , with a foo-$server package that sets up the deployement for that server in which it works 3. Application can use %{_datadir}/%{name} for its own purposes, therefore it might be a better idea to use something like %{_datadir}/webapps/%{name}/webapp-name (-- LubomirKundrak) 4. I have a strong objections against calling the directory with webapp webapp.war or webapp.war-exploded. For -exploded} is unnecessary, as it's obvious from being a directory and .war stands for web application archive, and being exploded this is no longer an archive (at least not in traditional meaning (-- LubomirKundrak) 5. If a web application is specific to a web server, why install it in %{datadir} and not in directory specific for that server? One objection might be a way to un-deploy the application by deleting a symlink would not be possible, but equivalent way is to just uninstall the subpackage (-- LubomirKundrak) 6. I propose that we use the path /var/java/www/%{name}.war for all server deployments. I don't see a problem running the application as exploded due to the nature of need to modify files like hibernate configurations and web.xml. Many sysadmins use something like puppet or cfengine to override these files based on the environment they are going to be running in (ie dev, qa, stage, prod). if you run this as a package, you will need to start the server, see it fail, shutdown, edit configs, restart the server. (-- LeeFaus) 1. I am wondering where did the /var/java/www path originate from? /var is for variable data as defined by FHS, we should really stick with /usr/share, as is currently mandated for other web applications. (-- LubomirKundrak) 7. I somewhat agree with the duplicate jars as mentioned above, the downside is you remove the advantages of the classloader in this situation. If the %{_javadir} is loaded as a classpath and I need a newer version of a framework, I can't override it. This is one of the things I disagree with in the JavaPackaging standards as well. Java allows the developer to load frameworkA.1.0.1.jar and frameworkA.1.1.jar. As long as frameworkA.1.1.jar is loaded first in the class loader, I will get it's functionality over frameworkA.1.0.1.jar. This is critical for many Java Web Applications and developers exploit this functionality routinely. There needs to be some rule about where it is ok to override this functionality and when it is not. (--LeeFaus) 8. I am attaching a graphic of a sample of how I see symlinking to other directories on the filesystem to help make some of my suggestions clear (--LeeFaus)

Sample Directory Listing

File:PackagingDrafts JavaWebApps sample.dir.layout.png

Web applications should be installed at %{_datadir}/%{name} instead of into the webapps directory of the application server. The application can then be deployed by creating a symlink from the exploded web application to the deployment directory of a specific server. Installation directly into the webapp folder of a specific server would cause automatic deployment, and is not desirable for the following reasons:

  • In many situations the web application should be able to be deployed by various web servers (for example Tomcat or Jetty). By not installing the application in the webapps folder of a specific server allows the application to be shared among different servers.
  • Configuration changes can be done before deployment and the application can be undeployed without losing changes (undeployment is usually done by removing the application from the webapp directory, or in this case removing the symlink).
  • There may be security reasons for not autodeploying the application (for example, needing to change the default password). This type of application should never be automatically deployed.

If the packager wants to give the web application the option of automatic deployment through an RPM, they can optionally provide container-specific subpackages which depend on the container and link to the exploded application directory. e.g. foo-tomcat5, which would provide a symlink:

 %{_datadir}/tomcat5/webapps/foo -> %{_datadir}/%{name}/foo.war

For web applications to be included in Fedora, they must be deployable on at least one of the Java servers provided in Fedora (as of Fedora 8, Jetty or Tomcat).

WAR files contain many different XML configuration files (for example web.xml and context.xml). These must be marked as %config(noreplace) to prevent changes from being overwritten.

What about configuration files? If we want to support deployment of package foo across multiple servers, perhaps we should also make it so that config files for each container reside in a container specific dir?

1. I wonder if it's worth the overhead, given how likely configuration it is. Do any PHP web applications already deal with this? (-- LubomirKundrak)

Are any of the items below even valid any more? I don't know what this talk of avoiding %{_datadir}/%{name}, providing only for tomcat5, etc. is all about. The guidelines above make the following clear:

    • Provide the exploded war in %{_datadir}/%{name}/
    • For all servers that you wish to provide a deployement for, create a /path/to/serverwebapps/%{name} -> %{_datadir}/%{name}/....war-exploded

Now, if there is a reason to not place items in %{_datadir}/%{name} at all, that is an issue... is anyone opposed to the placement there?

  • From the section that was here before:
  • If you for some reason need to create a WAR package, place it in %{_datadir}/%{name}. Try to avoid those.
  • Why should these be avoided?
  • Because they are analogous to static linking. Many web application depends on jars from foreign packages and given jars (zips) can not contain symbolic links, you would have to copy those, and loose benefits of the packaging system. Therefore I propose to forbid packaging wars and eventuelly provide a tool to construct a war from webapp directory with jpackage-utils. (-- LubomirKundrak)
  • Assume that tomcat5 is the only container, analogically to what is done with non-java web applications and Apache httpd.
  • Since Jetty is also within the Fedora distribution, why should tomcat5 be the only container assumed? Is there an official web application policy for Fedora?
  • This was proposed by me, and I no longer share that opinion since much smarter alternative was proposed. Feel free to delete it (-- LubomirKundrak)

TODO: change this example if the above changes to the policy are acceptable



BuildRequires:  jpackage-utils


%package tomcat5
Summary:        %{name} web application for Tomcat 5
Group:          Applications/Internet
Requires:       %{name} tomcat5

%description tomcat5
%{name} web application


%define webapp %{_localstatedir}/lib/tomcat5/webapps/%{name}
unzip -q %{name}.war -d $RPM_BUILD_ROOT%{webapp}
(IFS=:; for file in
%{_javadir}/%{name}.jar                         \
ln -sf $file $RPM_BUILD_ROOT%{webapp}/WEB-INF/lib
build-jar-repository $RPM_BUILD_ROOT%{webapp}/WEB-INF/lib <jar1> <jar2>


%files tomcat5
%config(noreplace) %{webapp}/WEB-INF/web.xml
%dir %{webapp}
%dir %{webapp}/WEB-INF
  • %files section looking like this would produce rpmlint warning about duplicate listing of %config files.
  • %files duplicates fixed.
  • I wonder if this is going to fly for all webapps, there might be some for which enumerating the files might produce too long lists (-- LubomirKundrak)
  • Paths output by build-classpath are absolute and symlinks that would be created this way are absolute.
  • Absolute symlinks should be fixed by changing build-classpath to output relative symlinks. In the meantime, either waive the rpmlint warning or use abs2rel like in java-1.6.0-openjdk.
  • Fedora 9's build-jar-repository will probably not be able to create symlinks. Would it be okay if we either choose the abs2rel way or tolerated absolute links until Fedora 10, and add the feature until then. (-- LubomirKundrak)

There are other java web archives such as EARs, SARs, HARs, CARs, ... which deal with Java Enterprise Edition (JEE) Application Servers. These will need to be treated in the same manner as WARs. A section will be available here once a JEE server is available in Fedora.