i'm trying to use this Versioning EJB so that i can use the caching in a Optimistic fashion
But i have some questions
I have a SessionFacade followed by and CMP kind of architecture
Imagine a client ask for a CMP to the SessionBean, i return a DTO with this information. Then the client wants to do an Update, he sends it to the SessionBean, that will look for the CMP (doing a findByPrimaryKey) at this time, all my information could have been compromised, because the information i got from the Database and the information i have on the DTO is potentially different.
Using version consistency i cant access the Version Column, so i can't verify if the version is correct when the SessionBean get the CMP (to do the update)
Version consistency will be good for me because i'm in a clustered enviornment, so i know that if someone in the other server changed something in the Database, the CMP will not allow me to update the info using and old bean. So i need this Version Consistency
I'm faced with an option of having Version Consistency for Clustered Enviornment, and a second version column so that i can check consistency in the call between client and CMP
Originally posted by Safin Ahmed: Version consistency will be good for me because i'm in a clustered enviornment, so i know that if someone in the other server changed something in the Database, the CMP will not allow me to update the info using and old bean. So i need this Version Consistency
Just to reiterate what i said before in case I wasn't clear or you didn't see the previous response, I can imagine how clustering *might* mean you are in a situation that would suggest VC could be useful, but only if you find you have very intense lock contention. Clustered solutions have their own ways of propagating information and syncing up with the database, VC is not a required technology to make that happen nor make it efficient. Think in terms of Amazon.com at Christmas, or some very broadly distributed application that can't even use the normal approaches to transactionality.
VC-like approaches have their place, but they can make dealing with relationships between tables horrifically complex. I've seen VC-based systems that have only a fraction of the throughput of non-VC systems of similar or greater complexity using much the same hardware and software components. VC is probably beneficial when all hell breaks lose in terms of usage load, or if you have some unusual nested transaction structure to deal with, but it generates its own kind of hell. It sounds great on paper, but unless you only use it in extremely narrow areas, you can end up writing a lot of extra code and be processing much more complex queries in order to co-exist with it. [ February 16, 2006: Message edited by: Reid M. Pinchback ]
Reid - SCJP2 (April 2002)
Joined: Feb 08, 2006
Thank you for your reply I didn't read it the first time you replied, so thanks for replying again
I'll give you an overview of my problem
I have a database with clients (and other entities, but let's focus on this one, the other will have the same problem/solution)
I want users to be able to read clients very often, and to update them only once in a while
To do this, i want the information to be cached, so that when someone wants to read a client he can read it without going to the database.
But imagine i'm watching this client, and this has been siting in my screen for a couple of hours, meanwhile, in another computer someone who had the same client, has updated a field. Now when i want to update my client with the information i've put in, this should give me an error, because i was updating a stale version
How can i solve this without using VC ?
Reid M. Pinchback
Joined: Jan 25, 2002
The caching part is easy. The staleness part may or may not be VC, depending on what kind of staleness you mean.
You can easily create a cache for entities, even in a clustered environment, using vendor-specific options for reading read-only and read-write versions of the same entity. The read-only bean pool forms the cache (a distributed cache if you are clustered). The read-write version causes notification events to be sent to the cache; the primary keys are part of that notification, and the read-only cache uses those to determine what needs updating.
So, if you are only worried about your cache being stale, you don't need to if you configure it properly; it really doesn't get stale.
The other kind of staleness has two broad variations that I can think of.
One is simply that you have concerns that people may leave a web page up for a long time, and that the *visual* information is stale, not what is cached in the server. While you could use VC, it isn't your only option. You could do something as simple as a timeout on requests. You could also go as far as approximating VC because in a sense the entire data set you used for that UI view when you last retrieved it already *is* a specific version. When you don't care about the specific VC values used for staleness detection, VC becomes isomorphic to entity state diffs because version difference detection is all that matters. When the user clicks "submit" you'll almost certainly be starting a new transaction, which means you could already be in a position to compare the current entity bean state to what was last shown to the user, and apply business logic to decide when they differ too much to allow the commit. Now the "do I use VC or don't I use VC" choice becomes an optimization question - if you have simpler data and doing the diff is easy, you get to avoid VC. If the costs of retrieval and examination grow, VC could be better. When, as you indicated, reading is much more frequent than writing (the typical case for transactional systems), you can hold off on VC or similar schemes for a very long time.
Another situation, which may or may not apply to you, is that you can have an extremely complex and slow (minutes, hours, days) workflow where different parties can modify sub-sections of the data at different times, and you need to allow partial commits where the changes aren't stale but block the pieces that are stale and give error information back to the originator. Essentially what you have is a long-running nested transaction, or you could think of it as a workflow with consistency checks on intermediate states up until you reach the end state of the workflow. Either way, this also could nudge you into a VC direction, but it is a really painful place to live. I'd rather just start with a proper workflow package and see how far it got me. [ February 17, 2006: Message edited by: Reid M. Pinchback ]
Joined: Feb 08, 2006
Hi, thanks again for your response,
for me the big issue here is that i have 2 separate problems, and either of them could require VC. But i don't want to have 2 version columns I can't use the same column for both problems, because one is invisible to me, the Server does all the work, and doesn't allow me to poke around there.
Problem no1. I have the information i send to the CMP, when the CMP goes to store the data into the database he can be doing so from an old record (the web UI example). And i need to avoid this kind of errors.
First solution (i'm using) - Nefore he stores he has to check the version, to see if this is the correct version. If it is, then he can go ahead and store the thing. This version column is managed by the server, i can touch it.
Now i have a second problem. The user has a DTO (or TO or Value Object) with the information matching the CMP, layed out on a nice web page. 5mts later (can be enough for someone else to make a change) he goes and send this to the SessionFacade. And in here lies the problem, the SessionFacade has to findByPrimary key the CMP, and doing so he will get the brand new one in the DB. So when he commit this information back to the CMP (that will search for problem no.1) everything will work fine.
The obvious solution, is a version checking, when the sessionFacade findByPrimaryKey the CMP, he could check the version in the CMP and the version in the DTO and if they were diferent then it's Exception time. But as i said i don't have access to the version from problem 1
So i need one version for problem 1 and another for problem 2, and this doesn't strike me as the right solution
I think what you said "The read-write version causes notification events to be sent to the cache; the primary keys are part of that notification" Can help me in problem 2, because instead of going to the database i can just the the CMP from the cache
About "You could do something as simple as a timeout on requests", it's hard, because data can be changed every second, or every hour, there would not be a right time for timeouts
For "...which means you could already be in a position to compare the current entity bean state to what was last shown to the user, and apply business logic to decide when they differ too much to allow the commit." I think that problem 2 doesn't allow this solution, because the logic would have to be in a kind of Version Column, and in there lies the problem
Thank you for your help
If you could nudge me in the right direction i would appreciate it. I think the problem is much clearer now
(Sorry for any english mistakes)
Reid M. Pinchback
Joined: Jan 25, 2002
Unless you have a situation where some of the problems you've described are a failure of a current app, and the project is explicitly to address those issues, I think you risk over-engineering the situation. There isn't anything you've described that isn't a potential for every other app, java-based or otherwise.
It is important to realize that for 99% of web/enterprise apps the fundamental objective is to be transactionally safe when you change the data. It doesn't matter if the database state changed at some point, only that from a relational standpoint the state reflects whole changes, not wierd fractional mixes of changes. You can't guarantee data hasn't changed, and most of the time you shouldn't even try. The most you usually need to do is identify particular fields or tables that are problematic and check them.
Example: you have a table of product data. That product has a description, and a price. You have a customer who uses a webapp to buy the product. You have an administrator who maintains the list of products and the price and description for each product on the list. You have a business policy that the description can only be changed by the administrator to fix errors, not to mutate a row from describing one product into some other product.
Given a situation like that, about the only version consistency issue you might have is to make sure that the price a customer used when submitting an order is the same as the price currently in the database. If the administrator changed the price, and the customer had a web page from before until after that change, clearly rejecting the order would make sense. The only consistency check would be to look at the price from the HTTP submit and compare it to the current state in the database. You wouldn't even need VC for something like this, you could even make the old price part of the SQL query for finding the entity to act on (select id from foo where id=1 and price=17.00); if the entity isn't found, data changed in a way you know you have to react to.
I'd suggest going through an exercise like that with the *real* situations your product is supposed to deal with, not ones I might make up or you might hypothesize. It could be the difference between a project taking weeks/months versus a project taking years.
And as a side note, except in limited situations, DTOs are not going to improve this situation, as I think you've already noticed. CMP beans will have select-for-update locks unless you've configured them differently, and that reduces some of the concerns you've raised (not the web user delays, just in the back-end processing). DTO is an old idiom that was understandable during EJB 1.0, but has hung around longer than really makes sense, at least for full-blown EJB applications. I think of it as the Statement (versus PreparedStatement) of EJB. It tends to shove people into a design process based on layers instead of modelling code based on appropriately organized behaviours or responsibilities. Layered isn't necessarily bad, but often such code exhibits rigidity, a common problem recognized long before Java was even on the scene. EJB 1.0 weaknesses (and a lot of publications) headed people in that direction, and DTO popped out as one of the many survival techniques. It has its place, but not really in current EJB code. No doubt a few people will come crawling out of the woodwork on that point, but c'est la vie.