Skip to main content

Please pass the StringBeans -- IoC-3 Components and String Dependencies

Posted by n_alex on April 28, 2004 at 11:21 AM PDT

It boils down to this:

You can use Picocontainer's constructor-dependency-injector strategy to automatically pipe an object instance into an action component, with the understanding that once the action is executed, it will alter the state of its dependency objects. This is one of the core principles of the WARS style. So, you create an object, invoke the execute() method on it, and assume that the dependency object has been altered. This strategy makes good sense and works very well in most cases.

But what if the component's dependency is a String object?

I'm not positive, but I'd bet that this is a fairly common problem and with the rise of constructor-dependency-injector strategies will become more common. Assume for a moment that you can only pipe your string into a component by way of its constructor, and that its execute() method has a void return value. Of course, you could easily write a simple object that takes a String parameter and returns another String parameter, but it's a different object. But in my case, that is neither possible nor desirable.

I want to be able to pass a String into an object, tell that object to operate on it, and have my version of the String change in turn. I can do this with any other object, just not a String. Has this problem arisen in any of the various finite-state machines or other state-processing engines?

The obvious solution to this problem, then, is to wrap up the String in a simple component (I'm calling it StringBean). You can pass the wrapper object to the constructor (or method, in my simple example below).

I'm fine doing this, but I don't want to create a stupid dependency if I can help it. Can anyone suggest a different / better way to overcome this problem (excluding the unacceptable solutions listed above)? It's a tricky problem, because strings are "separate but equal" with other objects in Java.

(Here's a simple class with a main method to illustrate my point.)

public class StringTester {

    public static void main(String[] args) {
        String s = "Hello, World";
        System.out.println("Starting state: " + s);
        funk(s);
        System.out.println("Trial 1 -- ending state: " + s);
        System.out.println("--");

        StringBean b = new StringBean(s);
        soul(b);
        System.out.println("Trial 2 -- ending state: " + b);
    }

    // does not alter the state of the incoming object
    private static void funk(String s) {
        s = s.toUpperCase();
        System.out.println("in funk: " + s);
    }

    // alters the state of the incoming object
    private static void soul(StringBean b) {
        String s = b.toString();
        b.setString(s.toUpperCase());
    }

    private static class StringBean {
        private String s;
        private StringBean(String s) {
            this.s = s;
        }

        public String toString() {
            return this.s;
        }

        private void setString(String s) {
            this.s = s;
        }
    }
}
Related Topics >>