站内搜索: 请输入搜索关键词
当前页面: 图书首页 > Eclipse Rich Client Platform: Designing, Coding, and Packaging Java Applications

Section 10.1.  Integrating a Third-Party Library - Eclipse Rich Client Platform: Designing, Coding, and Packaging Java Applications

Previous Page
Next Page

10.1. Integrating a Third-Party Library

Alas, not all Java code is structured as Eclipse plug-ins. There is a vast array of useful Java code available in standard Java JAR files. Whether it is third-party libraries or in-house legacy function, reusing this code is extremely attractive and efficient. Fortunately, integrating these libraries into Eclipse is reasonably straightforward. The process of taking non-Eclipse code libraries and transforming them into Eclipse plug-ins is referred to as bundling.

10.1.1. Bundling Smack

Writing your own XMPP messaging library is quite a challenge. Fortunately, the folks at Jive Software (http://jivesoftware.org) wrote and open-sourced their Smack messaging library. We use this throughout the Hyperbola examples and have found it to be stable and easy to use.

The fine print

When you decide to reuse someone else's code, the first thing to ask yourself is: "Does the license allow you to repackage it, and what are the exact terms of the license?" This is true regardless of whether or not you are working on open-source code or proprietary in-house software. Make sure you read and understand the license terms completely. You should not assume that just because you can look at it, you can use it, and just because you can use it, you can ship it.

It's not only what you can do with their code, but how does their license impact what you can do with your code and what your users can do with your product! You have to figure out what rights you are giving up by using a given library and how that affects your future users' use of the software.


First, get Smack from the smack directory on the CD that accompanies this book or from http://jivesoftware.org/smack/. At the time of this writing, the latest version was 1.5.0. Expand the archive somewhere convenient.

Create a plug-in project using File > New > Project... > Plug-in Development > Plug-in from existing JAR archives. On the next page, identify the JARs you want in the plug-in. Click on Add External... and locate and select both smack.jar and smackx.jar from the Smack 1.5.0 install. Click Next to get the page shown in Figure 10-1.

Figure 10-1. New plug-in project for bundling the Smack libraries


Fill in the project name and plug-in id. As discussed previously, the plug-in id and project name should match and the plug-in id should be based on the plug-in originator's Java package naming conventions. Here, the plug-in's code is coming from Jive Software, whose package naming convention for Smack is org.jivesoftware.smack. Use that as the project name. As you fill in the project name, the plug-in id is automatically completed by the wizard. Update the plug-in version to "1.5" to match Smack's version and fill in the provider.

Note

Some see this use of org.jivesoftware.* (i.e., Jive Software's spot in the plug-in id namespace) and their name as the provider as bad form. Others feel that using your own id (e.g., org.eclipsercp.smack) and name seems to claim credit for the Smack code and implies that the code is being forked. There is likely no right answer here. Eclipse itself does both. The Eclipse teams have tended to use the originator's package naming (e.g., org.apache.ant) if the code is being included verbatim. If the code is being modified or adapted, then the Eclipse namespace is used (e.g., org.eclipse.tomcat). The best bet is to ask the originator to deliver her code as bundles!


When the wizard is finished, you should have a Smack plug-in project that looks like the one in Figure 10-2.

Figure 10-2. Smack project after creation


The option to unzip the JAR archives is useful if you want to ship the new plug-in as a JAR itself. Otherwise, the JARs would simply be copied into the plug-in and the plug-in would have to be shipped as a directory.

Aside from creating the project and exploding the JARs, the wizard generates a MANIFEST.MF file. The generated file is shown below. Notice the various values you entered are embedded in the manifest. Notice also there is a list of exported packages. These are all the packages the wizard discovered in the Smack JAR.

org.eclipsercp.hyperbola/MANIFEST.MF
Bundle-Name: Smack Plug-in
Bundle-SymbolicName: org.jivesoftware.smack
Bundle-Version: 1.5
Bundle-ClassPath: .
Bundle-Vendor: Jive Software
Export-Package: .,
 org.jivesoftware.smack,
 org.jivesoftware.smack.debugger,
 org.jivesoftware.smack.filter,
 org.jivesoftware.smack.packet,
 org.jivesoftware.smack.provider,
 org.jivesoftware.smack.util,
 ...

The Export-Package header lists those packages available to other plug-ins. Since the main point of bundling is to make the library classes available to others, exporting them is a good thing. Note that without the exports, the Smack code would be usable inside the Smack plug-in, but not visible outside.

Notice that the bundling did not import any of the other files that were included in the Smack download. If you want the other files in the project, run the import wizard and select the File system import option. Then browse to the expanded Smack directory and choose the files to import into the existing Smack plug-in project.

10.1.2. Testing the Bundling

It's a good idea to test your newly bundled Smack just to be sure everything is in order. The easiest way to do this is to create another plug-in that uses Smack and then ensure that you can compile against it and run with it. The Smack API is very convenient, so let's just create an RCP application that sends a message using the new Smack plug-in.

First, create a new plug-in project and call it smack.testing. Make it an RCP application, and on the templates page, select Hello RCP. This is similar to the procedure you followed in Chapter 4, "The Hyperbola Application," to create the Hyperbola shell. When the wizard is done, the smack.testing plug-in editor is left open. On the Dependencies page, add org.jivesoftware.smack to the Required Plug-ins list and save the file.

Dynamic classpaths

One of the advantages of defining dependencies at the plug-in level is that it allows Eclipse tooling to manage your classpaths. Here you added Smack to the smack.testing plug-in's required list and automatically the content of the Smack plug-in was available on the smack.testing plug-in's classpath. The required plug-ins need not even be in the workspacePDE and JDT take care of it for you.

You have already been working in this mixed mode throughout the previous chapters. The Hyperbola plug-in depends on the org.eclipse.core.runtime plug-in, but that plug-in has always been in your target. The Hyperbola plug-in compiles because it said it required the Runtime. PDE hides the details.

If at some point you check the Runtime out of CVS and into your workspace (e.g., to fix a bug or prototype a new feature), PDE updates the classpath and Hyperbola continues to compile and run.


We don't really care about a UI for our little test, so open the generated Application class and replace the run() method with the little Smack example below:

smack.testing/Application
public Object run(Object args) throws Exception {
  try {
    XMPPConnection con = new XMPPConnection("eclipsercp.org");
    con.login("reader", "secret",
        Long.toString(System.currentTimeMillis()));
    Chat chat = con.createChat("eliza@eclipsercp.org");
    chat.sendMessage("Hi There!");
    Message message = chat.nextMessage(5000);
    System.out.println("Returned message: "
        +  (message == null ? "<timed out>" : message.getBody()));
  } catch (XMPPException e) {
    e.printStackTrace();
  }
  return IPlatformRunnable.EXIT_OK;
}

As you type the code, notice that code completion works and classes are resolved by the Java editor. This is a good signthe smack.testing plug-in can see the Smack classes. Ultimate proof comes when you save the Application class and it compiles without errors.

To run the test, right-click on the project and from the context menu, select Run As > Eclipse Application. If all goes well, the test code connects to the eclipsercp.org chat server as the user "reader" and sends a message to "eliza".

Eliza is actually a chat robot that responds to your messages in various ways. You should see her response in the regular Eclipse Console view. Depending on your UI setup, you may have to open it using Window > Show View > Other... > Basic > Console.

Returned message: HI THERE!

Here, Eliza has simply changed your message to uppercase and sent it back. Even if you get a timeout, the test has proven itselfyou were able to write a plug-in that compiled and ran with the bundled Smack library.

Bundling Smack was relatively easy. Other libraries may be more complicated depending on what they are doing and how they work. The typical problems encountered revolve around Eclipse's strong notion of component, classloading, and how the classpath is managed. Many libraries assume that all classes are available on the classpath, but Eclipse puts constraints on what classes are visible and from where. The most common programming patterns that can cause problems when bundling are the following:

  • Does the code use reflection, Class.forName(String), or class references such as Foo.class?

  • Does the library use the context classloader?

  • Does it make assumptions about seeing classes from the Java Extensions classloader?

There are also some general issues to consider when bundling existing libraries:

  • Are the original JARs signed and is the signature important?

  • Does the license allow you to repackage?

  • Can multiple JARs be combined and still work? For example, are there overlapping package structures that rely on classpath ordering?

If you are having problems bundling librariesfor example, you are seeing a lot of ClassNotFoundExceptions and NoClassDefFoundErrorssee Chapter 20, "Integrating Code Libraries," for instructions on how to fix these problems.


Previous Page
Next Page