Letters to the Editor

Out of the mouths of readers

"Listen to Heartbeats Using JMS"

Nicholas Whitehead

Get synchronized

Nicholas,

I noticed in your code that access to the class data members of HeartbeatPublisher and HeartbeatSubscriber (e.g., state, run, process, and so on) is not synchronized. This can cause problems since more than one thread accesses these data members: the thread that executes the run() method and the JMS (Java Message Service) thread that executes the onMessage() method.

Refer to these JavaWorld articles for more info about this issue: "Warning! Threading in a Multiprocessor World" (February 2001) or "Double-Checked Locking: Clever, but Broken" (February 2001).

Also, depending on the JMS server load, the heartbeat message will be delivered at varying intervals, or the messages might expire before they are delivered. That can prove problematic.

Atul

Atul, Thank you for your feedback and your debugging efforts on my behalf. I will revise the concurrency issues on the classes you mentioned. I realize the JMS server load might affect the delivery rate of heartbeat messages. In a way, this is intended, since delayed heartbeat messages indicate delayed regular messages as well, a behavior we attempt to measure and respond to. For example, in some real-time pricing environments, a delayed price might prove as bad as no price. So a failed heartbeat session would warn the consumer of delayed traffic, and this event might relate to some protective measure. However, in the interest of flexibility, I recommend that developers implementing the heartbeats determine a period ratio suitable for their environment, whereby a publisher's period is n times the subscriber's period. For example, a publisher period might be every 5 seconds, and a subscriber period might be 25 seconds -- a period ratio of 5. The period ratio allows some elasticity in the system where short bursts of extremely high activity do not cause rolling heartbeat session failures across your applications. That does not differ much from low-level TCP packet retransmissions, where we accept that some packets might be lost in the shuffle. As far as message expiration, note that the default time-to-live for the HeartbeatPublisher is zero, meaning the messages will not expire. Again, in the interest of providing more stringent characteristics to the heartbeat session, the publisher does expose a method that allows you to modify the time-to-live. In that way, you can specify that, if the heartbeats cannot make it through in n milliseconds, the service level you expect from your JMS network is not being delivered, and the heartbeat session will fail. Nicholas Whitehead

"Mix Protocols Transparently in Web Applications"

Steve Ditlinger

A Servlet 2.2-compliant solution

Steve,

I have a proposed solution that you might like to use or file in /dev/null.

In the RequestUtils.java file, the method getRequestParameters() will work with Servlet 2.3 only. WebSphere 4.0.1, which I use, only supports version 2.2 by default.

I suggest something similar to the code below as a 2.2-compatible version:

    public static String getRequestParameters( HttpServletRequest aRequest
){
        StringBuffer aReturn = new StringBuffer("");
        Enumeration parameterNames = aRequest.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String requestParameter = (String) parameterNames.nextElement();
            String[] aValues =
aRequest.getParameterValues(requestParameter);
            for (int i = 0; i < aValues.length; i++) {
                if (aReturn.length() > 0) {
                    aReturn.append("&");
                }
                aReturn.append(requestParameter);
                aReturn.append("=");
                aReturn.append(aValues[i]);
            }
        }
        return aReturn.toString();
    }

I became confused, because, although you use the getParameterMap() method (2.3 only), you also use the HttpUtils class (deprecated in 2.3).

Dan Leong

Dan, You are right; I do mix Java past and future in the article's code. My team has since eliminated the HttpUtils usage for our own purposes. Regarding Servlet 2.2 versus Servlet 2.3 specifications: Others wrote me about the same or similar workaround for their non-2.3-compliant Web containers. I had hoped that most vendors (especially IBM!) would be Servlet 2.3-compliant by now. Steve Ditlinger

"Write Once, Persist Anywhere"

James Carman

Apply DAO with Value Object

James,

I suggest you use the Data Access Object (DAO) design pattern with the Value Object design pattern -- also from the J2EE Patterns Catalog (login required). A value object is a simple Java object with get/set methods representing a table's view. When you use these two patterns with the APIs, the framework is much safer to use.

Let's say you have a table called employee, and the user wants to insert an employee; the code generated by the framework looks like this: public void create (Employee emp). That proves a better approach than public void create (object obj) -- though I agree the second method saves some code, but it's auto generated anyway.

Code that uses APIs with object in the parameters relies heavily on type casting, and the API is not intuitive to read. Parameters defined with data types are better.

Abhishek

Abhishek, I designed the API with the Value Object pattern in mind. As you stated, a value object is merely a lightweight, business data object. My API requires that the

java.lang.Object

parameters passed in to the persistence methods adhere to the JavaBeans specification with respect to setter/getter naming conventions, and they must provide a default constructor. These lightweight JavaBeans are the value objects. The design I suggested strives to avoid object-type dependence -- hence the

java.lang.Object

parameters. It provides a reusable framework that you can use in any application. I intentionally left the method signatures generic for reusability. If the

Dao

doesn't support the type passed in to the method, it will throw a

DaoException

. My

JdbcDao

implementation does not rely heavily on type casting. It uses reflection to hydrate/dehydrate the JavaBeans. I know what you're thinking: reflection is slow. However, I've done benchmarks and found that reflection doesn't introduce any performance bottlenecks. In fact, I've found that, in some cases, reflection was faster than my generated code! I designed the API to be as simple as possible. That's why I avoid object-type dependence. Otherwise, I'd need different interfaces for different object types like this:

