I have recently started to develop Web applications using the Web Dynpro framework. Coming from a pure J2EE world, I must admit that Web Dynpro has a few innovative features that I find interesting for user interface development. The use of component & view contexts, for example, is not unlike the ActionForms that one may find in a Struts application, but pushed a bit further. No complaints here.
What I do have some problems with is the whole CommandBean paradigm that is put forth by SAP (refer to the document Using" target="_blank">www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webdynpro/using%20ejbs%20in%20web%20dynpro%20applications.pdf">Using EJBs in Web Dynpro).
I do understand the usefulness of defining a model that will be used to generate and eventually bind to Context data structures. That's fine. What I do object to is the use of a so-called CommandBean to play that role. Again, coming from a J2EE world, I am familiar with the BusinessDelegate pattern - which would typically be used by a client application to invoke business logic on the server side. I would propose that a better, cleaner way of integrating EJBs with the Web Dynpro framework would be to use a BusinessDelegate for invoking business logic, and importing a separate and distinct ModelBean (instead of a CommandBean) to be used for defining and binding to Context data.
I have built one Web Dynpro application thus far. Instead of using a CommandBean, I created a ModelBean that extends my business object DTO (Data Transfer Object) (which is quite appropriate for that role, given that it implements all the get & set methods that are required for the business data that I need to model). My Web Dynpro application also makes use of an independant BusinessDelegate that is packaged with my EJB DC - this is a standard best practice on J2EE projects. I have been asked by the people working with me to modify this architecture to bring it more in line with the SAP way of doing things. I am open-minded and willing to learn and accept new ways of thinking and doing things. However, I fail to understand the usefulness of merging structure and behaviour by resorting to CommandBeans:
- <b>It violates the MVC paradigm</b> by having one object (the CommandBean) serve as both model AND controller as far as the Web Dynpro application is concerned. The CommandBean is obviously a model - since it is literally imported as such into the Web Dynpro application. It is ALSO a controller from the Web Dynpro's application perspective, since all calls to the back-end go thru the CommandBean via one or more of its execute_xxx methods. In contrast, the use of a business delegate by the Web Dynpro application clearly separates the model (the CommandBean... or rather, a more suitably named ModelBean) from the controller (BusinessDelegate).
- <b>Doesn't carry its own weight.</b> In other words, I haven't yet been provided with any valid justification for going thru the extra effort of coding the CommandBean's execute methods. It's been proposed to me that it somehow serves as an abstraction layer between the Web Dynpro application and the business logic. I would argue that it is the BusinessDelegate's role to abstract away the back-end logic from clients. If one does have a BusinessDelegate available, I would argue there's no need to code execute methods in a separate CommandBean. To prove my point, I would simply point out that all of the CommandBean examples that I have seen so far, either in How-To documents, or in production code, all follow the same pattern....
CommandBean.execute_doSomething() calls BusinessDelegate.doSomething()
Not a heck of an "abstraction" layer... I would in fact argue that it is worse than useless. If some major change occurs in the business logic that requires changing the doSomething() operation, we expect of course to modify the BusinessDelegate. The Web Dynpro client will also presumably need to be modified - that's to be expected, and unavoidable. But then, we'll also need to go about and change the CommandBean's execute_doSomething() method - again, extra work for no apparent benefit. Adding and removing business methods has the same implication. All this for an layer that simply adds the prefix execute_ in front of all business method calls... Is this "abstraction layer" worth the cost of creating and maintaining it ??
- <b>Unnecessarily complicates error handling</b>. I have been told that for technical reasons, it is recommended that all exceptions thrown by the CommandBean be of type WDException or WDRuntimException. But what if the client application needs to react differently to different failure scenarios ? When I create a business object, I might wish to provide the user with an error messages if connection is lost to the backend, and with a different error message if an object already exists in the database with the same attributes. In order to do that, I will have to catch the WDException, extract the cause, and continue processing from there... possible, yes, but clearly less standard and more labor intensive than the classical try/catch mechanism.
To say nothing about the fact that SAP's own API documentation clearly states that applications using Web Dynpro can reference and catch WDExceptions, but THEY MUST NOT THROW OR EXTEND IT !
- <b>Produces unnecessary DCs</b>. Page 6 of the aforementioned document presents an architectural view of a Web Dynpro project that uses a CommandBean. Why an extra DC for the CommandBean ?? I created my ModelBean class right inside the Web Dynpro project (in the Package view). That, to me, is where this class should reside, because it is created for no other reason that to be used by this particular Web Dynpro application. What is the benefit of placing it in its own independant DC ?
- <b>Not a typical application of the Command pattern</b>. The well-documented command pattern (Design Patterns - Gang of Four) has been devised mainly to enable encapsulation of request as objects, thereby making it possible to:
- specify, queue and execute requests at different times
- decouple execution of a command from its invoker
- support undo operations
- support logging changes so that they can be reapplied in case of system crash making it possible to assemble commands into composite commands (macros), thereby structuring a system around high-level operations built on primitive operations.
None of this applies to the way the SAP CommandBeans are being used. Not that much of an issue to people new to J2EE and/or OO development... but quite confusing for those already familiar with the classic Command pattern.
At this point, I fail to understand the advantage of merging structure (model) and behaviour (execute methods) through the use of a unique CommandBean object. Am I missing something ?