Agile Ajax

Leaky Business Data and Logic with GWT

Sometimes architectural concerns dictate design. That can mean abandoning an elegant approach for something more old school. Take for example the case of GWT-based webapp vs one implemented with vanilla JSP's. The presentation tiers differ in a number of ways, most significantly in who controls the execution environment. In the case of the JSP, you control it (unless someone hacks in). In the case of the GWT interface, the end-user controls it. This consideration forces our hand with regard to some design decisions.

Let's say we are big fans of the POJO approach, i.e. we want to hand appropriately neutered and spayed domain objects to the presentation tier (managed through a Pojo Facade), rather than trouble with the DTO approach. One technique for exposing the domain objects to the presentation tier (and the business tier) without allowing developers to do too much mischief, is to restrict access via a set of complementary interfaces: the View interface that allows access via nothing but getters; the Bean interface that allow access via both getters and setters, and the Domain interface, that allows access to the domain objects actual business logic related methods.

This three interface has some distinct advantages:

  • The presentation tier can be restricted to just accessing the object through the view/getter interface.
  • ORM libraries and dependency injection (DI) frameworks can use the bean/getter+setter interface
  • The domain objects/business tier can use the domain interface without being tempted to use the getters and setters.

In the case of our traditional JSP presentation tier, we send back view objects. If we take this approach to a GWT-based application, i.e. exposing our domain objects to the presentation tier through a view interface, we end up sending all of the data over to the browser, not just what we wish to expose to the GWT UI. Remember, remember, remember, the browser is not under your control.

Let's take a concrete example. Consider the following naive user comment system.


We load a set of messages and display them in a GWT StackPanel. Below you can see the three interfaces, MessageView, MessageBean, and Message (the business interface) and the fields of the MessageImpl class which also implements the GWT IsSerializable class for GWT-RPC purposes. Note that the email is not exposed to the presentation tier, presumably because we don't want someone spamming our commenters, yet we do want to uniquely identify our users via email for internal purposes.

public interface MessageView {    String getName();    String getSubject();    String getBody();    Date getSubmitDate();}public interface MessageBean extends MessageView {    void setName(String name);    void setSubject(String subject);    void setBody(String body);    void setSubmitDate(Date date); }public interface Message {    boolean hasValidEmail();    boolean hasBadWords();    void cleanMessage();}public class MessageImpl implements IsSerializable, MessageBean, Message {    private String name;    private String subject;    private String body;    private Date submitDate;    private String email;    [...]}public interface MessageService extends RemoteService {    /**     * get a list of messages     * @gwt.typeArgs <client.MessageImpl>

     */    public List getMessages();}

If we now pull up the interface and look at the response from calling the MessageService, we get the following chunk of data:

//OK[1186869290897,7,16,15,14,13,2,1186869290897,7,11,5,4,12,2,1186869290897,7,11,10,9,8,2,1186869290897
,7,6,5,4,3,2,4,1,["java.util.ArrayList/3821976829","client.MessageImpl/65273341","Hell\x20hath\x20no
\x20fury\x20like\x20a\x20developer\x20scorned.","jsmith@mail.com","John\x20Smith","Has\x20Ajax\x20jumped
\x20the\x20shark?","java.util.Date/1659716317","I\x20disagree.\x20Developers\x20are\x20relaxed\x20people
.\n\n>Hell\x20hath\x20no\x20fury\x20like\x20a\x20developer\x20scorned","Bob.Schmidt@angrydev.com","Bob
\x20Schmidt","Re:\x20Has\x20Ajax\x20jumped\x20the\x20shark?","You\x20are\x20so\x20wrong,\x20Bob!!","Ajax
\x20is\x20kewl!!\n\nDon't\x20diss\x20the\x20Ajax,\x20man.","biff@biff.com","Biff\x20Thompson","Jumped
?\x20Ajax\x20is\x20the\x20shark!!"],0,2]

As you can see, the serialized message from the GWT-RPC service contains the super sensitive email addresses, as you would expect. And since the browser's execution environment is not under our control, the email addresses of our forum contributors are exposed to anyone with a copy of Firebug.

This may seem like a dope slap obvious point to most developers. But I've run into this mistake with enough developers to be convinced it has to be pointed out again and again. So, even if you are writing what appears like Java in GWT, be aware of who controls your execution environment. Use DTO's instead that limit the data passed back to just that data you wish to expose.

One downside to using GWT with DTO's is that you can't dynamically generate your DTO's with something DynaDTO. Fortunately you can do reflection in GWT, unfortunately you can only do it at compile time. So right now you have to hand code your DTO's.

Technorati Tags: , , ,

Comments: 1 so far

  1. hand code it or generate it via andromda for instance

    Comment by Gabriel, Sunday, August 19, 2007 @ 6:31 am

Leave a comment

Powered by WP Hashcash

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics

WordPress

Comments about this site: info@pathf.com