public interface EmployeeDao
{
  public void create( Employee emp ) throws DaoException;
  public void delete( Employee emp ) throws DaoException;
  public void update( Employee emp ) throws DaoException;
  ...
}

You cannot reuse that in other applications. Also, how would I obtain a reference to an

EmployeeDao

object? Would I need an

EmployeeDaoFactory

, or would I have a

DaoFactory

class that looks like this:

public class DaoFactory
{
  public EmployeeDao createEmployeeDao() throws DaoException;
  public CustomerDao createCustomerDao() throws DaoException;
}

My framework tries to eliminate this object-type persistence. That's why it differs from other implementations. Your approach is the exact implementation strategy suggested by the

J2EE Pattern Catalog.

My implementation takes the abstraction one step further. James Carman

How do you avoid changing code in the DAO implementation layer?

James,

I have applied the DAO pattern in my projects before. It seems the pattern just allows portability between different data stores -- RDB (relational database), ODB (object-oriented database), XML FileSystem, and so on. But it still doesn't solve the basic issue that the object field change will affect the data store-handling code too. For example, when we add a new member variable in the object that requires persistence, it still must manually change the data store-handling code (for RDB).

Is there a solution for that? As I am lazy programmer, changing an object field that requires a manual change of data store-handling code is a really ineffective approach.

LCK

LCK, I have encountered the problem you mention, as have others. You can avoid changing code in your DAO implementation layer by basing the mapping on a configuration file, as I did in my JDBC (Java Database Connectivity) example. Then, if you add another field to the class you wish to persist, you just add another field-mapping descriptor to your configuration file. Now, if you really want to avoid changing anything but the code (and possibly the database), you must devise some standard naming scheme for your persistent storage tier. For example, you could ensure all persistent class names map to database tables, and all persistent property names map to database columns. Essentially, you would have to construct your mapping mechanism so that it need know only the type of object to persist the mechanism into the database. James Carman

Tips 'N Tricks

"Java Tip 122: Beware of Java Typesafe Enumerations"

Vladimir Roubtsov

Another equals() implementation

Vladimir,

I read your discussion with Edoardo and as I frequently use typesafe enums myself, I'd like your comments on this equals() implementation:

public int hashCode() {
return m_value? 1 : 0;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass().getName().equals(obj.getClass().getName())) {
return hashCode() == obj.hashCode();
}
return false;
}

I think it is:

  • Fast enough -- certainly a lot faster than reflection
  • Typesafe

However, I don't like it, and I wonder why I've never been forced to implement equals() this way. Somehow we always find ourselves in trouble if different class loaders load the same class, which we try to avoid. Unless you work in a non-object-oriented way -- using maps of ints, strings, dates -- I find it difficult to use real objects loaded by different class loaders. How would you implement an equals() on the following:

public class Person {
String name;
int gender; // or Gender gender?
...
}

and use it in the same test bench you've written for Enum?

Peter

Peter, Your

equals()

implementation is one of the better attempts at fixing the typesafe pattern that I've received. I still have a few objections to your version though:

  1. Relying on class name and hash code equality just seems dangerous. Although imagining circumstances where this would fail is hard, such code does not instill much confidence.
  2. Your equals() is still slower than a simple object reference comparison. You incur some six-to-eight method calls per comparison, depending on what data from this object you might cache.
  3. As I mentioned in my reply to Edoardo, I don't understand why an equals()-based solution can be considered typesafe in the first place: the method will take in any generic Object parameter. The compiler will fail to inform you that the following code won't compile:
    Enum e1 = Enum.TRUE;
    ...
    SomeOtherEnum e2 = SomeOtherEnum.TRUE; // Oops, mistake: should use Enum type here
    ...
    if (e1.equals(e2))
    {
    ...
    }
    
    The compiler would detect such a mistake if you were using reference comparisons (e1 == e2). Comparing different types through Object references is not any safer than comparing primitive int enum values.

I tend not to use typesafe enums. However, they can provide much additional value unrelated to comparison speed, such as implementing additional methods in the enum class. If I did use typesafe enums and was concerned about class loaders, I would implement such an enum class with an internal

int

ID field and use that value for identity comparison (via an exposed

getID()

method). Invoking a class-specific method like

getID()

requires you to cast your data to the actual enum class, at which point any mistakes related to loading the same class in multiple class loaders would become apparent; you will get

ClassCastExceptions

-- which would not happen if you used reference comparison (

==

) or

equals()

in the same situation. However, that is still a sub-par solution, which is why I would rather have Java support a good typesafe paradigm natively. Vladimir Roubtsov

"UI Design with Tiles and Struts"

Prakash Malani

Can you avoid hard-coded URLs using the Struts taglibs?

Prakash,

To avoid using hard-coded URLs in my HTML, I want to apply the technique described in your article to <FORM> and <A>. Is that possible when using the Struts taglibs?

For example, instead of writing:

<html:form action="../myAction.do" ...

I would like to write:

<html:form action="myAction" ...

FR

FR, Take a look at the

<html:base/>

tag. As far as

<html:form>

tag is concerned, we use Struts actions like

myAction.do

and typically only top-level ones. For example:

<html:form action="myAction" ...>

Now, in the

struts-config

XML configuration file,

myAction

can map to

com.malani.struts.action.DoFirst

action. That can then forward to any complex path, such as

/componentA/a.jsp

or whatever page we want. Hence, we haven't seen the need for relative paths in actions. If you want a dynamic action (i.e., not hard-coded), you can use Tiles as well. Do the following:

1 2 Page 1
Page 1 of 2