I am designing a J2EE application that is made up of a number of separate components that each have a well-defined responsibility. Each component is made up of one or more J2EE components (web clients and EJBs). I want to design the application such that it is easy in the future to deploy each component (or a group of components) on different servers. In order to do this I need to make sure that the interfaces between each component are exposed as remote interfaces (but I will use local interfaces inside each component). However, there are a number of entity beans that need to be accessed by more than one component. I am wondering how best to expose these entity beans. I believe there are a number of options:
1. Expose remote interfaces on each of the shared entity beans. The disadvantage of this approach is that it is inefficient and that I will not be able to take advantage of container managed relationships. (I am intending to use container managed persistence.)
2. Create a facade object (stateful session bean) for each of the entity beans which exposes a remote interface and in turn accesses the shared entity beans locally. The disadvantage of this approach is that I have to create some extra EJBs and that I cannot directly make use of container managed relationships etc from the client component.
3. I don't know if this is an option but I am wondering whether I can deploy a copy of each shared entity bean with each application component. The advantage of this approach is that the component would access the entity locally and could make use of container managed relationships. However, I don't know what the issues are with having more than one instance (per primary-key) of an entity in the same application. I don't know whether this would cause errors of whether they would get out of sync (because different instances with the same primary key would be updated by different clients). Initially each component would be deployed in the same server but later they would be deployed in different servers. In both cases with this option each component (JAR) would have copies of the shared entity bean classes.
Any suggestions as to the best approach and whether the last option is feasible would be much appreciated.
To state the obvious, the best answer depends on what you are trying to achieve. In particular, the volume of transactions and the proportion of reads to writes on the entity beans.
If you have really high volumes and lots of writes, you would need to set up multiple copies of the entity beans and to use clustering to synchronise the various copies of the entity beans. But understanding clustering and getting it to run is not a trivial problem.
If your volumes are lower, you would be able to synchronise the copies through the database. This means tweaking the commit-option for the entity beans (set up in jboss.xml) so that the entity beans reread the underlying data each time that they are accessed. This is inefficient but would be guaranteed to work.
An alternative approach is to keep a single set of entity beans in one instance of the JBoss server, and to run multiple copies of the separate components on different servers that access the single set of entity beans. This can be done by tweaking the ejb-ref to jndi-name links in jboss.xml and/or jboss-web.xml - well, that's what it says in the book.
Where your references to Entity Beans are almost entirely reads, you could use a different server for each component, and keep in each server a local cache of Value Objects containing the data from the Entity Beans. This minimises network I/O and server hits, BUT the local cache will not know if the underlying Entity Bean has changed.
So your option (3) is workable but only if you use clustering or the database to synchronise the copies.
Your option (2) is workable - but it would be a good idea to place the facade class on the servers containing each component rather than with the entity beans. This would enable you to change the strategy for accessing entity beans within the facade class without affecting the coding of higher level components.
Your option (1) could also work but would have a very heavy impact on network I/O if getters and setters on individual attributes were used.
Hope this helps.
Thanks very much for the information and suggestions. I don't know a whole lot about clustering so I guess I was trying to find a solution that would work initially running in a single app-server and that in the future rather than clustering the whole application I could just break it into bits and put different bits on different servers to help spread the load. It sounds like options 2. and 3. are both achievable. I will have to have another think about which one is going to be best.
I have had another think about it and I have realised that most of the shared entity beans are static (read-only) and that the ones that aren't will never be used by more than one component at the same time. (They go through a set of steps in the system and are flagged with a status depending on the step they are up to.) It seems that this will allow me to just make them all local access initially when I am running the whole application on the same server and then just replicate the shared entity beans with local access when I distribute the components onto different servers in the future taking care to configure CMP correctly. Thanks for your help with this.