Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Original Data Verification before Update  RSS feed

 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I have an Entity Bean which is being updated. I introduced a small time delay in this code between getting the Entity Bean and Updating it.
During this time delay, I updated the same record through SQLplus. After the timeout, I found out that Entity Bean updated had overwritten over the update I made through SQLplus.
Is there a way to warn the client, if the record in the table has changed between the initial extract and update. I was under the impression that EJBs were handling this.

Thanks.
Peter.
 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I like the solution suggested by David Harkness here

http://www.coderanch.com/t/313390/EJB-JEE/java/transaction-several-request
But the only problem is that I will need to add that extra column in every table. Not sure how enthusiastic the DBA's will be to do this.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter Vennel:
Is there a way to warn the client, if the record in the table has changed between the initial extract and update. I was under the impression that EJBs were handling this.

What you're looking for is optimistic concurrency. Pessimistic concurrency involves blocking other threads/systems from updating the data you want to touch. In WebLogic, this is database concurrency. When the bean is loaded in a transaction, its row is locked in the database, blocking other updates until the transaction completes. This is useful when it is very likely that data contention will occur, and you can accept other threads being forced to wait in line.
In contrast, optimistic concurrency assumes that contention will be minimal. First, a version number or timestamp column is added to the database tables. When the bean is read, its version number is read as well. When the container (again, WebLogic has this functionality) attempts to update the bean, it will match the concurrency column against the value read in the where clause. If the update fails, it means that someone else modified the row (and the concurrency column) between the read and the update, and the container will throw an exception.
Note that this requires *all* systems that touch the data to update the concurrency column in the same manner. A version number column is easy as you just increment it without having to access the system clock and worry about clocks being in sync, etc.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter Vennel:
But the only problem is that I will need to add that extra column in every table. Not sure how enthusiastic the DBA's will be to do this.

If you have other systems updating that data, they will all need to be updated to use the same logic. If not, it's *much* easier.
One way to sell it to the DBAs is that by using optimistic concurrency, you can tell your container to cache the beans between transactions. This means that five updates from the same cluster node will only require one read. Without caching, each bean involved must be loaded for each transaction. It then comes down to an extra column per table (with the exact same definition) in exchange for less pounding on the database.
In our system, the database is decidedly the bottleneck, so it's a huge win.
 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks David.
But the situation for me here is that, I am migrating .net apps to J2EE. So the Database Schema is already in place. Adding extra column to all the tables will have repurcussion to all other systems touching it.
What I was looking is something like 'Isolation Level'.
Unfortunately, this is only for BMT. I have to explore what Weblogic offers for CMT.
Peter.
[ February 11, 2004: Message edited by: Peter Vennel ]
 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
YES!
Found the solution.
Weblogic had <transaction-isolation> tag whihc can take value of
"TransactionReadCommittedForUpdate" (for Oracle DB)
Though I do not like the idea of locking the record for updates, I can live with this.

Thanks David.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter Vennel:
But the situation for me here is that, I am migrating .net apps to J2EE. So the Database Schema is already in place. Adding extra column to all the tables will have repurcussion to all other systems touching it.

Yes, that's usually what kills optimistic concurrency as an option. When I started this project (running on WebLogic 7.0sp1, now sp4), I set it up to use CMP, CMR and CMT. You can specify isolation level with CMT, and I have it set to READ_COMMITTED. Before OptCon, I was using Database concurrency strategy. If I recall correctly, this locks the database row (Oracle 9.2) for the duration of the transaction.
I distinctly remember performing exactly the test you did, but when I did the update in SQL*Plus, it blocked until the Java code's transaction completed, telling me that the row was locked.
I just looked back over my previous code from August, and I don't actually specify the concurrency strategy nor transaction isolation levels. I use XDoclet to generate the deployment descriptors, and IIRC it defaults to "Database" and "READ_COMMITTED."
So I just read up on the WebLogic docs (EJB Concurrency Strategy) to refresh my memory. Everything above is mostly in line, but there's another option I forgot about. You can use optimistic concurrency without adding a column. Instead, all fields are compared against the row when the transaction is committed (probably by adding all the old values to the where clause).
Check Data for Validity with Optimistic Concurrency
You can configure the EJB container to validate an Optimistic bean's transaction data before committing the transaction, to verify that no data read or updated by the transaction has bean changed by another transaction. If it detects changed data, the EJB container rolls back the transaction.
Note: The EJB container does not validate Blob or Clob fields in a bean with Optimistic concurrency.

I'd suggest reading through that part of the docs a couple times. It seems that every time I reread it I find something new.
 
