Web App Libraries and Eclipse Build Path
Table of Contents
In this article, we examine what the Eclipse "Web App Library" is used for, how to set one up and how to consume it from other projects besides the one in which it's set up.
Our example will be the Web App Library set-up in an Eclipse Web Tools Platform (WTP) Dynamic Web Project that we want to use for implementing an application in JavaServer Faces (JSF).
What is an Eclipse Web App Library?
As noted in JARs and Eclipse Build Path, the Web App Library is one of the optional groupings of library organization in the Eclipse project and is particularly germane and useful to the Dynamic Web Project (as opposed to a plain Java Project).
Don't take what I say here at face value or as gospel. If you're writing a JSF-based application, you don't necessarily need to set up your libraries under WebContent/WEB-INF/lib. I have found that just making MyFaces, JSTL, log4j and others mere User Libraries is sufficient (and neater too) as long as I'm only developing one server/servlet/application.
If you're writing some kind of server and have one or more servlets, and you're including a fair amount of unusual dynamicity in what you're doing, you might need to do this. The servlet API specification says that it looks first in WEB-INF/classes, then in WEB-INF/lib for classes to load.
Also, if you're writing a multi-project application, it will be convenient to have all the dependent libraries in one place and that place distributable across projects (project B can just use the Web App Library of project A. Etc.) That way, someone on your project team sets up a Web App Library for one project and all the other projects consume it. Even non-Dynamic Web App projects can consume the JAR libraries tucked away in a Dynamic Web Application project's Web App Library.
A project's Web App Library is composed automatically by Eclipse from any JARs on the project path, <project-name>/WebContent/WEB-INF/lib. JARs reach that location a) after the project is created (of course, since the project filesystem begins to exist only then) and b) by the user's hand.
Typically, this path is in the Eclipse workspace, but not necessarily. In the case where the project, source code and specified libraries are kept in a source-code control system such as Subversion, all of this would likely not reside in the workspace.
Composing the set of libraries (or JARs) in this location is done carefully and based on a complete understanding of what the project needs. All the JARs that are included at that location will be deployed as part of the application. This means that you don't want to put JARs that contribute nothing as that wastes space. However, you must put the JARs that contribute the symbols (classes, descriptors, etc.) necessary to the application.
You probably got the point here. It may be overkill to give you an example, if so, read on. If you'd like the example, look to the appendix.
Here it is, step by step.
Build Path -> Libraries, you can link source code or Java doc to your Web App Libraries. See JARs and Eclipse Build Path. This is so that in the Eclipse editor when you hover over a construct or identifier in your source code, or press
Ctrl-SPACEwhile editing, you get Javadoc or intelligent suggestions. If you do this, however, you had better be certain that this Javadoc or source code is delivered somehow a) as part of some project and/or b) on a ubiquitous path. This is because if the project, including the contents of the Web App Library, is checked out of Subversion, it must be on the path indicated by the mechanism above.
If you have more than one project, you can consume one project's Web App Library from another.
Let's imagine you've created a server application and corraled all the needed JARs in it. It may depend upon several "subprojects"1. The subprojects themselves may need to consume one or more JARs that happen to be in the Dynamic Web Project's WEB-INF/lib subdirectory.
The best way to share a project with other development team members (and keep it safe) is to use a repository like Subversion. Commit the entire project including the "hidden" files and subdirectories such as .classpath, .project and .settings. See Using Tortoise SVN and Subclipse for Window and Linux Development in Eclipse.
The .settings subdirectory contains files with preferences you've set.
For example, if you decide that you want the compiler to remain silent about
"dead code" in your project, you've set
Window -> Preferences ->
Java -> Compiler -> Errors/Warnings -> Potential programming problems
-> Dead code (e.g. 'if (false)''): to Ignore. Many other
project-specific settings such as which level of Java compliance to adhere to
and project facets are stored here. If you store this in Subversion, then those
who check this project out will have those settings too.
The .project file contains information about project building and nature—used by Eclipse. These can be influenced by what you have active in your project. Different things happen if you have JSP files. The existence and use of Eclipse web, Android, or other plug-ins is significant (and recorded).
The .classpath file contains a number of pieces of information including flies on which your project depends.
1 There is no such thing as a "subproject" in Eclipse, but you can create simply library projects—plain old Java projects— whose JAR'd output you consume from your main project.
For our JSF example, the following libraries were found to be crucial:
You must seek these JARs out, download them and copy them directly onto your project's WebContent/WEB-INF/lib path. If you are new to Eclipse or to JEE web application development and aren't comfortable you understand WebContent, please see Developing Your Java Project with Eclipse.
Each of these libraries is important. For example, the presence of log4j-1.2.15.jar and a correctly built log4j.properties on a path it can find prevents certain warnings from being issued to the Eclipse console and also ensures that, if you set the level to DEBUG, messages are printed instead that will help you figure out what's wrong with other components.
The lack of other JARs from this list will result in various errors reaching the console along with an ultimate (browser) result of 404, 500, etc.
To give a perverse example, imagine seeing
. . . INFO: Starting Servlet Engine: Apache Tomcat/6.0.26 Apr 26, 2010 11:00:17 AM org.apache.catalina.core.StandardContext listenerStart SEVERE: Error configuring application listener of class org.apache.myfaces.webapp.StartupServletContextListener java.lang.ClassNotFoundException: org.apache.myfaces.webapp.StartupServletContextListener at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1361) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3915) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4467) . . .
...and you're getting an HTTP status of 404 in the browser. Yet, you have myfaces-impl-1.2.8.jar, which contains this class, in your project.
Or, you get...
. . . Apr 26, 2010 9:58:50 AM org.apache.myfaces.webapp.MyFacesServlet init INFO: MyFacesServlet for context 'C:\Users\russ\dev\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\dvdcatalog-3\' initialized. Apr 26, 2010 9:58:50 AM org.apache.catalina.core.StandardContext resourcesStart SEVERE: Error starting static Resources java.lang.IllegalArgumentException: Document base C:\Users\russ\dev\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\dvdcatalog-2 does not exist or is not a readable directory at org.apache.naming.resources.FileDirContext.setDocBase(FileDirContext.java:142) at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4086) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4255) . . . INFO: Container org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dvdcatalog-2] has not been started Apr 26, 2010 9:58:50 AM org.apache.catalina.core.StandardContext resourcesStart SEVERE: Error starting static Resources java.lang.IllegalArgumentException: Document base C:\Users\russ\dev\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\de.vogella.jsf.starter does not exist or is not a readable directory at org.apache.naming.resources.FileDirContext.setDocBase(FileDirContext.java:142) at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4086) . . .
You could spend a week pulling your hair out over this. How were these problems solved? At first, digging class names out of JARs:
[email protected]:~/dev/downloads/myfaces-core-1.2.8-bin/lib> jar tf myfaces-impl-1.2.8.jar | grep StartupServletContext org/apache/myfaces/webapp/StartupServletContextListener.class
...only to find they are indeed there. Next, I Googled the web for these and other error messages, reading every article, every forum response and chasing wild geese that led me nowhere. After much reading, however, a picture begins to emerge:
Ultimately, if you're lucky or you've put in the effort, you get a running application with no errors: