Data stored in a collection consists of business objects, as defined in the previous chapter. The base structure of the Business Object Collection pattern simply adds an additional collection class to the business object structure built in the previous chapter (see Figure 7-1).
Of particular note in the generic collection pattern is the use of a BusinessObjectKey . Keys are a compromise between relational databases and the object world. Keys are useful in establishing the exact identity of an object and ensuring uniqueness across a set of attributes within a collection. Object purists often do not leverage keys, yet object/relational mapping tools typically require the use of keys, even if the keys are not directly exposed to the user . This pattern leverages keys because they are common in the business application usage of objects.
There are four components of a business object; the fourth of which, the BusinessObjectKey , is optional in a pure object-oriented environment:
BusinessObjectCollection: The collection implementation surfaces lifecycle and query methods for the business objects in the collection. Typically, collections offer several flavors of the lifecycle methods , especially the read and creation methods, based on the domains that the collection serves. At this point, there is an interesting issue about the containment relationship between the BusinessObjectCollection and the BusinessObjects . Although it is true that there is containment, the mechanism for containment is at issue. Consider the case that you have collections with 1,000,000 objects. You really want a containment mechanism that allows you to efficiently select one or two objects that a client requests , without populating all 1,000,000 objects to find the one or two you want. In common solutions such as Java Data Objects (JDO) or Enterprise JavaBean (EJB) Container Managed Persistence (CMP), the collection interface does not populate all objects; rather, they retrieve only the necessary objects for use in a particular scenario. Using these types of managed persistence typically implies a direct relationship between the collection interface and an intermediate storage manager, rather than a primary collection type such as a LinkedList . This book is not about persistence mechanisms, but as you study the collection code, you will notice that you use JDO directly to retrieve the objects requested by a user.
BusinessObject: The business object represents the domain-specific concept collected by the collection implementation. Chapter 6, "Exploring the Business Object Pattern" discusses the concept of a single business object without getting into the details of creating or deleting a business object. Interestingly, by coupling the business object with the service implementation, you remove the ability to create or delete a single business object. It would cause a severe problem to delete the service implementation in terms of the Web Service. Collections address this problem.
ComplexData: As defined in Chapter 6, "Exploring the Business Object Pattern," the ComplexData is simply data that is not of a primitive type. The BusinessObject gates access to the object, although the data resides in a separate object.
BusinessObjectKey: The key is a unique identifier for each business object. Keys are important to business applications as a way to enforce uniqueness. Business object keys also help the transition of complex object data to a persistent relational model.
By surfacing the BusinessObject , it is implicit that there is complex data, as described in the previous chapter, contained within the BusinessObject . It is somewhat important to note that the business object is simply complex data itself in terms of the business object collection.
The primary client collaborations with the BusinessObjectCollection are via the create, read, update, or delete operations. Using a key on the operations helps to identify particular objects in a collection without having the complete object contents. Using a key reduces ambiguity. Often, if you use a complex key, a partially specified key returns a group of objects rather than a single object. Clients often persist keys to ease future lookups of the object. You could also store keys in cookies on a browser client so that when a client returns to a Web site, the last item they viewed could be brought up for them. Deletion operations receive a key or an array of keys for removal, and updates use the key to identify the exact object for updates.
Locating objects (reading them) occurs through one or more lookup operations. Lookup through a business object key returns a single object, though you should not have to know a key to locate an object. More often, a series of retrieval operations exists on the Web Service to return arrays of objects that contain attributes within a given set boundary. For example, retrieve all customers with a particular last name , such as Smith. Another operation may retrieve all customers with available credit ranging from $5,000 to $20,000 to make a special offer for bulk orders. Figure 7-2 shows a typical lookup scenario.
In the scenario, a client application creates an instance of a business object key. They then pass this key to a Business Object Collection pattern implementation to retrieve a business object. The collection stores objects in a mechanism that remains private to the collection. In the P.T. Monday Coffee Company application, you use JDO. With JDO, the collection exists in a database, and you use JDO Application Programming Interfaces (APIs) to return a type of collection known as an extent . An extent serves as an input to further filtering operations for JDO or for your own consumption. As a result, the extent may not hold fully populated business objects; the JDO implementation can optimize the content of the extent. From the extent, you retrieve one or more business objects, request that JDO fully populates it, and then return the business object to the application. JDO does not get exposed outside of your Business Object Collection pattern implementation.
Many collections also contain a single location method that returns all objects. It is extremely important to remember that business applications rarely have small sets of business objects; rather, they contain thousands or millions of object instances. Surfacing a general operation that returns all objects can encourage performance and scalability problems from junior programmers who choose to ignore the better-suited query mechanisms. Unfortunately, these performance and scalability problems do not show up until well after system deployment because of the business object set being larger in an installed base.