Kyle Brown
author
Ranch Hand
Posts: 3892
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not sure if it Weblogic supports it (WebSphere does, but don't know about Weblogic...) but another way of doing optimistic concurrency is through an overqualified update. When (for instance) you set up WebSphere to do that, it automatically does a very specific WHERE clause as part of its update where it compares every part of the EJB as it was originally read against the columns as they exist in the database.
It avoids having to add an extra column.
Kyle
 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Kyle & David.
Originally posted by Kyle Brown:

"When (for instance) you set up WebSphere to do that, it automatically does a very specific WHERE clause as part of its update where it compares every part of the EJB as it was originally read against the columns as they exist in the database."

Actually This is what I am looking for.

Originally posted by David Harkness:

You can use optimistic concurrency without adding a column. Instead, all fields are compared against the row when the transaction is committed (probably by adding all the old values to the where clause).

How is this done? Can you guide me through it.
I read again and ran into this from weblogic
Configure validity checking for a bean with Optimistic concurrency using the verify-columns and verify-rows elements in the table-name stanza for the bean in weblogic-cmp-jar.xml file.
Specify the concurrency mechanism for a bean by setting the concurrency-strategy element in the entity-cache stanza in weblogic-ejb-jar.xml. Because concurrency-strategy is defined at the bean level, different beans in the same application can use different concurrency strategies, as appropriate.

So I went ahead and modified my weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>Courses</ejb-name>
<entity-descriptor>
<entity-cache>
<concurrency-strategy>Optimistic</concurrency-strategy>
</entity-cache>
<persistence>
<persistence-use>
<type-identifier>WebLogic_CMP_RDBMS</type-identifier>
<type-version>6.0</type-version>
<type-storage>META-INF/weblogic-cmp-rdbms-jar.xml</type-storage>
</persistence-use>
</persistence>
<enable-dynamic-queries>True</enable-dynamic-queries>
</entity-descriptor>
<local-jndi-name>Courses</local-jndi-name>
</weblogic-enterprise-bean>

and weblogic-cmp-rdbms-jar.xml
<weblogic-rdbms-bean>
<ejb-name>Courses</ejb-name>
<data-source-name>jdbc/PFO3DB</data-source-name>
<table-map>
<table-name>COURSES</table-name>
<field-map>
<cmp-field>courseId</cmp-field>
<dbms-column>COURSE_ID</dbms-column>
</field-map>
<field-map>
<cmp-field>courseName</cmp-field>
<dbms-column>COURSE_NAME</dbms-column>
</field-map>
<field-map>
<cmp-field>currEnroll</cmp-field>
<dbms-column>CURR_ENROLL</dbms-column>
</field-map>
<field-map>
<cmp-field>fee</cmp-field>
<dbms-column>FEE</dbms-column>
</field-map>
<field-map>
<cmp-field>maxLimit</cmp-field>
<dbms-column>MAX_LIMIT</dbms-column>
</field-map>
<verify-rows>Modified</verify-rows>
<verify-columns>Modified</verify-columns>
</table-map>
</weblogic-rdbms-bean>

Then when I ran my code, which had time delay between the read and update. I started TOAD from outside and modified the same record that would be updated. Then I expected my code to throw exception, but it ran through and updated the record. Am I missing outsomething? Please let me know.
Thanks
Peter
[ February 12, 2004: Message edited by: Peter Vennel ]
[ February 12, 2004: Message edited by: Peter Vennel ]
 
Peter Vennel
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Found the problem.
weblogic-ejb-jar.xml needs the following line too after <concurrency-strategy>.
<cache-between-transactions>true</cache-between-transactions>
But this has not been mentioned anywhere.
Now Finally I get the error I prayed for
"[EJB:010143]Optimistic concurrency violation. Instance of bean 'Courses' with primary key 'CS999' was changed by another transaction.]"
Never been so happy before stumbling upon an error.
This way , i do not have to maintain any exclusive lock of record.
Peter.
[ February 12, 2004: Message edited by: Peter Vennel ]
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter Vennel:
Found the problem.

Excellent! Boy do I know that wonderful feeling.
<cache-between-transactions>true</cache-between-transactions>

Ah, I think I misunderstood your original test. I thought you were doing
  • Begin transaction
  • Read bean
  • Sleep
  • Modify bean
  • Commit (expect OptimisticConcurrencyException)

  • If this *is* what you're doing, I don't see how caching between transactions should make the difference since this is all happening inside a single transaction. Just reread that section of the docs -- I wonder if the following is why you need to cache:
    Optimistic transactions read using a local transaction to avoid holding locks until the end of the transaction. However, optimistic transactions write using the current JTA transaction so that the updates can be rolled back, if necessary.

    Does this mean that if you *don't* cache between transactions, the bean will be read *again* when enlisted in the JTA transaction?
    Are you instead starting the transaction right before you modify the bean, or as a consequence of modifying the bean (CMT)? I guess it's not too important since you got it working.
    One suggestion though: XDoclet. Instead of deployment descriptors, this is how I make my beans use the various WebLogic features:

    XDoclet then generates the appropriate home and local/remote interfaces and all of the deployment descriptors. No more keeping the beans in sync with all the other files.
     
    Peter Vennel
    Ranch Hand
    Posts: 46
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Originally posted by David Harkness:

    If this *is* what you're doing, I don't see how caching between transactions should make the difference since this is all happening inside a single transaction.

    You had assumed it right. I am calling the Session Facde from my thin Client. The code snippet is as below :


    I think that it needs to cache the original value it got. So when finally updating, it will have pre-update and post-update value for that entity.
    That is why is caching is not set, it just ignores it. I may be wrong. This is just my assumption. I am newbie to EJB.
    Are you instead starting the transaction right before you modify the bean, or as a consequence of modifying the bean (CMT)?

    I am relying on Container Managed Transaction (CMT). So the transaction ends before the return of the method in my Session Bean (Stateless). I am not setting any transaction attributes in my client. The client is calling in an Unspecified context. Also the transaction attributes for all the EJBs were set to 'Required' by default while using JBuilder EJB Designer.
    I am now trying to start Transaction from my client call and I let you know how it goes.
    One suggestion though: XDoclet. Instead of deployment descriptors, this is how I make my beans use the various WebLogic features.

    I am using JBuilder X Enterprise version. It is an awesome product. It integrates everything and also deployes them on to the server right from my IDE. . The EJB Designer is the most coolest feature I found in it, that creates me home, remote and bean from the Table. And it also writes to all the relevant xml file.
    Peter.
    [ February 12, 2004: Message edited by: Peter Vennel ]
     
    Peter Vennel
    Ranch Hand
    Posts: 46
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It worked without the element
    <cache-between-transactions>true</cache-between-transactions>
    The new code with transaction beginning in client code is as below :

    Peter.
    [ February 12, 2004: Message edited by: Peter Vennel ]
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!