aspose file tools*
The moose likes Java in General and the fly likes Listening for a state change of a POJO Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Listening for a state change of a POJO" Watch "Listening for a state change of a POJO" New topic
Author

Listening for a state change of a POJO

Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Assume that we have a POJO class (just like a bean) as below:



And another class change the currentState by directly access the field:



In this case the currentState will be changed. But assume that MyPojo class needs to track this change on it's attribute, and do something. Just as below:



As a pojo, I know that we cannot track this change of the currentState variable by another method like currentStateChanged(). But would it be possible, if we use Java Reflection API here? Can we use the reflection api for a purpose like this?
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

Hi Treimin,

I'd recommend not using such an approach.

Firstly a simple solution would be to ensure that the state can only be changed by a public setter method. In that setter method you could perform extra logic that confirms whether the state has changed (if new value is not equal to current value then state has changed). There are other more sophisticated techniques as well.

Also, see Observer Pattern


Cheers, Martijn - Blog,
Twitter, PCGen, Ikasan, My The Well-Grounded Java Developer book!,
My start-up.
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Martijn Verburg wrote:
Firstly a simple solution would be to ensure that the state can only be changed by a public setter method. In that setter method you could perform extra logic that confirms whether the state has changed (if new value is not equal to current value then state has changed).


Aaah! I thought someone will tell this for me
I know that (using setters) well, but what I expect from this question is what I said before exactly. Can we use that java reflection api or some other 'advanced-technology' for that purpose?
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42648
    
  65
What are you trying to achieve by using something complicated, when simple solutions are available?


Ping & DNS - my free Android networking tools app
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Ulf Dittmer wrote:What are you trying to achieve by using something complicated, when simple solutions are available?


Yes I know; but I'm not going to build a real application now. I just like to learn that.
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

Well my advice is that for 'Real Applications' the simplest solution is definitely the best! The Observer pattern I mentioned effectively formalises the simple solution I suggested above. Many design patterns are like this, fancy wrapper names around mostly simple common solutions
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Treimin Clark wrote:
Yes I know; but I'm not going to build a real application now. I just like to learn that.
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

Oh, silly me, sorry I missed the not! Other techniques could involve the Listener Pattern (used in UI development) and/or a background thread monitoring that object...
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Using a background thread is a good idea for this. But assume that we have a lot of instances of the MyPojo class. If we have to check the state of each objects rapidly, by using (a) thread (even a low-priority thread), it would definitely cause a performance hit. Because the thread have to check the state of the object, even though it's state has been either changed or not.

Instead of using threads, how if we can 'listen' (like in Lsitener classes) for the state change of an object?

As I know, Java Reflection API can be used for some 'miracle' tasks
Can we use it for this task?

If not, what else we can use?
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

This starts to get beyond my knowledge, I think you could use Reflections (hideously expensive), the Listener Pattern does use low priority background thread IIRC, that's about all I've got (I'd still strongly recommend the Observer pattern).
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Martijn Verburg wrote:I'd still strongly recommend the Observer pattern.


Aaah! You again


Thanks Martijin for providing your valuable comments.

Shall we move this to another forum, relating to the reflection api? To which forum? To the "Other API" forum? Or,.... where? I couldn't find.
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

I'd start a new thread in this forum with your Reflection specific question .
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42648
    
  65
I'd start a new thread in this forum with your Reflection specific question

Or you could just take it from Martijn (and myself) that using reflection for this is not a good idea (I'm not even sure how you propose to use it in this case - if those fields can be set directly, then they can be read directly; what's the point of using reflection?).
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Ulf Dittmer wrote:
Or you could just take it from Martijn (and myself) that using reflection for this is not a good idea (I'm not even sure how you propose to use it in this case - if those fields can be set directly, then they can be read directly; what's the point of using reflection?).


You didn't understand the scenario. Assume that we have a class named "EntityManager", which can receive any kind of objects by it's EntityManager.persist(Object) method. After an object is added to the EntityManager, EntityManager needs to do 'something' when the state of that Object is changed. The EntityManager doesn't know anything (method names/field names) about that object. So how that EntityManager listen for that Object's state change? That is the point why I'm looking for the Reflection API.
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

Well, I'd design it so that the Object needs to inform the Entity Manager! (You could do it the otehr way around but basically you'r talking about a pollign monitor, which can be resource intensive).

I'd design in that the Entity Manager is aware of all of its objects (a list of ids if you will), and that each object is aware of its Entity Manager (make all objects inherit from a base class that has the Entity Manager if you want to avoid repeating that declaration). When an object is changed, e.g. Via it's public setter method, check to see if the state has been changed and if it has then notify the Entity Manager.

