Letters to the Editor

Java Q&A

"Profiling CPU Usage from Within a Java Application"

Vladimir Roubtsov

How do you use Runtime.exec() to return PID?

Vladimir,

In your article, you indicate that "A suggested alternative might use Runtime.exec() to determine the JVM's process ID (PID)." How do you do this? There is no method in the Process class to return the PID.

On a more positive note, your Java Native Interface (JNI) classes look very useful.

Nigel Charman

Nigel, I was referring to using Runtime.exec() to execute a command like ps -f, and parsing PID and PPID (parent process ID) data in the output to figure out the JVM PID. This needs to be adjusted for whichever Unix/ps flavor you use. And this won't work on Win32 systems at all unless you happen to have a reasonable ps port. This is very fragile, of course. Vladimir Roubtsov

"Should You Go with JMS?"

Thomas Laramee

Security through obscurity?

Thomas,

In your article, you say, "Also, because JMS is a generic API, it's more prone to security breaches than a proprietary system that uses an unpublished API."

You are suggesting that security through obscurity is a good thing? Although obscurity can sometimes provide tiny benefits, those benefits are difficult to quantify and can vanish with a single newsgroup posting. Obscurity should never be relied upon as a design rule and has no place in an article about architectural tradeoffs.

I like your diagrams, but the article overall needs to take into account Java Message Service (JMS) implementations' significant differences in performance (small versus large messages; database versus filesystem queues). Moreover, many of the pros and cons are trivial, arguable, or so general that they apply to any implementation.

Paul Baclace

Paul, Maybe taken in the worst possible light, yes, you're right. Security through obscurity is not a good thing (though I'm not so sure the benefits are "tiny" and "difficult to quantify"). However, my comment intended to convey the idea that the richer your Internet-available API is, the greater the security risk. Take HTTP for example; it's seemingly such a simple protocol, yet there are endless security problems with HTTP servers. JMS is a very rich API, so making it available carries with it a substantial security risk (as opposed to fronting your JMS servers with a set of HTTP servers and then putting the JMS servers on a private network). Simplicity is the key to strong security, and providing generic connectors makes it easy for someone to penetrate your server security. There is no way to prove that any set of APIs is better than the other, but best practices say you shouldn't make unnecessary items or knowledge available. I agree that it would make sense to discuss some implementation details, but that wasn't the focus of the article. The discussion of whether to use a database queue versus a filesystem queue in your JMS implementation comes after you've already decided to use JMS. Engineers who jump right to the implementation details miss the big-picture design issues (like, is a queue-based solution appropriate for our problem?) and end up with system architectures that do not solve their problems, or solve them in a way that's far more complicated than necessary. You bring up an interesting issue about database versus filesystem queues. This issue concerns a lot more than performance: you need to discuss reportability, robustness, and disaster recovery. Depending on the specific application, some of these issues will trump any performance concerns. The JMS considerations I brought up are not trivial. Something like caching should not be overlooked during your system design phase. I'm pretty sure every issue is arguable. The article tries to formalize some of the arguments surrounding distributed system design and relate this context to JMS system design, such that the arguments are not arbitrary (as they so often are). The end goal is to encourage appropriate choices for system architecture. Indeed, many of the issues are germane to other software systems (to any distributed system, really). That doesn't mean they should not be considered during system design. If anything, that makes them more relevant. Thomas Laramee

Sluggish servlets

Thomas,

After the article's first page, I fully expected you to suggest Jxta or some other distributed technology, but never in my wildest imagination did I think ISAPI/NSAPI (Internet Server API/Netscape API) would come up. You didn't specify why servlets cannot achieve the same tasks the C++ NSAPIs handle. Connection pools, threading, and other issues are handled well in Java. Your solution would not fit most applications I've developed. I haven't used ISAPI/NSAPI in years, and I doubt other readers use them either. We use servlets with Tomcat, BEA WebLogic, and IBM WebSphere.

Taylor Cowan

