 | Level: Intermediate Brian Fleming (flemingb@ca.ibm.com), Advisory Software Engineer, IBM Aaron Kasman (akasman@us.ibm.com), Staff Software Engineer, IBM
27 May 2008 Imagine being able to navigate to the rich function of a Rich Client Platform
(RCP) application just as easily as you can navigate to a Web page today. Follow along
to enable the opening of specific business objects in your Eclipse RCP application simply by clicking a URL.
The Eclipse Rich Client Platform (RCP) provides an extremely flexible, feature-rich
framework for thick clients. But one drawback is the ability to easily link to
business objects in an RCP application from other sources. It would be helpful if a
user were able to click a link in another application and be taken to the RCP
application with a business object referred to in the link already open. For example,
imagine an RCP application used to process expense claims. Perhaps a report for overdue
reimbursements is generated and published as a spreadsheet (or on an intranet, or as a
rich-text document, or as an e-mail, or as … well, you get the picture). The report
probably has a reference number for each overdue claim. Instead of forcing the consumer
of that report to copy and paste the reference number into a search dialog within the
RCP application, the report could contain a hyperlink URL that will launch the
RCP application, taking the user directly to that expense claim. This article will explain how to accomplish just that.
Readers should have experience writing Eclipse plug-ins, as well as general knowledge
of the Windows® registry and the TCP protocol. While this article provides
specific examples for a Windows operating system, the same function can be achieved on
other operating systems. See Resources for more information.
Solution overview
Let's take a look at the big picture of how the solution works once it's in place.
Then we will break it down and discuss how to implement each of the parts.
Follow along with the flow in Figure 1:
- Assume that a user already has the
RCP application open on his desktop.
- Then suppose this user receives an e-mail in his
favorite mail client containing the link rcp://claim=25222 — a reference to an
overdue claim (1).
- The user clicks the link, which launches the user's default browser
to handle the request (2).
- The browser knows that it cannot natively open this URL, so
it consults with the Windows registry to determine how the action should be delegated
(3).
- The registry looks up the rcp:// protocol and determines that there is a batch
file bound to it (4).
- This batch file is executed (5), which triggers a stand-alone
Java™ client (6), captures the URL's parameters, and makes a local TCP
call to a TCP server embedded in the RCP application for this purpose (7).
- The TCP server handles parsing the parameters from the URL (i.e., claim=25222) and requests the
RCP application to open the corresponding business object (8).
- The user is then presented with the requested business object in the RCP
application UI (9).
Figure 1. Flow control when opening an RCP application using a URL
There are many steps involved in this process, but fortunately, each is relatively
straightforward and can be adapted to your environment and applications. Some
finishing touches help with details like bringing your RCP application into focus in Windows.
Solution details
Registering your application to a URL protocol in Windows
Windows uses entries in the registry to recognize valid URL protocols and to determine
what application a request with a particular protocol should be sent to. To enable our
RCP application to respond to URLs, a key must be created under the HKEY_CLASSES_ROOT
hive. The key name must match the protocol being created. In this article, we are using
an "rcp://" URL protocol, so the key must be named "rcp." The default string value
under this key corresponds to the display name of the new protocol. Under the "rcp" key,
we must also create a shell\open\command key with a string value containing the path to
the application Windows should open when it receives an "rcp://" request.
In this article, we will point Windows to a batch file (see "The batch file"). The string value for this key should also have a
%1 appended to the end of it, telling Windows to pass the URL query string to your
application. This is how we will pass context information, such as the particular
business object to open, to the RCP application.
The following Windows batch file snippet will create the appropriate keys in your
registry, with an "rcp://" protocol, which will launch Notepad. To customize the script,
replace all instances of rcp with the protocol you wish to use and
C:\Windows\Notepad.exe with the full path to the file you want Windows to execute.
Listing 1. Batch file code to register a URL protocol in the Windows registry
reg add HKCR\rcp /ve /d "URL:RCP Protocol"
reg add HKCR\rcp /v "URL Protocol"
reg add HKCR\rcp\Shell\Open\Command /ve /d "C:\Windows\Notepad.exe %%1"
|
Note: If you prefer updating your registry manually with regedit,
see Resources for an article describing how to do this.
Once the URL protocol has been registered, you can test it out by typing rcp:// into your browser's address bar and clicking Go.
Notepad (or the file you chose to register) should now be open.
Other operating systems, such as Linux®, delegate the job of
registering URL protocols to the browser. See Resources for
instructions to register a URL protocol in Mozilla Firefox.
The batch file
Once you have tested that the rcp:// protocol we defined opens Notepad as expected, try
remapping the rcp:// protocol to a batch file that will launch the TCP client. To do
this, change the value for the HKCR\rcp\Shell\Open\Command registry entry. See Listing
2 for an example of how the batch file that launches the TCP client might look.
Listing 2. Batch file code to launch a TCP client
@echo off
set JAVA_BIN=c:\<insert your java directory here>
cd <root location of your URIClient application's package.>
%JAVA_BIN%\java.exe com.company.uri.URIClient %1
EXIT
|
Table 1. Annotations for Listing 2
| Line number | Annotation |
|---|
| 2 | For example, set JAVA_BIN=C:\Program Files\IBM\Java50\jre\bin
|
|---|
| 3 | For example, the directory containing the TCP client's parent package |
|---|
| 4 |
URIClient is described below |
|---|
The TCP client/server pair
As described in the overview, the user's action of clicking on the rcp:// hyperlink
ultimately fires off a TCP request that hits a TCP server embedded in the RCP
application. This solution involves a bit of network programming, but fortunately, the
Java API takes care of the details of the TCP communication for us.
In our example, the TCP server is launched in an RCP plug-in's startup code and waits
for a call from the TCP client. The call will be from the client to a server on its
localhost, made on a port number known to both the client and the server. The client
passes the details of the URL request to the server over a Java socket. The TCP server
is then responsible for executing the appropriate RCP actions to open the business
object. These actions will be specific to the particular application, but we'll deal
with that in "Handling the business object."
For our demonstration, we use four Java classes that live in the com.company.uri
package.
-
URIClient.java
- A stand-alone TCP client triggered by the URL selection
-
URIServer.java and URIServerThread.java
- Comprise a TCP server embedded in our RCP application
-
URIConstants.java
- Some constants shared between client and server
These Java files are available for download.
The TCP server —
URIServer and URIServerThread
-
URIServer is responsible for listening for requests. As it detects a request, it
spawns a thread of URIServerThread that will handle the connection with the TCP client.
-
URIServer can be launched in a plug-in's initialization class. Each RCP plug-in may
have an associated startup class that extends org.eclipse.ui.plugin.AbstractUIPlugin.
This class's start method can initialize URIServer.
- Our RCP application spawns
URIServer by calling new URIServer().start(), launching the sever in its own thread and
preventing the RCP application from blocking with waiting TCP requests.
- Our
URIServerThread handles logic for opening the business
application. This will be discussed in detail in "Handling
the business object."
- Note that both
URIServer and URIServerThread extend java.lang.Thread.
Listing 3. Sample plug-in start method
/**
* This method is called upon plug-in activation, starts up URIServer
*/
public void start(BundleContext context) throws Exception {
super.start(context);
new URIServer().start();
}
|
The TCP client application —
URIClient
- The TCP client is deployed as a stand-alone Java file not referenced by the RCP
application.
URIClient.main() is executed when triggered by
the batch file associated with the rcp:// protocol.
- The constructor passes the URL parameters to the
tcpConnect
method. This method constructs a socket targeted to the TCP server on the localhost at
a host number known both to the client and server through URIConstants.
-
Tip: Consider that while the Java client isn't referenced by an RCP plug-in,
deploying it within a plug-in allows the code to be updated through the Eclipse updater
framework. If it were to reside outside of a plug-in, deploying code updates becomes more difficult.
Handling TCP requests
- How do the TCP client and server communicate? Assume that the RCP application and,
therefore, the TCP server, is already running. As we have explained, the registry and
batch file handle launching the TCP client.
URIClient will
strip off the parameters (i.e., claim=25222) and will attempt to make a socket
connection to the URIServer at a port number known to the client and server.
- Now that the connection's been made, the server will acknowledge the client and
request further instruction by sending a literal stored in the constants file, and known
to the client and server. In the example, the server sends the literal
sendAction. Once the client receives this instruction, it responds by
sending the server the name-value pair — in this case, "claim=25222"
— containing the information about the desired business object. At this
point, the client and server terminate their connections. Of course, as long as
the server knows what to expect, the specific name-value pairs being sent can be customized.
- It's now up to the TCP server to parse the arguments and launch the appropriate actions.
Ideally, the TCP client and server that have been described above could both be
launched by the RCP application, eliminating the need for a stand-alone Java
application and reducing the number of deployed artifacts. Whenever the RCP application
is triggered using a URL, conventional application startup would be attempted using the
application's .exe or batch-file starter. However, early on in the application's
initialization, the application would check whether an instance of it is already
running. If the application is already running, a TCP client would be initialized and
pass the URL arguments to the embedded TCP server waiting to receive such notification
in the running RCP application. The server would handle opening the respective business
object, as in the example above. However, if the RCP application is not yet running, it
would proceed to be opened at this point, and it would use the URL arguments as RCP
program arguments to open the appropriate business object.
Embedding the TCP client in the RCP application may not be possible if you are unable
to access your application's early startup code, such as if you are deploying a plug-in
on top of an existing application. For this reason, this article has described the more
flexible approach of a stand-alone TCP client.
Handling the business object
As noted, our URIServerThread handles opening the business
object. In the listing provided here, for simplicity, the code launches a dialog that
shows the business object ID provided on the URL. In a real application, we would do
something far more interesting, like invoke an Action that
will find and open our business object that has the identifier provided.
Eclipse has a single thread for managing the user interface, and some SWT API methods
may only be called from that thread. (see Resources for more
information). Because our URIServerThread is running as its
own thread, we need to consider this limitation. In order for a spawned thread to call
back to the Eclipse workbench, it must use methods in the Display object to gain access to the UI thread. If this is not done,
an ERROR_THREAD_INVALID_ACCESS error will be thrown at runtime.
Finishing touches
By default, clicking on the rcp:// link will indeed open the business object in an RCP
application, but the RCP application may be hidden behind other applications, such as
the one that contained the rcp:// link. It is important that we bring the RCP
application into focus. In the URIServerThread listing,
notice the following statements that are responsible for bringing the RCP application
to the user's attention:
shell.setActive();
shell.setMaximized(true);
shell.setVisible(true);
shell.setFocus();
|
We have not mentioned error handling, but this is clearly necessary in several places.
First, TCP communication brings along with it try/catch blocks that need to be handled
appropriately. Also, one needs to ensure that cases are handled for various malformed
URLs, especially to protect against intentional attacks.
You may have noticed that delegating resolution of the rcp:// protocol to the Windows
default browser has the unwanted side effect of leaving a browser window open. While
not ideal, this is something we have tolerated. We would be eager to hear your
suggestions as to how to prevent this, especially in an environment where the RCP
application is distributed widely and tweaking the user settings in Firefox might not be feasible.
Conclusion
The process described details a framework for opening a single business object in
your RCP application using a URL. However, there are possibilities for extending this
idea in interesting ways. For instance, several name-value pairs could be included in
the URL to perform more sophisticated operations. Consider an order-entry application,
where a URL could be used to pre-populate an order with certain products. Following
these steps, any action defined in an RCP application can be accessed
from any application simply by clicking a link.
Download | Description | Name | Size | Download method |
|---|
| Sample code | os-eclipse-rcpurl.source.zip | 4KB | HTTP |
|---|
Resources Learn
Get products and technologies
Discuss
-
The Eclipse Platform newsgroups should be your first stop to discuss questions regarding Eclipse. (Selecting this will launch your default Usenet news reader application and open eclipse.platform.)
-
The Eclipse newsgroups has many resources for people interested in using and extending Eclipse.
-
Participate in developerWorks blogs and get involved in the developerWorks community.
About the authors  | |  | Brian Fleming is an architect in IBM Software Services for WebSphere, specializing
in IBM's own implementation of WebSphere Commerce Enterprise and IBM Sales Center for WebSphere Commerce. |
 | |  | Aaron Kasman is a software engineer in IBM Software Services for WebSphere where he
has worked with WebSphere Commerce, specializing in Eclipse rich client application
development. He is also a collaborative-technology enthusiast. |
Rate this page
|  |