Hope that helps!
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Martijn Verburg wrote:Well, I'd design it so that the Object needs to inform the Entity Manager!


No, it's not possible here. An object which is passed to the EntityManager MUST be a simple bean class (but we can use annotations, if needed). But that object cannot implement a class, or do 'another' thing.

For an example



An instance of this class should be passed to the EntityManager as below:




After that EntityManager is responsible to do somthing, when a variable of MyDetails is changed.

Eg:


When I do that, the EntityManager must track it and do it's 'task'.

What I need to know is, how to code the EnityManager (or the Entity annotation if needed) for this purpose. However we cannot tell the user (creator of MyDetails class) to implement any other syntax, other than what I used in above example.

(Remember, EntityManager doesn't know anything about the variable/method structure of MyDetails, because the user can pass any Object to the Em)
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

Another approach is to have a 2nd thread acting as an Entity Monitor, it checks every x seconds if state has changed on an object and if it has then it informs the Entity Manger. Not this could be an expensive operation (checking each object, holding onto a reference to each object etc, etc).
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Martijn Verburg wrote:Another approach is to have a 2nd thread acting as an Entity Monitor, it checks every x seconds if state has changed on an object and if it has then it informs the Entity Manger. Not this could be an expensive operation (checking each object, holding onto a reference to each object etc, etc).


This is impossible, because the 2nd thread doesn't know about variables/methods in the object that is passed to the EntityManager.
Martijn Verburg
author
Bartender

Joined: Jun 24, 2003
Posts: 3274
    
    5

The 2nd thread would need to have access to a Map of all of the objects yes (this is why it's potentially inefficient).
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18911
    
    8

If I'm not mistaken, the products which actually do this sort of thing (caching applications and the like) use byte-code modification. In other words they modify the byte code of the entity's class so that changes to the entity's properties are recorded as they happen and communicated immediately to the manager. At least, that's how I imagine they work, I don't know anything about them in detail.
Treimin Clark
Ranch Hand

Joined: Nov 12, 2008
Posts: 757
Martijn Verburg wrote:The 2nd thread would need to have access to a Map of all of the objects yes (this is why it's potentially inefficient).


Do you think that I'm going to make an impossible application?

Well, the EntityManager application which I mentioned above is a real world application (java class) in the EJB Object/Relational mapping. It can persist any entity class to it. And then, the changes made to the entity will be written to the database automatically.

I didn't post this thread in neither object/relational mapping forum or EJB forum, because I need to know "how" EntityManager is implemented by using Java. (So there are nothing talking about EJB or O/R mapping here).


If I tell you again,

  • The EntityManager class doesn't know anything about the fields of passed object.
  • But finally, EntityManager should read the variables in that entity. I wan't to know how EntityManager do that?
  • The passed object should be a simple class, only with variables, no methods, no statement.
  • We cannot tell the user (programmer of the passed object) to implement anything else.
  • But, the only thing we can tell to him is, that class (here, MyDetails) should be annotate with the @Entity annotation, as I mentioned above in my code. But that @Entity annotation doesn't know anything about the MyDetails class, or it's fields.
  • I know that this can NEVER be done by using general Java Object Oriented Concepts.
  • But it is not impossible, because this is a real-world situation.
  • I highly believe that EntityManager uses Java Reflection api or any other 'miracle' api to do this task.


  • Can someone imagine a possible implementation now?
    Martijn Verburg
    author
    Bartender

    Joined: Jun 24, 2003
    Posts: 3274
        
        5

    Oh I see now!

    See this article on how the Java Entity Manager works behind the scenes. It's similar to how Hibernate deals with this situation as well IIRC. The caching/management of entities in memory is where these things really excel (or fail). My simple hold all objects in memory would be a big performance hit. These guys do something similar but are a lot cleverer about only holding onto what is strictly necessary. Interesting reading all round (almost as bad as the JCA spec ;p)
    Treimin Clark
    Ranch Hand

    Joined: Nov 12, 2008
    Posts: 757
    Cannot go to the link which you provided. The HTTP Error 110 (SSL Authentication Certification Needed) is thrown.
    Ernest Friedman-Hill
    author and iconoclast
    Marshal

    Joined: Jul 08, 2003
    Posts: 24187
        
      34

    Treimin Clark wrote:

    Can someone imagine a possible implementation now?


    There is no way, using Reflection or anything else, to be notified when a member variable changes. No way. Nothing. Zilch. Zip. Nada. Nein.

    The only way to know if a non-private member variable of an object has been changed is to store the value at some known time, and periodically check the value against the original to see if it's changed.

    There is no way to be notified asynchronously. The only way to be notified soon after any arbitrary change is to check often. Yes, this is inefficient, so that it's rarely (if ever) implemented.

    Instead, what Hibernate and JPA actually do is only look at the data in the objects when they actually need to. The database is never kept up to date whenever any attribute is changed; objects are flushed to the database only at specific, well-defined times, and these are the times at which the objects will be examined.


    [Jess in Action][AskingGoodQuestions]
    Steve Luke
    Bartender

    Joined: Jan 28, 2003
    Posts: 4181
        
      21

    Treimin Clark wrote:Do you think that I'm going to make an impossible application?


    I don't think that is what Martijn was saying, just that it would be inefficient, not impossible.

    Well, the EntityManager application which I mentioned above is a real world application (java class) in the EJB Object/Relational mapping. It can persist any entity class to it. And then, the changes made to the entity will be written to the database automatically.


    The EJB EntityManager behaves much differently than what you have described above. Above you ask about 'tracking changes' and calling 'currentStateChanged' methods when the value changes. These are (near) real time affects that require regular monitoring of the resource. An OR persistence layer only needs to know about the state of the data at the time of commit, which is a lot simpler. It doesn't need to know all the changes made and the interim values, just the value when the data is being sent to the database. This means it doesn't need to constantly monitor the entity. My guess is that it does use Reflection to read the values, but it would not need an underlying thread to monitor those values. It just uses it at the point of committing data.

    I didn't post this thread in neither object/relational mapping forum or EJB forum, because I need to know "how" EntityManager is implemented by using Java. (So there are nothing talking about EJB or O/R mapping here).


    The question as originally asked - to track changes and call 'currentStateChanged' methods when the value has changed is possible (yes using reflection) by using a thread to monitor the values to be watched. This operation would be resource intensive, inefficient, and would be woefully poor at scaling to lots of managed entities.

    The question as relating to O/R persistence is possible and scalable - though potentially slow - since the reflection wouldn't be an on-going process, objects are able to be freed from management in a meaningful time period, and there would be no thread potentially eating all your resources trying to determine if values have changed.

    If I tell you again,


    Just so you know, you are not repeating yourself here. You are completely changing the context of your question when you start to refer to the entity manager as being part of an O/R persistence layer.
  • I highly believe that EntityManager uses Java Reflection api or any other 'miracle' api to do this task.


  • Reflection is not a miracle api, nor do I believe any miracle APIs exist. You would probably do well to study it so you understand how it works so as not to think of it as miraculous.

    Steve
    Treimin Clark
    Ranch Hand

    Joined: Nov 12, 2008
    Posts: 757
    Ernest Friedman-Hill wrote:
    Instead, what Hibernate and JPA actually do is only look at the data in the objects when they actually need to.


    Oh! I understood. JPA looks at the database for the field names, and then invoke them from the entity. For an example, if there was a field name "ADDRESS" in the database, the JPA will call to the getAddress() method on the entity when needed. Am I correct?

    If it is, to implement that, JPA will automatically write a .java file implicitly including the getAddress() method, automatically and implicitly compile it and execute it to get the "address" from the entity (Just like JSP does). Is this correct? Otherwise, how do it invoke the getAddress() method on the entity?
    Ernest Friedman-Hill
    author and iconoclast
    Marshal

    Joined: Jul 08, 2003
    Posts: 24187
        
      34

    Treimin Clark wrote:
    If it is, to implement that, JPA will automatically write a .java file implicitly including the getAddress() method, automatically and implicitly compile it and execute it to get the "address" from the entity (Just like JSP does). Is this correct? Otherwise, how do it invoke the getAddress() method on the entity?


    It could generate and compile Java source, or generate bytecodes directly; or it could use reflection. Reflection can be used to call methods whose names you find out only at runtime, or access variables at runtime. It can not be used to get automatic notification when a variable changes -- which is what I thought you were asking about. All it can do is read the value of a variable, when you ask it to.
    Treimin Clark
    Ranch Hand

    Joined: Nov 12, 2008
    Posts: 757
    Ernest Friedman-Hill wrote:
    It could generate and compile Java source, or generate bytecodes directly; or it could use reflection. Reflection can be used to call methods whose names you find out only at runtime, or access variables at runtime. It can not be used to get automatic notification when a variable changes -- which is what I thought you were asking about. All it can do is read the value of a variable, when you ask it to.


    Many thanks Ernest, I got what I need.

    Thanks to Martijn, for spending your valuable time to help me.

     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Listening for a state change of a POJO