HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML

Unlike the doctor who works for your HMO, I won't require a copayment for each visit nor ask you to fill out long arduous forms. I'm here to help readers of Java Developer's Journal find a cure for their Java system ills.

Q: I'm constructing a tree from a file and I need a way to halt the tree construction until after the file is finished reading from a separate thread.

A: A couple of approaches come to mind. Your problem centers on the behavior of threads, so let's look at a couple of possibilities. First, you could consider having the TreeBuilder thread check a global variable such as isFileLoadComplete and yield if file loading has not been completed. You could have the FileLoad thread get a reference to the TreeBuilder thread and make it sleep until the file has been loaded. You could also use thread synchronization using notify and waitFor. I recommend none of those approaches, and instead suggest a different design.

If you want to build a tree, it's easier to do it in the same thread. Consider the following approach: upon opening a file, create an instance of the tree. When reading each line of the file, update the tree in place. Once you're done reading the file, copy the tree to its appropriate location. This approach will keep your code clean and allow your program to run faster. If the tree you're adding to is also updated by simultaneous file reads, make sure that you wrap it in a synchronized block.
I hope this solves your problem.

Q: In your January column, (JDJ, Vol. 7, issue 1), your answer to the question about authentication to a Windows 2000 server gave me some good insight. Our company has chosen not to go to Active Directory yet. Can you describe a similar approach to the problem using Windows NT 4.0 server?

A: Active Directory is one of the better implementations of LDAP on the market and is one of the few that isn't licensed on a per-entry basis. I hope your organization will migrate in a timely manner. To authenticate to a Windows NT domain, you can't use the JNDI approach mentioned but will need to consider implementing the Java Authentication and Authorization Service (JAAS). JAAS provides a Windows NT provider that will meet your needs. For more information on JAAS visit http://java.sun.com/products/jaas/index-10.html.

Q: I've been doing a little reading on JAAS and I like the fact that there's a standard API for authentication and authorization. Can you describe how to use JAAS's authentication mechanism without relying on its authorization machinery? For example, I'd like to use JAAS as the standard way to find out who the current client is and then use that knowledge to make some minor behavioral adjustments to the code. For example, if you're logged in as Bob, then I might tweak a SQL statement a bit so you don't see as much as user Ted. Can JAAS do this for me?

A: Let me make a couple of assumptions: first, if you have your own authentication mechanism, such as a login page, you most likely will have stored who the user is in a bean. If you want to know who the logged-on user is in a Swing application, you can determine this from the Java system properties that have a user.name attribute.

JAAS wouldn't help you with tweaking SQL statements, as this is better handled by either database-level security such as creating a new JDBC connection for each user or by delegating the change of SQL to a stored procedure. JAAS would be appropriate for authentication and authorization if you were integrating with a third-party security provider, such as the Active Directory and Windows NT Domain, or using a single sign-on solution such as Netegrity's SiteMinder, RADIUS Servers, or Kerberos.

Each of these products will require that the user be authenticated before any authorization step takes place. You can hide the authentication step within your application, but you can't skip it.

Q: I have a servlet that talks to a secure gateway to authorize credit cards. It uses JDK 1.3.1 and JSSE. When I upgraded to JDK 1.4, it stopped working. The following line of code throws a ClassCastException:

HttpsURLConnection connection =
(HttpsURLConnection).url.openConnection();

Could you tell me why my code doesn't work?

A: This problem can be easily corrected by changing some import statements. In JDK 1.4 HttpsURLConnection has changed to javax.net.ssl and no longer uses com.sun.net.ssl. If you still need to use an older class, you can reference it at startup by using:

java-Djava.protocol.handler.pkgs=
com.sun.net.internal.www.protocol

Alternatively, you can set it at runtime as follows:

System.setProperty("java.protocol.handler.pkgs"
,"com.sun.net.ssl.internal.www.protocol");

Q: What's the best way to internationalize exceptions?

A: I'm not sure of the best way, but I can show you how I would approach the problem. I would suggest creating your own exceptions and throwing them using internationalized strings. The following code snippet demonstrates the approach:

import java.util.Locale;
import java.util.ResourceBundle;

public class InternationalizedException extends Exception {
ResourceBundle rb = Resource
Bundle.getBundle("i18nBundle",
Locale.getDefault());

public InternationalizedException() {
super(rb.getString("exceptionKey");
}
}

To learn more about Java and internationalization, I suggest visiting the following URL: http://java.sun.com/doc/books/tutorial/i18n.

Q: I'm using Java and EJBs to access a legacy system. Accessing the host each time is very expensive. The data from the legacy system is read-only and I'd like to cache it somewhere. I'm not sure where it should be stored.

A: The Java Community Process is working on the JCache specification that will solve your problems in the future. In the meantime, let me see if I can help you with your problem. For EJB developers the first thought may be to store it in a stateful session bean. Stateful session beans would cause the construction of the bean for each client access, so this won't work. The next idea may be to use stateless session beans. This won't work either, because stateless session beans exist in a pool and the container determines when and how many instances will be constructed.

Entity beans may also come to mind but may not work well either. Remember that the EJB container can call activate and passivate anytime it desires. The activate call would need to retrieve the value from your legacy system again.

Some developers might consider using the Singleton pattern in this situation. This works in very limited situations and never works in a high-availability situation. As there is never a Singleton in a cluster, this pattern shouldn't be used. Furthermore, in Java a class is unique based on its ClassLoader, not the Java VM itself.

Let's discuss a couple of approaches that will actually work. First, you can consider using JNDI to store your data. In many of the application servers, JNDI is a clusterable resource, so changes to your read-only data will be replicated to all instances. A second approach is to use an RMI server where you can store copies of your data and have all EJBs connect to it. For high-availability situations you'll need to make the RMI server aware of other RMI servers that provide the same function. A third approach is to store your cached data in an object-oriented database such as Gemstone or Versant. Many databases optimize I/O and cache the data in memory, so there won't be any round-trips between the database and application server.

Q: How do I set the referrer for a URLConnection?

A: The following code snippet demonstrates how to set the referrer:

URL url = new URL("http://doctorjava.htsco.com");
URLConnection conn = url.openConnection();
conn.setRequestProperty("Referer",
"http://doctorjava.sys-con.com");

InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);

Of course, you'll need to catch any MalformedURLExceptions that might be thrown.

Q: What is your opinion of Jtrix?

A: Jtrix is remarkably similar to Jini, as both offer a distributed-service model. Jtrix added some useful features that don't currently exist in Jini, such as a hosting service where a service can find somewhere else to run and copy itself into that space. This will allow a Jtrix application to scale almost endlessly, as it will distribute itself as needed. I can see this being a powerful feature for Web services that in the future may need to be accessed across the planet.

Jtrix added accounting features as well. If a Web service needs to expand via its hosting service, the provider will need a mechanism to bill based on resource usage (CPU, memory, network traffic, and so on). Lack of an accounting feature will hinder the growth of all service-based approaches. The other feature that Jtrix provides is the complete separation of client and server. In Jini the client and server have to use the same versions because they're in the same space.

I prefer that developers use Java standards where they exist and would hope that the Jtrix team would formalize their work using the Java Community Process and focus on making Jini better. If you decide to use Jtrix, I suggest that the Jtrix netlet export a Jini service as a default.

Author Bio
Doctor Java, aka James McGovern, moonlights as an enterprise architect with Hartford Financial Services (www.thehartford.com), where he focuses on the architecture of high-availability and J2EE-based solutions. [email protected]

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.