I feel your pain. Too often I find myself mumbling about the layers upon layers, all the while feeling that there must be some better way. In Tapestry you have your DAOs and smart POJO DO's and everything Just Works. To my understanding, the major difference here is that with GWT you are effectively giving the client the source code for client/shared packages. (it can be modified, however unlikely, in the browser and therefore cannot be trusted).
It almost always occurs then that the business logic that you want to protect needs to exist on the server side only. Not only business logic, but anything else you wouldn't want to the end user to reverse engineer. Any client side validation of data should be duplicated on the server side. If possible, you might put some verification code in your shared package, so you can have code reuse on both tiers. *You want to make the client's experience nice (client side validation) *You can't trust the client (server side authentication, authorization, validation and business logic) *You have the potential to disclose business logic to the client (JS translation of client/shared packages) I am facing a similar unwanted abundance of classes due to the fact I need to "bridge" or "adapt" my objects to different layers. For instance I use a double sided view helper object (View Helper pattern) for my DTOs, to convert them to SmartGWT ListGridRecords and back (I'm calling these bridges, the analogy works but my terminology is off I think) Selected DTO's get sent to the server in an RPC and data is cleansed/validated before working on them Then on the serverside a DTO for something like RoomDTO would get mapped to " and roomtype = 'S' " when I go to construct the SQL (the DB I connect to was not put together well enough to use an ORM effectively) But I don't want to have bits of SQL in my DTO either, so I have a serverside "db helper" which acts as a DTO->SQL-fragment converter. I was flipping through the Sun Core J2EE patterns book the other day, and one option might be to play with inheritance, where the Domain Objects extend the client side DTO, so that the getters/setters stay in sync and there is less duplication. That way your server side DOs could be a little smarter. I end up not minding the client side view-helper-bridge thing, because it still feels elegant and agile. And I realize the potential need for more than one type of these bridges per DTO, if I need to have the ListGridRecord display different fields to the UI. It doesn't feel like a solid one-to-one relationship between DTO and bridge, so I feel less urge to couple them. However on the server side, when I use a DTO to do a query, I do feel the urge to make the DTO aware of what it is in the database. Especially if I have an enum or static list of possible values, which the client side already received through an RPC! Some mid-day coffee brainstorming: So far we have UI Objects (simple strings or ListGridRecords, etc) DTOs DOs on the server side (may have more fields than DTOs, stuff we don't want to expose) BOs for doing server side calculations UIO<-->DTO can be done with a bridge/converters that exist client side DTO<-->DO can be done with a bridge/converters that exist server side, or possibly through inheritance BO<--DO can be done through composition, etc. As far as I'm concerned, the way the GWT designers set up RPCs to be used is no mistake. So I'm trying not to go against the flow, although it doesn't hurt to try an innovate. Having my RPCImpl call a DAO method works fine for me, and I get code reuse from a previous project. Would having the domain object smarts in an inner class help the code consolidation problem, from an editing standpoint? (server side) While it may seem orthogonal to the problem, a command pattern or event bus could be made to help. I'll have to think about this some more. On Wed, Aug 12, 2009 at 2:21 PM, Kaspar Fischer <[email protected]>wrote: > > Hello, > > I am trying to design the architecture of an application that uses GWT > and am struggling with the connection between my persistence & logic > layer and the GWT presentation layer. I think I have not yet read and/ > or understood enough about GWT and hope that somebody can point me > into the right direction. > > My app's persistence layer is JPA (Hibernate) and in designing my > logic (business) layer, I have tried to follow an OO design in which > my domain objects are more than "stupid" data containers but instead > contain business logic where appropriate -- i.e., I am trying to avoid > an anemic domain model [1,2]. As a consequence, my service layer is > rather thin and most logic is realised by the entities themselves. > > My question: What approaches exist to integrate GWT into such an > architecture? > > I have read through "Using GWT with Hibernate" [3] and it seems that > all of the approaches mentioned there (DTOs, Dozer, Gilead) rely on > "powerful" services. So for example, while my entity Book has a method > getAuthors(), these frameworks "suggest" to do a service call > bookService.getAuthors(callback). I like the advantages [1] of having > intelligent domain objects, so I am wondering whether people have for > instance thought about on-the-fly transforming the domain objects > (Book) to light-weight async objects (BookAsync) so that one can call > book.getAuthorsAsync(callback) if one has configured the method > getAuthors() as "lazy". (This would eventually call a service in the > background, of course, but one that is generated automatically by the > framework.) Are there approaches like this? > > Basically, I have the same problem like other posters [4]: I would > like to avoid writing lots of boilerplate code, like DTOs that mostly > duplicate my existing domain class hierarchy, or services that are > merely wrappers of method calls on my entities. In my experience > having these additional layers makes the application unreadable and > less agile as even a small change (like adding a parameter to an > entity method) entails tons of "syntactial" changes in all the > services, etc. > > Thanks for any pointers, > Kaspar > > [1] http://en.wikipedia.org/wiki/Anemic_Domain_Model > [2] > http://groups.google.ca/group/EtoE/browse_thread/thread/cac1eafe15f06f5b/7db829b9dacc59ab%237db829b9dacc59ab?sa=X&oi=groupsr&start=0&num=3 > [3] > http://code.google.com/webtoolkit/articles/using_gwt_with_hibernate.html > [4] > http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/1035e0e677efac06/14e430525a734e99 > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/Google-Web-Toolkit?hl=en -~----------~----~----~----~------~----~------~--~---
