views:

692

answers:

6

Hi All, I am involved in this project where we are building on good bit of legacy code. I have a particular situation about one big java bean object which has to be transferred over wire. So my first thought was to make it immutable and serializable to do the trick .At this point I am faced with a few difficult choices :-

1> Ideally I want some way to automatically generate an immutable, serializable version of this class. I dont have the scope to refactor or alter this class in any way and i would really really hate to have to copy paste the class with a different name ??

2> Assuming that i gave up on 1 i.e i actually chose to duplicate code of the HUGE javabean class , i still will be in the unsavoury situation of having to write a constructor with some 20-25 parameters to make this class immutable. what is a better way to make a class immutable other than constructor injection ??

Thanks and Regards,

+3  A: 

To make it truly immutable, you need to initialize the members at construction time.

One way (and I ain't sayin' it's pretty!) to do this and avoid a huge parameter list in the constructor is to have a mutable type that has the same properties. Set the the properties on the mutable type one at a time, through "setters", then pass the mutable object to the constructor of the immutable type as a single argument. The immutable object then copies the properties from the mutable source to it's own (final) members.

You might also consider "effective immutability". That is, even though immutability is not enforced by the system, you use coding practices that clearly separate the initialization phase from the usage phase. After all, immutability is not required for serialization.

You can take this a step further, creating an implementation-hiding wrapper for the interface that doesn't expose the properties of the implementation. The wrapper only implements the methods in the interface, by delegating to the "real" implementation. The setters and getters from the implementation are not present in the wrapper. This will stop clients from simply down-casting from the interface to the implementation class and manipulating the properties.

erickson
+1  A: 

20-25 properties is not huge for a one off, particularly if you are using a half-decent editor.

If you already have a mutable instance when constructing the immutable version, just pass that to the constructor.

If you want to be really evil hacky, use java.beans to create a serialisable Map for the mutable class or subclass implementing Externalizable. Alternatively you could use java.beans XML serialisation (the XML than can be sent over Java serialisation...).

Tom Hawtin - tackline
A: 

Step 1: Create a new class and give it instance variables with the exact same names as the instance variables of your 'big java bean object'. That new class should not have setters (but getters only) to make it immutable.

Step 2: Use Apache Commons BeanUtils.copyProperties to copy all the properties (i.e. instance variables) from your 'big java bean object' to your new object.

Aries McRae
A: 

A few ideas:

Protected setters and factory methods You can define beans with protected setter methods and in the same package, a factory class that takes all the parameters and calls those setters. The bean is immutable outside that package. To enforce this, be sure to seal your jar so end users cannot create new classes in the same package.

Note: You can use my JavaDude Bean annotations to make the creation simpler: http://code.google.com/p/javadude/wiki/Annotations

For example:

@Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
    properties={
        @Property(name="name"),
        @Property(name="age", type=int.class)
    })
public class Person extends PersonGen {
}

Creating getters and a constructor in eclipse

Eclipse has some nice tools to make this fast:

  1. Create the bean class
  2. Add the fields you want
  3. Right-click in the editor window
  4. Choose Source->Generate Getters and Setters
  5. Press the "Select getters" button
  6. Press ok
  7. Right-click in the editor window
  8. Choose Source->Generate Constructors from fields
  9. Pick and order the fields you want in the constructor
  10. Press ok

Immutability Decorator

Another idea is to define your bean with getters and setters (you can use the above technique but include setters), then you can create a wrapper class for it that only has the getters.

Scott Stanchfield
A: 

Joshua Bloch's "Effective Java" illustrates the Builder pattern, where simple Builder objects are used to construct a complex object with a long constructor argument list. I'd recommend it.

http://www.drdobbs.com/java/208403883;jsessionid=PJWS41F5DJ4QRQE1GHRSKH4ATMY32JVN?pgno=2

Patrick van Kann
A: 

What about a simple read only interface cotaining the getters?

If the bean class is your own, let it simpley implement the interface and use just the interface after creation.

If you have no control over the bean class, you can also create a getter interface and implement it by creating a proxy for the getter interface with an invokation handler delegating all method calls to the bean.

Arne Burmeister