Once your classes are properly modified, you can test their new features. The objects will become versionable, that is you can make inquiries whether the object has been modified, created or deleted. The modification happens transparently, there should be no visible changement of the object's behaviour (after all, VOs shouldn't have any behaviour).
While it would be possible to do this by casting the object to its new interface "Versionable" to expose its API, the preferred method is to use the static methods of the helper class SmartAccess which does all this for you. An example for its usage:
TestVO test = new TestVO(); // reset version information SmartAccess.reset(test); // modify object test.setName("test"); // check for modification if (SmartAccess.isDirty(test)) { System.out.println("object has been modified"); }A call to the object's setter "setName" should change the object's state to "modified", as the setter will most certainly overwrite the field containing the name.
Other useful methods include:
For the full documentation, refer to the javadoc page: org.bsf.smartValueObject.SmartAccess.
In many cases your VO will contain a collection of other objects, normally implemented with a class of the Java collection framework.
Now, it would be interesting if you could track changes in these containers, e.g. know if there have been any additions or deletions in the container. If the object in the container has been modified (not deleted!) and is a versionable object, there is no need for further support by the library as it's already been taken care of by the bytecode modification.
But as deleted objects would be garbage collected, you have no way to "know" that the object is no longer in the container, except if you carry a copy of the old state around or implement custom containers to do this.
The modified transfer objects do this automatically for you: every time you have an assignment like
Collection c = new ArrayList();in your code, the assignment will be intercepted on runtime and replaced with a "smart" container. These are wrapper around common interfaces (java.util.Collection, Map, Set, List) that take care of the versioning.
The condition for this to work is that you assign only to interfaces, not to concrete types. Otherwise the interception will fail and you end up with a normal container.
The main difference with respect to the "normal" containers is that newly added objects get a 'created' flag while deleted objects are flagged as, 'deleted'. Once deleted they still remain in the container but are no longer visible to the application. That means all methods invoked on the container will behave like the objects had really been deleted.
Again, to get this 'hidden' information you need to use SmartAccess. It offers the following methods to work with smart containers:
SmartAccess.isSmartContainer(Object o); // checks if object is a smart container SmartAccess.isContainerModified(Object o); // checks if objects in the container have been modified SmartAccess.deletedIterator(Object o); // gets an iterator for all deleted objects SmartAccess.createdIterator(Object o); // gets an iterator for all added objects
In a client/server scenario the server can use this method to do a quick check if updates to the storage tier are necessary. The component which does this checks acts as a mediator between the versioned value objects and the backing storage.
back | index | next |