Hi Noc2,
according to your description I can not see anything that you may be
doing wrong. But there is one problem that I faced myself sometime ago.
Let's assume you set your start timestamp as follows:
perf.setStart(new Date());
The start timestamp then holds a value that has millisecond resolution.
If you store this value to a database column that has only second
resolution the milliseconds will not be contained in the database. If
you try to update this object in another transaction Castor will load
the object from the database and compares it with the cached one. At
this time Castor recognizes that the start timestamp form the database
is not the same as the one of the object in cache because the
milliseconds are missing. This will lead to a ObjectModifiedException as
seen by you.
Having said that this may also happen with other datatypes (e.g. if you
store a 30 char string into a database field with only 25 chars).
Regards
Ralf
Noc2 schrieb:
> Hello everybody,
>
> I am back with a new problem, a real mindcracker for me. As usual, it is
> possible that this problem is as easy as cake, then i will feel stupid
> again, but as it is now (with my limited knowledge) i cant seem to find a
> solution.
>
> The situation is as following:
>
> check the next piece of mapping:
>
> <<<<<<<<<<<<<<<<<<<mapping>>>>>>>>>>>>>>>>
>
> <field name="start" type="date">
> <sql name="start" type="timestamp" />
> </field>
>
> <field name="stop" type="date">
> <sql name="stop" type="timestamp" />
> </field>
>
> <<<<<<<<<<<<<<<<<< end of mapping >>>>>>>>>>>
>
> As you can see, i am trying to "convert" java date obj into a timestamp
> object.
> This piece of mapping tries to map a Performance Object, the code following
> here:
>
> *********************** start of code **************************
>
> public class Performance implements TimeStampable {
>
> private int performanceID;
> private int userID;
> private int activityID;
> private Date start;
> private Date stop;
>
> private long timestamp = 0;
>
> public long jdoGetTimeStamp(){
> return timestamp;
> }
>
> public void jdoSetTimeStamp(long timestamp){
> this.timestamp = timestamp;
> }
>
>
> public int getUserID() {
> return userID;
> }
> public void setUserID(int userID) {
> this.userID = userID;
> }
> public int getActivityID() {
> return activityID;
> }
> public void setActivityID(int activityID) {
> this.activityID = activityID;
> }
> public Date getStart() {
> return start;
> }
> public void setStart(Date start) {
> this.start = start;
> }
> public Date getStop() {
> return stop;
> }
> public void setStop(Date stop) {
> this.stop = stop;
> }
> public int getPerformanceID() {
> return performanceID;
> }
> public void setPerformanceID(int performanceID) {
> this.performanceID = performanceID;
> }
> }
>
> ************************** end of code ***************************
>
> As you all can see, not much about it.
>
> I recently solved the problems i had with caching and long transactions,
> everything worked perfectly, until i tried to create and update Performance
> objects in long transactions.
>
> The scenario is as following: i create a performance object to track the
> start of some activity. Due to database restrictions (mysql), it is
> impossible to have a timestamp entry that is null (this might have nothing
> to do with the problem but i think its better to just tell everything).
>
> Ofcourse i also need to know when the activity stops, so i perform an update
> on the Performance object when the activity stops, and i would then like to
> create a new Performance object for the next Activity.
>
> But on the update, i get the following Exception and errormessage:
>
> org.exolab.castor.jdo.ObjectModifiedException: Invalid object timestamp
> detected.
>
> Now, to me, this looks very strange. ObjectModifiedException is thrown when
> there is a concurrency problem, more accurate, when one transaction is
> modifying an entry used by another transaction.
> In my case, this is not really possible, because every single operation i
> perform on the database is a transaction that has been committed. To prove
> this, i ll give the code i use to update.
>
> ************** start of code *************
> public void update(Object updatedObject) {
> try {
> db.begin();
>
> db.update(updatedObject);
>
> logger.info("UPDATE COMPLETED");
>
> db.commit();
>
> } catch (PersistenceException e) {
> logger.fatal("PersistanceException : " +
> e.getMessage());
> e.printStackTrace();
> }
> }
> ********************* end of code **************
> In the application, when i create the currentPerformanceObject, it has no
> ID. I let MySql create an auto increasing number for that. So i figured i
> might be making my own object a dirty one, because castor isnt aware of the
> change in the database. So logically i tried to set the the dirty attribute
> in the mappingfile to ingnore, but with no effect (this also means that my
> theory about the ID is not correct as well).
>
> I dont have a clue what could be wrong. To complete this post, i ll add the
> pieces of code where all this stuff happens.
>
> ********************** start of code *********************
>
> activityList.getList().addSelectionListener(new
> SelectionListener(){
> public void widgetSelected(SelectionEvent event){
> MessageBox msgbox = new
> MessageBox(site.getShell(),SWT.ICON_INFORMATION|SWT.YES|SWT.NO);
> msgbox.setMessage("Are you sure you wish to
> start this activity?");
> int msg = msgbox.open();
> if(msg == SWT.YES){
>
> if(currentPerformance != null){
> endCurrentPerformance();
> }
> currentActivity =
> (Activity)activityList.getElementAt(activityList.getList().getSelectionIndex());
>
> status.setText(statusText+currentActivity.getName());
>
> logActivity();
>
> }
> }
>
>
> private void logActivity(){
> currentPerformance = new Performance();
>
> currentPerformance.setActivityID(currentActivity.getActivityID());
> currentPerformance.setUserID(Application.conn.getCurrentUser());
> currentPerformance.setStart(new Date());
> currentPerformance.setStop(null);
>
>
> Application.conn.getAccess().createPerformance(currentPerformance);
>
> System.out.println("THE TIMESTAMP OF THE PERFORMANCE OBJECT:
> "+currentPerformance.jdoGetTimeStamp());
> }
>
> private void endCurrentPerformance(){
> currentPerformance.setStop(new Date());
>
> System.out.println("THE TIMESTAMP OF THE PERFORMANCE OBJECT
> WHEN UPDATING:
> "+currentPerformance.jdoGetTimeStamp());
>
>
> Application.conn.getAccess().updatePerformance(currentPerformance);
>
> System.out.println("UPDATE COMPLETED");
> }
>
> ******************** end of code **********************
>
> As you can see, all the activities are contained in a listviewer. When i
> click an activity, i want to make sure that the user didnt accidently
> clicked it, so i ask to confirm with a dialogbox. If there is a
> currentPerformance, i update it in 'endCurrentPerformance', if not, i just
> create a new Performance in 'logActivity'.
>
> In my opinion this is a very strange situation. The errormessage indicates
> that there is an invalid object timestamp. I know that when i create a new
> object, the timestamp has to be 0, as an indication that the object is a new
> one. Castor changes the timestamp, so the object will not be forgotten.
>
> I compare the timestamp value with the original one just before updating,
> and they are exactly the same.
>
> In my application i use the same variable name to instantiate a new
> Performance. But since instantiating means assigning a new reference to the
> variable, it can not be that the new object has the timestamp of the object
> that was previously referenced by the same variable.
>
> Any help on this matter would be very much appreciated.
>
> greetings,
>
> Noc2
--
Syscon Ingenieurbüro für Meß- und Datentechnik GmbH
Ralf Joachim
Raiffeisenstraße 11
72127 Kusterdingen
Germany
Tel. +49 7071 3690 52
Mobil: +49 173 9630135
Fax +49 7071 3690 98
Internet: www.syscon.eu
E-Mail: [EMAIL PROTECTED]
Sitz der Gesellschaft: D-72127 Kusterdingen
Registereintrag: Amtsgericht Stuttgart, HRB 382295
Geschäftsleitung: Jens Joachim, Ralf Joachim
---------------------------------------------------------------------
To unsubscribe from this list please visit:
http://xircles.codehaus.org/manage_email