[ComponentDesignPatterns | CategoryPattern]
Context
Applicability
Problem
Forces
Separate the aspects of managing persistence issues away from the components themselves. Make the persistence or transience of a component independent from its type (i.e., allow both persistent and transient instances of the same component type).
Participants
Structure
Collaborations
Resulting Context
Consequences
Known Uses
Enterprise Java Beans
Implementation
Sample Code
Related Patterns
ContainerManagedPersistence is an aspect ContainerIndependence; some containers need persistence, some don't.
Motivation
Consider the following scenario in ComponentBasedDevelopment. A group of programmers sets out to build a new order processing system. They find two sets of components they need to build (roughly "models" and "views") and begin working on coding their components.
They decide that their system will use Java Serialization to persist its Orders. They make this decision because it is simple, and because only one department of only a few people will ever use this system. They go ahead and code the persistence directly into their models, with some supporting code in the application-level "glue" that ties the models and views together.
Then two months after they ship, disaster strikes. Marketing discovers their little application. They want to roll it out onto the web for thousands of customers to use. When the developers review their code they find that they will have to recode over half of the application because of how deeply embedded their persistence code is. How could they have avoided this needless pain?
They could have taken the approach that something is persistent because of WHERE it is, not WHAT it is. That is, they could have created an object that held onto their models and managed their persistence for them. That way, they could have isolated away the dependencies into a separate container component.
As a container may contain many differing components, it makes sense to centralize their persistence management. Moving the responsibility to the container provides a consistency across all components in that container, and eases the burden on the component developers. Publishing the model, like the EnterpriseJavaBeans specification, also allows container developers to provide a cross-industry standard encouraging the use of cross-container entities.
What is the Solution here? I think that it is:
The developers violated OnceAndOnlyOnce. The application, even using serialization, "should" have had the persistence centralized because the developers didn't see, or didn't pay attention to, what the code was telling them. Another case of JustGoodFactoring? -- RonJeffries
Yeah, you're right. But then again, one of the key reasons we have design patterns is to teach newbies what JustGoodFactoring is! Remember that that was one of the common complaints about DesignPatterns by some of the OO "old farts"; it "didn't teach them anything new". But that was the idea!
The EJB specification also allows ComponentManagedPersistence, although, as pointed out in the example given in the motivations section, this is not always the best of practices. As a component developer, we cannot necessarily guarantee the level of persistence the container will provide, which is why ComponentManagedPersistence becomes more appealing.
True and a difficult conundrum to solve. ComponentManagedPersistence also brings its own problems -- like having a no-source-code component that saves itself in Oracle that we suddenly need to work with DB2. ComponentManagedPersistence has a subtle attraction for developers - but overall I think it's a wrong turn.StuartBarker:
Agreed. I was almost at the point of considering this an AntiPattern! But in some ways it's needed as a possible alternative to this pattern. If the component developer wishes his component to only be applicable in a certain domain or application framework that has no persistence management then he's likely to go down the route of ComponentManagedPersistence. I certainly don't like it as it flies in the face of component reuse (unless of course they package up the entire persistence store with the component!).
I plead ignorance... we have had / seen InheritanceManagedPersistence, with a superclass called PersistentObject, which contained the protocol, caught the "save this object" message, etc., as advertised in the OO sales literature. But I can't figure out how ContainerManagedPersistence works. Does each component know that it is a persistent object? If not, how does the "save this object" get to the container? If yes, it does, it still will not know its container, so how does the "save this object" get to the container?
Here is how I understand ContainerManagedPersistence at least with EJB (more specific, Weblogic). It behaves similar to an object monitor. When a user request enters the container (on way to the bean) the container loads/activates the object, supplying a transaction context specific to the user. The user then has exclusive access to the object for the duration of that call. When the call exits the bean, the container then deactivates/stores the bean. The container uses reflection in conjunction with a bean descriptor file to perform the storage. The descriptor file provides the mapping between bean and storage. A factory (the Home/Finder) provides construction services. I believe that only Entity beans support container managed persistence.
Found the answer in InheritanceManagedPersistence:
Sort of, but not entirely. Someone has to know the structure of the persistent object - usually that's the object itself, but it might be a separate helper object (sort of like a BeanInfo?). Take a look at my CrossingChasms papers; the dynamic patterns advocate a ContainerManagedPersistence approach.
I have to ask.. are you getting at reflection? External agents figure out what your structure is and "persist" you. Persistence does seem to be one of the cross-cutting aspects of software.. The kind of thing you'd like to change in one place, but unfortunately it ends up touching every class in some manner. I've wondered what it would be like to have every object in a system transparently registered with some agent that "persists" it on demand, and neither the classes or the objects would know anything about it. The agent would have complete access to all object internals and use reflection to get at type information. Breaks encapsulation big time, but I suspect that persistence is one of those things that should force us to jump out of the model.
I've been grappling with the issue of ContainerManagedPersistence vs ComponentManagedPersistence in my current consulting project. In general, the lines in the sand are drawn with OO folks favoring ContainerManagedPersistence and database folks favoring ComponentManagedPersistence. Specifically, we're working with EJB.
Realizing that both sides have valid points, I have begun a question for a pattern or set of patterns that might allow us the best of both worlds, i.e., modeling types to be persisted independent of the persistence code. Thus, we could easily change out the ComponentManagedPersistence code without affecting the actual component. After a quick survey of the usual places, I'm starting to explore a variation of Visitor in order to achieve this. Has anyone considered this and maybe done it?
Been a long time since I've visited WikiWeb, and today I'm glad I came :-)
Chris,
Cool - glad you're glad. I wonder if a kind of guidance regarding how you blend or choose between ComponentManagedPersistence and ContainerManagedPersistence can be addressed in a higher level pattern that contains these and perhaps a few others.
Something should be written down that helps the developer use ContainerManagedPersistence to store the context, e.g. the definition and location of interfaces and methods used by a bean, and ComponentManagedPersistence to get and set data it should appropriately manage. Here is an example:
You have a Java bean that calls two CORBA methods - one is to retrieve data and display its results, and the other to submit updated data. Then, let's say generating stubs from the IDL wasn't feasible because you would need to recompile the bean every time an interface changes. So you decide to use Dynamic Invocation Interface (DII) and the Interface Repository (IR) to dynamically build your invocations at runtime. And, you wish to archive the bean's state so it can be instantiated later without contacting the IR and rebuilding the method's signature and location.
As the Intent tells us, ContainerManagedPersistence should allow us to separate the aspects of managing persistence away from the components themselves. This should allow us to have persistent as well as transient instances of the same type and gives us the freedom to store those instances in different storage mediums (e.g. flat files vs. RDBMS). This is a wonderful goal to achieve.
If we take a closer look at how AlistairCockburn describes a way of how it could be done, we figure out that the goals are not achieved. If we require our components to implement a defined interface that allows them to provide the "content" that should be made persistent, we explicitly give the components themselves responsibility for their persistence (something we want to get away with).
Furthermore implementing just one such interface (something like IPersistStream) does not allow us to use different kind of storage mechanisms and mediums. Consider the following example:
This way the components are not influenced at all by changing persistence mechanics. Providing a general interface for all containers even allows us to keep the application code independent of persistence issues. What needs to be changed are the specs as well as the container implementation.
The question that comes up is how those specs could look like and how they depend on the components. This is largely driven by the question if you are willing to break encapsulation or not (i.e., allow the container using the spec to access the attributes of the components directly or not). We opted to use some intermediate approach where components need to provide a getter-method for each persistent attribute.
How about PackagedPersistence? In any language there exists a finite number of primitive data types (plus object references). Each persistence media (serial file, random access file, ORB, serial network connection, RDBMS, OODB, etc.) uses a packaging object that is a mediator between the object and the medium by taking the field, type and value information given by the object and packing them in a way which is friendly to the persistence medium.
PackagedPersistence contains the implementation penalties of ComponentManagedPersistence, but can be made more robust in the face of changes in the implementation of the objects being persisted and since it uses a limited interface which makes no assumptions about how a particular primitive is stored in the medium, it can support a much wider variety of persistence media. It also does not rely on any reflection mechanisms, which are not available in every language and which are not robust in the face of changes to the object's implementation anyway.
Since CBD is more about packaging (where interface is separated from implementation yadda yadda) using InheritanceManagedPersistence isn't applicable at the component (binary) level. However, in the component's implementation, nothing stops you from doing it.
The drawback to it, to ComponentManagedPersistence, and to perhaps PackagedPersistence is that your dependencies and/or persistence requirements are hidden from the users of your component. To get around this, in my current project, I use ThirdPartyBinding with ComponentManagedPersistence by using an external "management" component to handle persistence of component metadata and other administrative functions.
So this is an example of ContainerManagedPersistence where the container delegates management to a separate standard management component coupled by design to one or more of the other components.
Thoughts? I can provide a concrete example if you'd like ;-)
In EnterpriseJavaBeans (especially in v2.0), CMP is pretty elegant. Entities don't need to subclass an all-knowing PersistentObject class, nor do they need to be aware of how to persist themselves in any way. Instead, an entity class only has to make public the fields (in EJB 1.x) or accessor/mutator methods (EJB 2.x) that must be persistent, and declare them in the bean's EjbDeploymentDescriptor?. The EjbContainer can do whatever it wants with this information, but most will either hand the deployment descriptor off to a reflection-based persistence interrogator, or generate some code that does the job more quickly. Either way, the actual interface between the public fields-or-methods and the PersistenceMechanism is up to the container vendor. This is a good use for ObjectRelationalMapping techniques.
More info:
http://java.sun.com/j2ee/j2sdkee/techdocs/guides/ejb/html/Entity4.html
--
Of course, by now everybody knows that EnterpriseJavaBeans (especially in v2.0) is considered a failure. PojoPersistence? has killed ContainerManagedPersistence, and even EnterpriseJavaBeans 3.0 has switched to PojoPersistence? (with some help from AnnotationMetadata).