We've written a few articles on applets before, but compiling our viewer as an applet, or adding your
own class to our viewer, is still causing some of our customers grief. None of this
is helped by the untimely death of the pack200 Ant extension we've previously advocated. So, to cover these bases completely, here's
a step-by-step guide to compiling your own Applet based on our code. Some caveats:
- The commands are UNIX centric, although hopefully our descriptions of what to do will
get you through on other operating systems
- It's command-line centric. Again, if you prefer to work with an IDE then the descriptions
should steer you through.
- We're assuming you're using ant to build, you have
src
folder for source, a lib
folder for Jars and your viewer will live in the mypackage.pdfviewer
package. Every code sample below assumes you're in the parent directory containing
src
and lib
.
- The end result is going to be a single signed Jar containing our main PDF Library
and your own, independent version of our Swing Viewer which you can edit to your hearts
content
Let's get started.
First steps
-
Download the Apache Compress Ant Library task and install
ant-compress-1.2.jar
and commons-compress-1.2.jar
in the lib
folder of your Ant installation. Despite Pack200 being a standard part of Java since
1.5 it's never been properly integrated with Apache Ant, and there have been a number of different solutions, workarounds and bodges to get it working. The "Apache Compress" Library referenced above still
isn't part of Ant's core, but it is sanctified by the Apache Group and after waiting
eight years I guess that's as good as it gets.
- Download our PDF Library and unpack the file. Take the
bfopdf.jar
as well as the other supplementary Jars, and put it in your lib
folder.
cp bfopdf-2.11.24/bfopdf*.jar lib
- Download our build.xml, which is a revised version of that found in a previous article.
wget http://bfo.com/blog/files/build-v2.xml
Adding your own features to our applet
The easiest way to work with our applet is to add your own custom features to it.
If your new feature is in the mypackage.pdfviewer
package and you just want to link it with our applet, all you need to do is create
a src/META-INF/services/org.faceless.pdf2.viewer2.ViewerFeature
file that lists the class name(s) of your features. Then skip to building and signing below.
Building a completely independent applet
If you want to edit our codebase, rather than just linking in to it, then you're going
to need to rename the classes to your own package - doing so will make your life easier,
because your classes won't clash with ours, and it will certainly make our lives easier
when you email us a stacktrace for debugging. We supply the source code for our viewer
with the download package, so here's the steps you need to take to migrate that to your own codebase.
- Our download package also contains the source code for the
viewer2
package, which is our Swing viewer that you'll be cloning. Copy the source into the
src/mypackage/pdfviewer
folder of your dev environment:
mkdir src/mypackage
cp -r bfopdf-2.11.24/src/viewer2 src/mypackage/pdfviewer
- Our Jar includes a list of features in the
META-INF/services/org.faceless.pdf2.viewer2.ViewerFeature
file, which is disovered via service discovery. Your viewer is going to be in a different package, so this file needs to be extracted
from our Jar and renamed:
cd src
jar xf ../lib/bfopdf.jar META-INF/services
mv META-INF/services/org.faceless.pdf2.viewer2.ViewerFeature META-INF/services/mypackage.pdfviewer.ViewerFeature
- If you're working with a version of our package prior to 2.11.25, we didn't include
the non-Java resources for the viewer in the "src" folder, so you'll need to extract
these from
org/faceless/pdf2/viewer2/resources
to mypackage/pdfviewer/resources
. If you're on 2.11.25 these files were moved as part of step 3 above, so you can
skip:
cd src
jar xf ../lib/bfopdf.jar org/faceless/pdf2/viewer2/resources
mv org/faceless/pdf2/viewer2/resources mypackage/pdfviewer
rm -rf org
- The source for all our classes is in our
org.faceless.pdf2.viewer2
package, but you want to move these to your own mypackage.pdfviewer
package. This means updating the "package" and "import" directives in each source
file - IDE folk can probably find a menu option to do this, for the rest of us it's
time to break out the regular expressions:
cd src
sed -i '' 's/org\.faceless\.pdf2\.viewer2/mypackage.pdfviewer/g' mypackage/pdfviewer/*.java mypackage/pdfviewer/*/*.java META-INF/services/*
If you're doing this by hand, don't forget the file in META-INF/services/
.
- You will need to edit the
build.xml
file to change the servicefile
property. This is the service file containing the list of features which you renamed
in step 4 from org.faceless.pdf2.viewer2.ViewerFeature
to mypackage.pdfviewer.ViewerFeature
- update the property accordingly. You'll also want to exclude our original viewer
package from the build, as you're using your own. Add the highlighted line below to
the <jar>
operation of the build
target:
<jar destfile="${jar}">
<zipfileset src="${bfopdfjar}">
<exclude name="${servicedir}/${servicefile}" />
<exclude name="META-INF/*.RSA" />
<exclude name="META-INF/*.SF" />
<exclude name="org/faceless/pdf2/viewer2/**" />
</zipfileset>
<fileset dir="build" />
</jar>
Building and Signing
-
Your
build.xml
should now be able to run ant build
, to compile the code and assemble the classes into the Jar, and now is a good idea
to double check this.
ant build
-
In order to do anything useful with an Applet, it must be signed. We've covered some of this before, but our suggested route these days is to roll everything that's core to your
applet - our code, your code, the license - into one Jar, with the additional Jars
we supply (for Chinese/Japanese/Korean text, adding new annotations and so on) referenced
from JNLP if you need them. In recent versions of the Applet Classloader these Jars
must be signed with the same key to avoid warnings or errors. So you need a Keystore.
Maybe you have one already, but if not here's a quick way to generate one for testing:
keytool -genkey -alias myalias -keystore keystore.jks \
-storepass password -keypass password \
-dname "cn=me"
- You may need to edit the
build.xml
file to tell it where to find your signing key. Change the ks.path
, ks.alias
and ks.password
properties to the location of your KeyStore file and the alias/password for signing.
In the example above these would be keystore.jks
, myalias
and password
respectively.
- You're now able to sign the Jar with
ant sign
. This will sign the original Jar, the supplementary Jars, and create a pack200 version
of the signed Jar.
ant sign
-
Lastly, create the JNLP file from the
bfopdf-applet.jnlp
included with our download package. You should only need to update the name of the
Jar file, and the package name in the package
clauses if you've changed that. Add the applet tag to your webpage, making sure to
reference the JNLP. An example is below - we assume the Jar files and JNLP file are
all in the applet
subdirectory.
<applet code="org.faceless.pdf2.viewer2.PDFViewerApplet" name="pdfapplet" codebase="applet" archive="bfopdf.jar" width="900" height="500">
<param name="jnlp_href" value="bfopdf-applet.jnlp"/>
<param name="draggable" value="true"/>
<param name="swing.defaultlaf" value="javax.swing.plaf.nimbus.NimbusLookAndFeel">
</applet>
Note that at the time of writing, the separate_jvm
parameter for applets results in a gray square instead of the applet on OS X. This
is a fault with the Java Plugin in Apple's JVMs since sometime in 1.6, so it will
affect all browsers using that plugin. The Oracle Java Plugin is due to replace Apple's
but hasn't appeared yet - we will update this section when it does.