Taylor, You're right that I didn't specify why servlets cannot achieve the same tasks, and I suspect in many cases they probably can. I didn't suggest servlets for the global registration system because of performance issues; servlets are just too slow for that application (and many other applications). I had the opportunity to design a system for collecting large quantities of data from Internet users (not the distributed login system; it was a contest engine), and I decided to use servlets instead of ISAPI to save time. When it came time to test how many users per second the system could handle, I was completely disappointed (as I always seem to be when I use servlets). Despite tuning the app server using the vendor's recommended approaches, the system achieved profoundly less throughput than a comparable C/C++ ISAPI/NSAPI-based system. This was a relatively niche application though; I couldn't take advantage of the app server's database caching, and I didn't need data analysis or presentation (presentation was done via other servlets), but it was definitely too slow. As to whether or not the suggested alternate approach would fit your systems, you're correct in that it's a relatively niche design; but, because it uses HTTP as its communications protocol and is presumably one part of a data-driven application, it can be used in more places than you think, particularly when performance is paramount and data presentation is asynchronous from presentation and analysis (plus, I forgot to mention Apache, which could be used instead of Netscape's server or Microsoft's Internet Information Server (IIS)). It appears that most people are using Apache and IIS. Although it is possible, I'd be surprised if people use Tomcat/WebLogic/WebSphere as both their application server and their main Web server (e.g., Tomcat listening on port 80 without an Apache install fronting it). Web server infrastructure can take advantage of APIs for plug-ins/modules (point taken on the Netscape app server though). Thomas Laramee

"Yes, You Can Secure Your Web Services Documents"

Part 1: XML Encryption keeps your XML documents safe and secure

Part 2: XML Signature ensures your XML documents' integrity

Ray Djajadinata

Put serialVersionUIDs in your Serializable classes

Ray,

In your article you say:

The moral of the story? Always put serialVersionUIDs in your Serializable classes, if some JDK you're using computes its serialVersionUIDs differently. If that happens, your library will still work with another JVM, because it will compare the SUID with the class's serialVersionUID, so it doesn't matter even if one of the implementations is buggy.

Can you kindly give me step-by-step instructions for putting serialVersionUIDs in my Serializable classes?

John Smith

John, Certainly! Let's say you have a class like the following:

package blah;
import java.io.Serializable;
public class MySerializableClass implements
Serializable {
}

After you've designed the class (all the methods, members, etc.), then run the serialver utility against this class. I use the one that comes with the Java 2 Platform, Standard Edition (J2SE) 1.4.1, and this is the result:

static final long serialVersionUID =
4051016186521705156L;

This is the result of running serialver against an empty

MySerializableClass

. Adding

main()

like this:

package blah;
import java.io.Serializable;
public class MySerializableClass implements
Serializable {
   public static void main(String[] args) {
      System.out.println("Hello world!");
   }
}

changes serialver's result to:

static final long serialVersionUID =
5739497617226741935L;

Simply copy this and paste it into your class like this:

public class MySerializableClass implements
Serializable {
      static final long serialVersionUID =
5739497617226741935L;
     public static void main(String[] args) {
        System.out.println("Hello world!");
     }
}

That's it! Hope this helps. Ray Djajadinata

"Integrate Your Legacy Applications with JNI"

Michael L. Perry

Michael,

I have the following design issue. Please provide some insight as to whether the approach is OK.

We have a C++ application that is presently logging information into binary files (in real-time mode) for later use (in offline mode). At the same time, this information is sent to a Java-based Web graphical user interface (GUI) application over a socket connection.

We want the backend C++ application to put information a into standard relational database management system (RDBMS) (instead of binary files); in offline mode, the GUI application would directly query the RDBMS instead of again invoking the backend C++ application to read the binary files and send the data.

I plan to use the JDBC (Java Database Connectivity) API in the GUI for reporting purposes and JNI as the glue between the C++ application and JDBC APIs for data population.

Will this solution work with regards to performance or will the JNI layer become an overhead? Please provide your expert advice on this and offer any pointers about the JNI-JDBC wrapper.

Sunita

Sunita, As you know, the premise of the article was application integration, not necessarily language integration. As such, I began with a technology assessment, which concluded with using JNI to integrate a new Java application with the existing C application. Along the way, I weighed several alternatives, one of which is integration not through program code, but through the database itself (as stated in the article):

To integrate Aphid with Beetle, we could have chosen to access the database directly through JDBC, which would have yielded disastrous consequences. Because much of the business logic that is necessary for proper operation (such as balance-based double entry) is actually encoded within Beetle, circumventing the application would require us to duplicate the business logic in Aphid.

In that case, I had a compelling reason not to use the database as an integration point. Your situation, however, might be different. As I understand, your current solution populates binary files from a backend C++ application. You wish to instead populate a relational database. Your best option is to use an appropriate data access technology in C++ itself. Based on the RDBMS that you choose, you might use ODBC (Open Database Connectivity), OLE DB, or ADO (ActiveX Data Objects). You also wish to modify your Java-based Web front end to directly access the data using JDBC. I believe that is the proper choice for the front end, as you will take advantage of Java's strengths, and JDBC drivers are available for the majority of RDBMS vendors. In your situation, I recommend a language-appropriate data access technology over JNI. Use ODBC, OLE DB, or ADO in C++, and use JDBC in Java. Unless you have a compelling reason to integrate your application code—such as shared business logic—you will find it easier to integrate just your application data. Michael Perry