Annotations Observed

Hi all,

I have a situation where I feel the need of combining Annotations and the Observer pattern. I would like to record field changes on an Object. So I decided to use the Observer pattern this way:

class PersonObserverimplements Observer

{

private List<String> changedFields =new ArrayList<String>();

publicvoid update(Observable obs, Object args)

{

changedFields.add(args.toString());

}

public List<String> getChangedFields()

{

return changedFields;

}

}

class Personextends Observable

{

//class instances

publicvoid setName(String val)

{

this.name = val;

setChanged();

notifyObservers("name");

}

publicvoid setId(String val)

{

this.id = val;

setChanged();

notifyObservers("id");

}

//A lot more fields are set here with the 'setChanged' and the 'notify'

}

As you can see if my Person object contains some 40 fields it would be very easy to omit the call to setChanged. Besides, I'd like to come up with an API that would force consumer to implement this pattern. That's when I thought of Annotations. I thought if I could annotate each of the setters in a way that if one is called at runtime, then the changed flag would be set to TRUE and somehow the observer would record the field change. So far I can only find the methods that are annotated as "Changeable" through Reflections but if they're not actually called at all, I run the risk of recording an unchanged value.

I hope this made a little sense. If any of you have encountered this before or has an idea of a workaround, please let me know.

Thanks a bunch

[2643 byte] By [transient_mana] at [2007-11-27 11:44:59]
# 1

Look at Spring AOP, it is extremely powerful but simpler than AspectJ and you can write aspects using the AspectJ annotation style if you want. You do not need to change your code at all, you would make Person (for example) a Spring bean so that it is managed by the Spring container and configure that all calls to it are routed through the AOP proxy.

YoGeea at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

Thanks for the response,

My application is currently running on a different framework. I doubt architects would be keen to the idea of introducing other frameworks especially for just monitoring changes. I was hoping to find a mechanism to determine if a "setter" has been called through reflections and annotations. But I guess the real question boils down to how to know if a method on the object has been called. It seems like the Observer would do something like that but hopefully this isnt the only way.

Thanks

transient_mana at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

> Thanks for the response,

> My application is currently running on a different

> framework. I doubt architects would be keen to the

> idea of introducing other frameworks especially for

> just monitoring changes.

That's just a mindset. Calling everything a "framework" invariably leads to this happening, but Spring isn't a framework as such, it's very modular. To utilize it's AOP you'd only need the core IoC container (to configure things) and the AOP module itself, neither of which are particularly heavyweight

> I was hoping to find a

> mechanism to determine if a "setter" has been called

> through reflections and annotations.

There are a few alternatives. You could roll your own AOP code specific to this problem, farily easily but it won't be any lighter than Spring AOP, and certainly not as complete or easy to use. All you're after is a dynamic proxy around whichever objects you're monitoring, and that's all Spring AOP is anyway, with the tiny overhead of the IoC container to make configuring it dead simple. On top of that, the only code change you'd need to make would be a small modification to however you start your application, in order to kick off Spring configuration, and that's literally a couple of lines of code. It would take virtually no effort at all to give Spring a try. If I was doing this, I'd reach for Spring, definately

The problem with your annotations idea is it's far from transparent. You'd need to be making code changes all over the place. By leveraging Spring, you do it all declaratively, in (typically) XML configuration, with the couple of lines to kick things off as I mentioned

georgemca at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> As you can see if my Person object contains some 40

> fields it would be very easy to omit the call to

> setChanged.

It would be straightforward to auto generate your Person object.

> Besides, I'd like to come up with an API

> that would force consumer to implement this pattern.

I'm not clear on what you mean by this ? Are you expecting them to build objects like Person that will plug into something your framework. Or do you expect them to use yours ?

> ... the setters in a way that if

> one is called at runtime, then the changed flag would

> be set to TRUE and somehow the observer would record

> the field change.

> ...

> if they're not actually called at

> all, I run the risk of recording an unchanged value.

Why can't you use classic dirty flagging ?

MartinS.a at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

Or what about this ?

public void set(String object, String value)

{

this.name = value;

setChanged();

notifyObservers( object );

}

public void setName(String value)

{

set(this.name, value ) ;

}

public void setId(String value)

{

set(this.id,value);

}

}

MartinS.a at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

public abstract class BusinessEntityInstance {

private Map attributes = new HashMap();

private List listeners = new ArrayList();

protected void setAttribute(String attributeName, Object value) {

this.attributes.put(attributeName, value);

this.notifyListeners();

}

protected Object getAttribute(String attributeName) {

return this.attributes.get(attributeName);

}

private void notifyListeners() {

//notify listeners...

}

public void addAttributeListener(...) {

//...

}

public void removeAttributeListener(...) {

//...

}

}

public class Person extends BusinessEntityInstance {

public static final String NAME_ATTRIBUTE = name;

public void setName(String name); {

this.setAttribute(NAME_ATTRIBUTE, name);

}

}

jfreebsda at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

> Or what about this ?

> > public void set(String object, String value)

> {

> this.name = value;

> setChanged();

> notifyObservers( object );

> }

> public void setName(String value)

> {

> set(this.name, value ) ;

> }

>

> public void setId(String value)

> {

> set(this.id,value);

> }

> }

>

An enormous amount of boilerplate, though. Can you imagine going through every single method and working out if it needed monitoring, then putting it all in? You're bound to get some of it wrong. Then you have to keep adding that stuff to new code, as it's written, and it bloats every class, annoys programmers for having to remember to do it and invariably gets forgotten sometimes. Code that is only partly updated is at least as worthless as code that wasn't at all - you can't trust the results

Monitoring code has nothing to do with any particular problem domain, it shouldn't need to be written into production code at all. This is a classic cross-cutting concern, and as such a prime candidate for a sprinkling of aspect-oriented programming. Spring AOP - or your own equivalent, done properly - will allow it to be added to an existing codebase with virtually no effort at all

georgemca at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

For monitoring applications and opimization efforts, the leader is AppSight. See for yourself:

http://www.identify.com/

GhostRadioTwoa at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

Thanks all for the useful suggestions. I see that Spring AOP is probably the best way to go although I really like jfreebsd's and MartinS's approach. Unfortunately for AOP advocates, configuration files for this project have become a "no-no". One more XML and architects will freak out. I am not so sure why. So I'll probably keep it simple and combine somehow jfreebsd's and MartinS's method to both get rid off the repetition and force the implementation of the notifiers. Thanks much

transient_mana at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 10

> Thanks all for the useful suggestions. I see that

> Spring AOP is probably the best way to go although I

> really like jfreebsd's and MartinS's

> approach. Unfortunately for AOP advocates,

> configuration files for this project have become a

> "no-no". One more XML and architects will freak out.

> I am not so sure why. So I'll probably keep it simple

> and combine somehow jfreebsd's and

> MartinS's method to both get rid off the

> repetition and force the implementation of the

> notifiers. Thanks much

Odd attitude from your "architects"! Do inform them that the solution you're being forced to use will take quite some time to put in place, pollute your codebase with unnecessary code, slow your application down forever and introduce bugs for the rest of the application's lifecycle though

You could still roll your own AOP solution using dynamic proxies, fairly easily, and provide a much neater solution than forcing classes to implement an interface that has nothing to do with their intended purpose. CGLIB or ASM will help you proxy classes as well as interfaces

georgemca at 2007-7-29 17:59:12 > top of Java-index,Other Topics,Patterns & OO Design...