Overall architecture
Follows a summarized description of the logical structure and behavior of the object model. Focus is on the key elements and on how they relate and cooperate to fulfill the requirements. Notice that what follows is not a detailed description of all elements, relationships and behaviors. This is a bird-eye description that elides many details for the sake of presenting the key ideas.
Structure
The design of the remote access to the OME data management server is centered around the Remote Facade Fow03 and Data Transfer Object Fow03 patterns. The OME data management server makes a set of procedures, the Remote Facade interface, available for remote invocation over the XML-RPC protocol Win99. This remote I/F is geared towards:
- Reducing the number of calls in client/server interactions.
- Hiding the internal server logic and objects to the client.
- Keeping the server in control of DB transactions.
- Providing a client’s specific view over the server logic.
The operations declared by the remote I/F are centered around the client’s usage. We use this knowledge to transfer all data that the client is likely to need for a while. So, RemoteFacadeImpl? the server class that provides the actual implementation of the Remote Facade, implements coarse-grained methods such as getDataTree(), which retrieves the data needed by the client to build a tree widget that represents a hierarchical view of the user‘s data projects, datasets and images. This way we reduce remote calls. Often, the data that we need transfer in such coarse-grained remote invocations come from different server objects and we use Data Transfer Objects ((References|Fow03)) to assemble that data together. The structure of a DTO (abbreviation of Data Transfer Object) should be fairly simple, mainly composed of primitive types or a simple graph usually a hierarchy. The reason is that a DTO should provide the client w/ a simplified view of the server objects and, at the same time, ease the marshaling process. Generally speaking, a DTO serves as the input of a given procedure or as returned value. However, the same DTO can be used both as input and return value for a given remote call or can be shared among different procedures, where that makes sense that is, when the data to transfer is similar. These concepts are exemplified by the following UML class diagram, which shows the DTO’s needed by the client in two different use-cases: presenting the user w/ their data (the tree widget) and editing a project.
Using DTO’s also has the benefit that the client doesn’t see the actual server objects. However, we need extra code to switch from one representation of the data (DTO’s) to the other (server objects). Assembler classes on the server-side take on this responsibility.
That said, the tasks of RemoteFacadeImpl? boil down to overseeing the remote invocation and delegate as appropriate. Each procedure will start a transaction, ask the right assembler to transform the input DTO’s (if any) into the server objects expected by the Manager classes in the server API, delegate execution to a Manger class, transform the returned value (if any) into a DTO, again by delegating to an assembler, close the transaction and return.
On the client-side, a remote proxy GoF95, RemoteFacadeProxy?, takes care of implementing the Remote Facade I/F by forwarding the calls to the real subject on the server-side this also entails serialization/deseralization of DTO’s and passing a token that identifies the user’s session.
The above discussion is summarized in the following UML class diagram.
A few considerations now.
The first thing that comes to mind from looking at the above diagram is that there is no explicit definition of the Remote Facade I/F nor explicit DTO’s on the server-side. B/c XML-RPC is just an RPC protocol and not a complete RPC environment, you don’t have I/F definitions and automatically generated client/server stubs. Client and server have to agree implicitly on the procedures names and input/output data. This comes handy on the server-side as we can use Perl hashes and arrays to quickly build DTO’s that can be marshaled automatically by SOAP::Lite (XMLRPC::Lite). However, this also makes the remote framework less robust, so we may want to consider a way around it in the future.
The second thing to mention is how semantic types are handled. We make a distinction b/w the core semantic types which are known a priori and those that are not known until runtime. As we know, at design time, what the core semantic types look like and how their data is to be supplied to clients, we don’t need to use a reflection API to discover their characteristics and access the data that the attributes carry. Instead, we define an explicit I/F to access that data DataManagementService? in the above diagram and we optimize remote calls as discussed above. We then provide a separate I/F SemanticTypesService? in the above diagram to access a reflection API for those semantic types that are not known at design time, such as a module’s input and output parameters. The SemanticType? and Attribute classes in the above diagram play the role of reflective DTO’s. In this case we have no knowledge of how the data is going to be used and we provide a “best guess” I/F w/ bulk accessors (retrieve a bunch of types definitions, a bunch of attributes and so on), which are not necessarily going to minimize remote calls.
The last observation regards the Web UI. B/c calls and data are designed around the needs of the Java client, a slightly different (local) I/F might be required for the Web UI. This shouldn’t be a big concern as the Remote Facade contains no server logic and is pretty easy to implement.
Behavior
We now focus on the collective behavior of those elements described in the static model. We do that by illustrating the object collaborations in the two use-cases already mentioned in the previous section: presenting the user w/ their data (the tree widget) and editing a project.
The following UML sequence diagram depicts the messages exchanged when the client asks for the data needed to build the tree widget that summarizes the user’s data hierarchy.
The diagram is pretty much self-explanatory. I’ll add just a couple of notes. First, it’s important to remember that a transaction is started as soon as the server procedure begins and closed right before returning. This is important b/c objects that are accessed by the procedure may, in turn, access (indirectly) the DB, like the instance of DataTreeAssembler? above. Speaking of assemblers, notice that DataTreeAssembler? is building the return DTO as an array of hashes. Even if no explicit definition of DTO is given on the server-side, the server has to stick to the format implicitly agreed w/ the client.
Follows another UML sequence diagram to describe the object interactions when a project is being edited.
A quick note on this diagram. Each server procedure sets the DB transaction boundaries. However, this doesn’t take into account application transactions, that is (in our case) several system operations (the server procedures) that form a logical atomic execution unit for which ACID properties apply. For example, if retrieveProject() and saveProject() don’t make up one of such units, then a lost update is possible:
- Project 1 has name=ABC and description=DDD.
- User A retrieves project 1 and starts editing the description field.
- User B retrieves project 1, sets name=LOST and saves.
- User A sets description=ZZZ and saves.
- Now project 1 has name=ABC and description=ZZZ.
Given the small amount of concurrent users that we are to support such occurrences would be quite remote. However, we may want to consider, in future, an offline locking scheme. Fow03.
Attachments
-
edit_project.png
(35.5 KB) - added by callan
23 months ago.
-
retrieve_data_tree.png
(37.8 KB) - added by callan
23 months ago.
-
rf_structure.png
(35.7 KB) - added by callan
23 months ago.
-
DTOs.png
(23.6 KB) - added by callan
23 months ago.




