Transient Entity
Posted By: Toby Hede on August 16, 2001
Anecdotal evidence suggests that many developers remain skeptical about the value of Entity Beans, especially prior to the EJB 2.0 specification. Many system designers and developers choose not to invest precious resources in a technology that remains unproven in large scale deployments.
Transient Entities are session beans that handle interaction with a datastore, generally a relational database. As Transients are only instantiated as needed and exist only for the life of the Session Bean, significant load reductions can be seen. Transient Entities are essentially the architecture enforced when using Microsoft's COM+ model (As COM+ has no Entity BEan equivalent).
Two types of transient entity are available for use: Conversational and Non-Conversational.
Conversational Transients are modelled on Stateful Session Beans and exist for the lifetime of the client session. Data can therefore be cached in the Transient Entity, reducing the load on the underlying datastore.
Conversely, Non-Conversational Transients exist for the lifetime of the method call and therefore no data can be cached in the Entity itself. Non-Conversational Transients are the most efficient and scalable way of handling perisistence in the application server (See Notes).
Transient entities typically wrap both business logic and data, in a traditional OO model. However, Transients can be modelled on Entity Beans and be used as 'simple' data entity objects with no included business logic.
A typical Transient architecture has the following form :
Client -> TransientEntity -> Datastore
or this alternative ('pure data' Transient):
Client -> BusinessObject -> TransientEntity -> Datastore
Sample Code:
In this example our Account object is a Non-Conversational Transient Entity.
We create an 'AccountModel' for our data (this is essentially the ValueObject pattern for data transfer). This is an immutable object and data is set on creation.
public class AccountModel implements Serializable
{
private String accountID = null
private String name = null;
private String email = null;
public AccountModel(String accountID, String name, String email)
{
this.accountID= accountID;
this.name = name;
this.email = email;
}
...
// create getters for each value
...
}
We create a remote interface for our EJB. In this case we are using AccountModel to encapsulate data for create and update, but we could explicitly pass the necessary parameters ( or even use either strategy as neeed dictates).
public interface IAccount
{
// standard Transient create-read-update-delete methods
public AccountModel create(AccountModel model) throws EJBException;
public void delete(String id) throws EJBException;
public AccountModel read(String id) throws EJBException;
public void update(AccountModel model) throws EJBException;
}
The exceptions returned should probably be extended to include more applicable and descriptive errors.
Now we implement the Session Bean itself. In this model we pass the AccountModel to a factory-based Data Access Object that handles the underlying JDBC implementation. This is similar to the system used by the latest version of Sun's Petstore blueprint application.
public class AccountEJB implements SessionBean
{
public AccountModel create(AccountModel model) throws EJBException
{
try {
IAccountDAO dao = AccountDAOFactory.getDAO();
dao.create(model);
}
catch(Exception e) {
// handle error
}
}
public void delete(String id) throws EJBException {}
public AccountModel read(String id) throws EJBException {}
public void update(AccountModel model) throws EJBException {}
...
// remember to implement SessionBean inherited methods
...
}
The implementation of the IAccountDAO interface is a Data Access object that handles the database interaction. In this implementation, we are actually using a Stored Procedure with the database to handle the query itself. This keeps messy SQL out of our Java code.
public void create(AccountModel model)
{
CallableStatement stmt = null;
...
getDBConnection();
String qry = "Account_Create (?, ?, ?)";
stmt = con.prepareCall("{call " + qry + "}");
stmt.setString(1, model.getID());
stmt.setString(2, model.getName());
stmt.setString(4, model.getEmail());
stmt.executeUpdate();
...
}
The use of stored procedures is on of the major benefits of handling peristence manually. Significant performance benefit can be seen from utilising stored procedures effectively, as the database can optimise and cache the execution plan for the SQL statement.
The client can then access the AccountEJB, calling the relevant methods as necessary.
Conversational Transients:
In a Conversational Transient, the AccountEJB would be a Stateful session been and would hold a local instance of the AccountModel. This model then gets reassigned as methods are called.
AccountModel model = null;
public AccountModel create(AccountModel model) throws EJBException
{
try {
IAccountDAO dao = AccountDAOFactory.getDAO();
dao.create(model);
this.model = model;
}
catch(Exception e) {
// handle error
}
}
Care must be used in managing Conversational Transient Entities as there is real danger of corrupting data. One technique is to set flags in the database - in this technique each each data row flag that marks locking and all queries return only when this flag indicates the record is not locked. Other strategies are cedertainly possible.
Consequences:
Conversational Transients should only be used in cases where the existence of a client session precludes other sesions, applications or systems altering the underlying data. This generally means that when a Conversational Transient is used, some sort of locking mechanism should be in place for the underlying data. Failure to do so will result in possible data corruption as cached data becomes stale and is no longer an accurate reflection of the current state of the underlying database.
Transient Entities are not as simple as CMP entity Bean solutions, because all database interaction code must be produced manually. Although this can be reduced to some extent by developing an appropriate reusuable code, in some sitautions CMP Entity Beans are definitely of great benefit and should not be discounted out of hand.
In using a Transient architecture, the load on the database can be increased significantly, especially in cases where the majority of data interaction is in read-only scenarios - each read invbolves another database call, where in an Entity Bean scenario, data can be effectively cached in the application server.
Notes:
When talking about Transients as the most efficient means of handling persistence in the ~application server~ that is exactly what i am talking about - the application server itself. Entity Beans obviously increase the demand on the application server. In a Transient architecture this demand is pushed to the database, and the load on the database is therefore increased significantly.
That said, RDBMS systems have had over 20 years to refine the strategies for handling large numbers of concurrent transactions. This fact can be utilised in developing a large scale system by relying more heavily on the database to handle persistience. The ability to seperate the physical database application server further increases the power of this type of model.
COM+ exhibits the ability to scale at least as well as similar EJB solutions without using Entity Beans, so the model is definitely workable.
3 replies in this thread
Transient EntityPosted By: David Churchville on August 19, 2001 in response to this message.
I like this pattern, and it makes sense for those not opting to use CMP beans in a read-mostly application.
Only issue, it doesn't support caching of frequently accessed data, which I almost always have to do.
One strategy to use with this pattern is:
Implement caching layer using Business Delegate.
Use a Java class to wrap access to a session bean that returns read-mostly data. Let the Java class cache results after first calling the session bean, and return cached data otherwise.
If used in a Servlet/Web context, this Java class can be stored as an application object for "global" data, or in the session context for user-specific data.
1 replies in this thread
Transient EntityPosted By: David Churchville on August 19, 2001 in response to this message.
I should have specified this strategy applies to the "non conversational" verison of your pattern. The conversational version supports caching, naturally.
Another thing I noticed, you don't actually mention queries here, just CRUD data access. I assumed (maybe incorrectly) that you would add query methods to the Transient objects? That's the whole basis for my caching discussion, not the caching of individual entities, but of collections.
0 replies in this thread
Transient EntityPosted By: Cameron Purdy on August 20, 2001 in response to this message.
Toby: "Anecdotal evidence suggests that many developers remain skeptical about the value of Entity Beans, especially prior to the EJB 2.0 specification. Many system designers and developers choose not to invest precious resources in a technology that remains unproven in large scale deployments."
I am not sure where you collect anecdotal evidence, but I can assure you that it is fundamentally invalid. Most of the companies that I have worked or spoken with over the past year have based their transactional data models in their new J2EE applications entirely on entity EJBs. These include, for example, most of the major financial institutions on the east coast and several of the largest in Europe.
I do not wish to discourage you from developing high performance patterns for EJB development. I simply encourage you to avoid prefixing your thoughts (and thus devaluing them) with irrelevant statements.
Peace,
Cameron.
1 replies in this thread
Transient EntityPosted By: Roman Stepanenko on August 21, 2001 in response to this message.
Your solution is not transactional. You can add tx behavior but that would make really ugly implementation and effectively you will repeat functionality of ejb container (in a very buggy manner). That's why people use entity beans.
1 replies in this thread
Transient EntityPosted By: Toby Hede on August 21, 2001 in response to this message.
When I deply my Transient Entity, I simply declare the methods as Transaction Required in the deployment descriptor. In JBoss (my app server of choice), at least, this lets the container manage the transactions. I have tested this with several techinques including nested calls across multiple methods and the transactions do work.
1 replies in this thread
Transient EntityPosted By: Roman Stepanenko on August 22, 2001 in response to this message.
When I mean transactional I not only mean propagation. If there is an exception during saving the state, then your objects will not be refreshed automatically. You will have to provide the code which will be buggy and unreliable.
0 replies in this thread
Transient EntityPosted By: Toby Hede on August 23, 2001 in response to this message.
I find amusing, to say the least, that you counter my anecdotal evidence with anecdotal evidence of your own.
Joking aside, many of the discussions on this very site have revolved around alternatives to Entity Beans. Some of the reports I read from JavaOne, concurred that the general trend seemed away from Entity Beans, including this report from IBM:
"A practical tidbit that was commonly spouted by a number of different speakers was that real performance came only in minimizing (if not outright banning) the use of Entity beans. Ah, what a difference a year makes!"
(http://www-106.ibm.com/developerworks/library/j-j1wrap.html)
And for a recent example of a discussion on the server side:
http://theserverside.com/home/thread.jsp?thread_id=8627
As well, in my travels as a developer I have have talked with any number of people, and there is a significant number suggesting that Entity Beans need serious consideration.
I swear my anecodtal evidence has to be as good as yours!
2 replies in this thread
AnecdotesPosted By: Cameron Purdy on August 23, 2001 in response to this message.
> I find amusing, to say the least, that you counter my
> anecdotal evidence with anecdotal evidence of your own.
Yes, yes, but at least they aren't analogies. That would be more like the pot calling the kettle black. ;-)
I've heard a lot of concerns about entity beans. These concerns usually fall into two categories:
1) My entity beans are slow, how do I speed them up?
2) I've never written an entity bean nor used one nor seen one but I think that they are slow. I'm going to do (x, y or z) instead because it is faster.
Question number two is a bit odd IMHO, and falls into the same category of comparing the speed of Java with C++, arguing if Macs are better than PCs, or arguing if Unix is better than Windows. Of course a Mac running Java on Unix is fast, Macs are supercomputers after all.
I do like question number one. The answer to question number one is sometimes that the EJBs are being used where they are arguably inappropriate, for example for set-oriented database access used in page construction, or in reporting.
Entity EJBs excel at serving as a transactional data model, which means as the target of business operations, they work well.
Entity EJBs are worst at set-based operations, particular with object-to-object navigation. Even with optimizations (such as Gene Chuang's fat-key), if a second operation is done across an optimized iteration, the result becomes O(n^2) instead of O(n). For example:
for each EJB in home.find()
invoke EJB.method() which goes to a related entity
(e.g. getting vendor names from a vendor ejb for each selected stock item ejb)
The fat-key optimization on 1,000 EJBs results in a total of one select on the first EJB (e.g. stock items) but then up to 1,000 selects will occur as vendor names are loaded using the vendor id foreign key in the stock item.
You can only make the EJBs so non-granular (in this case, denormalized), for example using a join to load the vendor name as part of the stock item, but each time you employ this optimization, you increase the cost of using the EJB in every case in order to optimize some set of uses. You also increase your chance of having stale data within a tx because you have data on an EJB which is not responsible for its being updated.
As a result, for reporting or massive page-gen purposes, both of which are almost always non-transactional in nature, it makes sense to use mechanisms other than an entity EJB as the means for database access.
Early optimization is the root of all evil. I've found that developing entirely with an entity EJB data access layer then optimizing read-only operations works pretty well. First of all it validates and fleshes out the data model design relatively quickly. Secondly, it insulates the app code from db changes because I know what has to get updated when parts of the db change. Lastly, it works early on, and it typically does not work slowly in development (i.e. a single user hitting a local database).
The difficult choices in optimization are typically found in one of two categories:
1) Read-only access, typically to build a response page, that hits a handful of EJBs but could be done several times as optimally with direct JDBC etc. These are hard calls because they are borderline -- not too expensive, but certainly worse than they could be.
2) Large transactional operations, particularly ones that you know will grow as the data volume in the application grows. Often these are batch-like or periodic processes. Take the stock item / vendor concept as one type of problem ... if that type of object navigation must occur on a large number of EJBs in a single transaction, it is a real resource hog. These types of transactions are rare in most applications, and deserve special care in optimization. If possible, just comment out the use of the tx data model (EJBs) and do as much work as possible on the db side in a few set-oriented SQL DML statements. Leave the EJB code as documentation that describes how the object model is affected.
I have discussed several potential solutions with EJB developers, but the problem is how can the EJB developer or container implementor (for CMP) predict what data needs to be prefetched? In other words, how can 1,000 ejbFindByPk calls be optimized in advance into a single select? Is that something the EJB developer needs to code? Declare? Is it something the container needs to guess? Use AI to figure out? If this particular question could be answered, entity EJBs in read-only uses could be as fast as custom O/R approaches. You know the ones that I'm referring to.
In summary, there are issues with entity EJBs that are a grey area for the performance question. That doesn't make entity EJBs any more evil than any other technology -- each has (or at least most seem to have) a purpose in life. I would have designed the entity EJB specification much differently than "they" did, but hey, they didn't bother to ask any of us now did they? ;-) So let's look for the good in this particular pile.
BTW - I wasn't trying to say that your optimization idea was bad. I think it is pretty cool that you are working to figure out faster / better ways of getting data, with or without using entity EJBs. I just didn't want people to accumulate one more unchallenged anecdote that led them to believe that entity EJBs were unusable, slow, despised by all developers and a complete failure.
Peace,
Cameron.
1 replies in this thread
Transient EntityPosted By: N K on August 31, 2001 in response to this message.
I am working in one of the largest financial institution (ML-East Coast). We are using Websphere. Our entire application donot have a single entity bean. All are stateless session beans that either wrap store procedure or wrap data classes,which are normal java classes with jdbc code.
2 replies in this thread
Transient EntityPosted By: Nick Minutello on August 31, 2001 in response to this message.
>Posted by N K 2001-08-31 08:40:55.0.
>I am working in one of the largest financial institution
>(ML-East Coast). We are using Websphere. Our entire
>application donot have a single entity bean. All are
>stateless session beans that either wrap store procedure
>or wrap data classes,which are normal java classes with
>jdbc code.
... which is fine.
However, it is not the point of the previous argument that Cameron was presenting.
The point is to use entity beans where they make sense. If a particular "entity" is not going to be a performance bottle-neck - make it an entity bean. It is *usually* quite a bit quicker to code a CMP bean than to implement a BMP bean - or its java-classes-wrapping-jdbc solution. It is certainly far more flexible and a lot easier to maintain.
If the access to the data is transactional, again look very hard at making it an entity.
If it is largely read-only (and it is a result-set, page generation data access) AND the perfomance has proven to be an issue having *already* tried entity beans, then look at using stateless session beans and JDBC.
The big point is to follow the 3 steps in optimisation (this is patently a stolen quote;):
1) Dont do it
2) Dont do it yet
3) Now that you have waited and are sure you have no choice, try one last time to talk youself out of it.
Maintainability of code (read: simplicity) is far more important than performance.
An interesting observation:
+ A lot of IBM consultants are proponents of this JDBC-wrapped classes, using session beans as a facade pattern.
+ IBM Websphere has been regularly complained about for poor entity bean performance.
I wonder which is the cause and which is the effect - which is the chicken/egg if you like?
0 replies in this thread
Roll-your-own Entity BeansPosted By: phil bradley on September 4, 2001 in response to this message.
I mostly agree with Cameron's post.
A couple of additional points.
Your Transient beans look to me like your own version of entity beans without the good bits. You admit it can't handle concurrency, and must implement your own explicit locks - not nice!
Entity beans were introduced as a safe OO persistence mechanism and to support shared access to data. Nothing about support for queries!
One common problem is that people confuse persistence with data access. Most queries are not a persistent operations and hence should not be performed thru entity beans. (Isolation issues ignored!)
Entity beans are widely used, not withstanding the limitations of some vendors implementations, because they are safe and scalable. No hard to debug JDBC code! Guaranteed concurrency and transactionally safe.
BTW, the Optimisation - Rule 1, Don't do it, Rule 2, if you must do it, then don't do it yet' Is a quote from Michael Jackson, the British systems Guru.
Phil Bradley
0 replies in this thread
Transient EntityPosted By: Yi Lin on September 6, 2001 in response to this message.
What's new in this "pattern"? Isn't this essentially the old straightforward way that everyone was doing before there is entity bean? - Writing your DB access code to get data into Java (or C++...) object so you can used it. What's new about it? Am I missing something?
> Posted by N K 2001-08-31 08:40:55.0.
> I am working in one of the largest financial institution
> (ML-East Coast). We are using Websphere. Our entire
> application donot have a single entity bean. All are
> stateless session beans that either wrap store procedure
> or wrap data classes,which are normal java classes with
> jdbc code.
OK, but why? Is that because no one in your institution really understands entity bean and ever used it? Maybe your team is missing out something very productive.
I am a supporter of entity bean because:
1. Entity bean (the entire app business as well) is NOT only about performance. It is also about "not reinventing the wheel" and productivity (I don't know about you, but I hate writing time-consuming and boring JDBC/SQL code). If performance is the only important thing, why aren't we still write tight fast assembly code today?
2. Entity bean can be optimized, either by better app server implemention and configuration. After all, reading data from memory (bean) is faster than from DB. (I admit for a particular server using certain configuration, it can cause EJB to load data from DB on every call, it nullifies entity bean advantage. Also EJB does not support fast bulk data retrieval.)
To me, entity bean is one generation ahead of this "pattern" and ahead of COM+ as well in this aspect.
1 replies in this thread
Transient EntityPosted By: Cameron Purdy on September 7, 2001 in response to this message.
The "ML on the east coast Websphere project without entities" is only one of many Java projects at ML. AFAIK Most new Java projects at ML are targeted at Weblogic, since ML chose Weblogic as its standard enterprise application platform. It's not surprising that an old Websphere project would NOT use entity beans, since Websphere barely (or "almost", or "kind of") supported CMP 1.0, for example.
0 replies in this thread