Sharable Libraries Feature in NetBeans 6.1 Beta

I’ve been excited waiting for the new Sharable Libraries feature to be delivered in NetBeans 6.1 Beta. The concept is similar to the current Libraries features in NetBeans, but as I understand it has a few additional benefits. One of the big ones (at least from my perspective) includes better portability of NetBeans projects to continuous integration servers (Hudson being my favorite CI server of choice).

Now that NetBeans 6.1 Beta has been released I wanted to explore this feature a little and document some of what I found.

Steps I took to try it out….

I created two sample Java Web Applications called MyWebApplication5 and MyWebApplication6. The projects were created in my D:projectstest directory.

On the Sharability screen in the project creation wizard, as shown in Figure 1, I make sure the field ‘Project shared with other users’ is checked. The ‘Sharable libraries location’ field is initially set to the relative path of “..libraries”. The concept of relative paths here makes a big difference, especially if your development team works on and deploys to multiple platforms. You definitely do not want to use any sort of hard-coded or absolute path (there may be certain cases where the opposite is true).

I also left the ‘Copy jars to sharable location’ radio button selected. This will cause all of the web server’s JAR files into a sharable library. This can be useful if you want to make sure every developer is working on the same set of Tomcat server libraries if you deploy to a specific version of Tomcat. If you select the first radio, the project will use the JAR files for the server registered locally in your IDE. If you have multiple developers with different versions of NetBeans, there may be different server versions present. A mild warning to beware of.

Figure 1
Figure 1

Once the projects were created I looked at the D:projectstest directory and saw my two project directory names, ‘MyWebApplication5′ and ‘MyWebApplication6′, as well as a ‘libraries’ folder. This is the relative location that the NetBeans new project wizard generated.

The libraries folder contains a folder for the server libraries (if you chose to copy them here), as well as the 2 supported JUnit versions (JUnit 3.X and 4.X). The directory ‘junit’ contains the JUnit 3.X libraries and the directory ‘junit_4′ contains the JUnit 4.X libraries.

The top-level libraries folder also contains a file named ‘nblibraries.properties’, the contents of which are shown below :

libs.junit.classpath=
${base}/junit/junit-3.8.2.jar
libs.junit.javadoc=
${base}/junit/junit-3.8.2-api.zip
libs.junit_4.classpath=
${base}/junit_4/junit-4.1.jar
libs.Tomcat_6.0.type=j2eeshared
libs.Tomcat_6.0.javadoc=
${base}/Tomcat_6.0/javaee5-doc-api.zip
libs.Tomcat_6.0.classpath=
${base}/Tomcat_6.0/annotations-api.jar;
${base}/Tomcat_6.0/catalina-ant.jar;
${base}/Tomcat_6.0/catalina-ha.jar;
${base}/Tomcat_6.0/catalina-tribes.jar;
${base}/Tomcat_6.0/catalina.jar;
${base}/Tomcat_6.0/el-api.jar;
${base}/Tomcat_6.0/jasper-el.jar;
${base}/Tomcat_6.0/jasper.jar;
${base}/Tomcat_6.0/jsp-api.jar;
${base}/Tomcat_6.0/servlet-api.jar;
${base}/Tomcat_6.0/tomcat-coyote.jar;
${base}/Tomcat_6.0/tomcat-dbcp.jar;
${base}/Tomcat_6.0/tomcat-i18n-es.jar;
${base}/Tomcat_6.0/tomcat-i18n-fr.jar;
${base}/Tomcat_6.0/tomcat-i18n-ja.jar;
${base}/Tomcat_6.0/tomcat-juli.jar

This file lets your Ant build scripts access the shared libraries using simple properties. Note that the directory paths contain a reference to a ${base} property.

If you open the nbproject/buildimpl.xml file for one of the web applications, you can look at the -init-libraries target.

<target depends=”-pre-init,-init-private” name=”-init-libraries”>
<property location=”..librariesnblibraries.properties” name=”libraries.1.path”/>
<dirname file=”${libraries.1.path}” property=”libraries.1.dir.nativedirsep”/>
<pathconvert dirsep=”/” property=”libraries.1.dir”>
<path path=”${libraries.1.dir.nativedirsep}”/>
</pathconvert>
<basename file=”${libraries.1.path}” property=”libraries.1.basename” suffix=”.properties”/>
<touch file=”${libraries.1.dir}/${libraries.1.basename}-private.properties”/>
<loadproperties srcfile=”${libraries.1.dir}/${libraries.1.basename}-private.properties”>
<filterchain>
<replacestring from=”$${base}” to=”${libraries.1.dir}”/>
</filterchain>
</loadproperties>
<loadproperties srcfile=”${libraries.1.path}”>
<filterchain>
<replacestring from=”$${base}” to=”${libraries.1.dir}”/>
</filterchain>
</loadproperties>
</target>

The line :

<property location=”..librariesnblibraries.properties” name=”libraries.1.path”/>
The property libraries.1.path references the ‘nblibraries.properties file that contains the directory/JAR references in the sharable library. After the paths are converted, the target reaches the <loadproperties>directive that loads the actual property names and values from the nblibraries.properties file. The JARs from the sharable library are then able to be referenced by your build script.

You can then go about the business of adding JARs and libraries to your web application. In the Projects window, if you right-click the Libraries node in the Java Web Application, MyWebApplication5, and select Add Library, the Add Library window will appear, as shown in Figure 2.

Figure 2
Figure 2

In Figure 2, you can see the junit, junit_4, and tomcat_6.0 libraries that exist after the project creation. Let’s say I wanted to create a small library of XML JAR files. Click the Create button and the Create New Library window appears. Type the name of the library, such as XML-Libraries, and make sure Class Libraries is selected in the Library Type field. Click the OK button. The Customize Library window appears. Here, you can click the Add JAR/Folder button to select the JAR files that will belong in the library.

The Browse JAR/Folder dialog should appear allowing you to navigate your file system and choose JAR files. In Figure 3, notice the right side of the dialog window. In contains 3 fields related to sharable libraries.; ‘Use relative path’, ‘Copy to shared libraries location’, and ‘Use absolute path’. Since we’re using a shared libraries directory, select the second radio button for ‘Copy to shared libraries location, and click teh Add JAR/Folder button. The Customize Library window should display the list of selected JAR files in the Classpath tab. Clck the OK button.

Figure 3
Figure 3

The new library, XML-Libraries, should now appear in the Add Library window, as shown in Figure 4. Now click the Add Library button to associate the newly created library with your web application.

Figure 4
Figure 4

The new library will appear listed under your Libraries node in the Projects window.

Notice the contents of the d:projectstest directory have changed. The directory now contains the 2 XML-related JARs that I added to the XML-Libraries library.

NOTE : One thing to note, however, is that they are not placed inside a directory called XML-Libraries, like the other libraries in that folder, such as junit, junit_4, and tomcat_6.0. I wonder if that is intentional or unintentional. Anyone from the NetBeans team care to comment?

Also notice the contents of nblibraries.properties has changed. The following is added to the bottom.

libs.XML-Libraries.classpath=
${base}/xalan.jar;
${base}/xerces.jar

Notice that JAR files are only referenced in the base directory and not in a separate sub-directory as mentioned above.

When you added the new library to the Java Web Application project it also sets that library and its files to be packaged with the distribution of the application. You can deselect this by right-clicking the project name in the Projects window and selecting Properties. When the Project Properties window opens, click to the Libraries tab and uncheck the checkbox in the Package column for the library. This will allow you to have the library used at compile time, but not packaged or deployed with the application.

The XML-Libraries library that was created is now also referenced in the project’s nbproject/project.properties file as :

libs.XML-Libraries.classpath.libfile.1=../libraries/xalan.jar
libs.XML-Libraries.classpath.libfile.2=../libraries/xerces.jar

These properties in then referenced by the build-impl.xml file in the library-inclusion-in-manifest and dist.ear.dir targets :

<target depends=”init” name=”library-inclusion-in-archive” unless=”dist.ear.dir”>
<copy file=”${libs.XML-Libraries.classpath.libfile.2}” todir=”${build.web.dir}/WEB-INF/lib”/>
<copy file=”${libs.XML-Libraries.classpath.libfile.1}” todir=”${build.web.dir}/WEB-INF/lib”/>
</target>

and :

<target depends=”init” if=”dist.ear.dir” name=”library-inclusion-in-manifest”>
<basename file=”${libs.XML-Libraries.classpath.libfile.2}” property=”included.lib.libs.XML-Libraries.classpath.2″/>
<basename file=”${libs.XML-Libraries.classpath.libfile.1}” property=”included.lib.libs.XML-Libraries.classpath.1″/>
<copy-ear-war file=”${libs.XML-Libraries.classpath.libfile.2}” propname=”included.lib.libs.XML-Libraries.classpath.2.X”/>
<copy-ear-war file=”${libs.XML-Libraries.classpath.libfile.1}” propname=”included.lib.libs.XML-Libraries.classpath.1.X”/>
<mkdir dir=”${build.web.dir}/META-INF”/>
<manifest file=”${build.web.dir}/META-INF/MANIFEST.MF” mode=”update”>
<attribute name=”Class-Path” value=”${included.lib.libs.XML-Libraries.classpath.1.X} ${included.lib.libs.XML-Libraries.classpath.2.X} “/>
</manifest>
<delete dir=”${dist.ear.dir}/temp”/>
</target>

Long story short, this makes the JAR files more portable, especially if you’re running a continuous integration server. In Hudson’s project configuration, I used to have to specify a set of name/value settings that were then passed to the build file when it ran. These name/value settings were hard-coded paths to things like JUnit libraries that existed on my build server. NetBeans previously referenced these using a relative location that didn’t exist relative to the project build directories in Hudson, nor would it have been convenient to place the JAR files there either. So I had to override the specific location properties of all the libraries and provide hard-coded absolute paths. This new sharable library feature helps correct the problem. I can have all the shared libraries in one location that I specify and that is referenced correctly in the actual project’s build.xml file, NOT buried in a configuration screen in Hudson.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>