How to GWT

In an attempt to orient myself and my colleagues with GWT, I've been reading up on GWT, trying things out, and blogging about them here. My goal is to start with simple use cases and build on to them with more complex ones. The way it's been working so far is that each post builds on the prior one.

Saturday, March 20, 2010

More Robust Back Button and Bookmark Support

In the last post, we looked at how to interact with GWT’s History class in order to provide Back Button and Bookmark support for the Contact List application. There are some issues with the approach we took in the last post. The biggest deficiency is that the page’s “place” is fully determined inside a particular UI Component. If the page was enhanced such that the page’s “place was represented by multiple UI Components, things could get messy. We have a call to History.newItem() inside the ContactListPresenter, so it will be really cumbersome if some other Presenter needs to participate in determining the current place in the application.

For example, if we enhance the Contact Management Application so that the user, from the Contact Detail UI Component, can decide if s/he wants to manage more information about the Contact:

image

When the user chooses to ‘Show More…’, a new UI Component will be presented for the user to view/edit other information about the Contact.

image

And let’s add support for the “Show More…” link to participate in our Bookmark/Back support. This means that a “place” in the Contact Management app. represents both the current contact selected in the Contact List UI Component AND the state of the show/hide link in the Contact Detail UI Component.

The design in our last post had the Contact List presenter calling History.addNewItem() when the user selected a Contact. When ‘Show More…’ is clicked, the URL needs to change again. If we were to call History.addNewItem(“ShowMore”), we’d be left with a URL like: ContactListTest.html#ShowMore. This wipes out the Contact that should also be in the anchor so, if the page were bookmarked, it wouldn’t know which Contact to display. In order for the Contact Detail UI component to manage this correctly, it would need to check the current URL and append ‘ShowMore’ on to it so that the URL instead looks something like this:

ContactListTest.html#Jim/ShowMore

By having the Contact Detail UI Component know what the Contact List UI Component put in the URL string, it starts coupling the two components together and it becomes harder to have Contact Details UI Component as a standalone, reusable UI Component.

And if the Contact List UI Component were to be reusable within some other page, it really shouldn’t call History.addNewItem(“Jim”) when a Contact is clicked. Something else on that page could already have something in there that needs to be maintained. Maybe it’s an email app. that enables the user to manage their Contacts. In this case, before the user even interacts with the Contact List, the URL would look something like: EmailApp.html#ContactManagement. And a link to Contact in the Contact List would then need to look something like: EmailApp.html#ContactManagement/Jim.

There are a ton of scenarios we could dream up, but the point is that for UI Component modularity, a UI Component’s Presenter probably shouldn’t be wholly responsible for generating its own URL’s.

To handle this, the Presenter will establish an interface for generating URL’s within its UI Component. Here’s an interface the ContactListPresenter establishes for its component.


/**
* Used to generate a URL for a Contact in the Contact List
*/
public static interface ContactListUrlGenerator{
public String generateContactUrl(Contact contact);
}


So when the ContactListPresenter is ready to generate a URL for a Contact in the Contact List, it will call in to the supplied implementation of this interface, get the URL, and then apply it to the View.



The ContactListPresenter will require a UrlGenerator at construct-time. Now the thing that constructs and wires up the Presenters can be responsible for implementing the URL generator. For the Contact Management application, here’s that generator:




private PlaceManager placeManager = new PlaceManager();

private class PlaceManager implements ValueChangeHandler, ContactListUrlGenerator{

public void onValueChange(ValueChangeEvent event) {
/*
* Pulls history token off URL and interprets it in order to tell the presenters
* in the app what to present.
*/
String contactName = event.getValue();
if (! contactName.equals("") && contactName != null){
// change the Contact List
Contact contact = contactListPresenter.showContactAsSelected(contactName);

// change the Contact Detail
detailpresenter.setContact(contact);
}
}

public String generateContactUrl(Contact contact) {
/**
* Helps generate the history token for the ContactListUrlGenerator
*/
return contact.getFirstName();
}
}


Our URL Generator implementation is actually more than just a URL generator. So it can listen to History events, it also implements ValueChangeHandler<String>. We put it all together and call it a PlaceManager. With this, we will use placeManager both to construct the ContactListPresenter and to register with the History class:




contactListPresenter = new ContactListPresenter(listView, placeManager);
History.addValueChangeHandler(placeManager);


The reason we give PlaceManager these two responsibilities is because they are so closely related. The generateUrl() method will be generating URL’s and onValueChange() will need to parse/interpret whatever generateUrl() constructs. If one method needs to change, the other will likely need to change, also. Lastly, by placing this URL management outside of the Presenters, it can actually have visibility in to all the Presenters and can do things like tell each Presenter what do with when the history token has a particular contact name:




// change the Contact List
Contact contact = contactListPresenter.showContactAsSelected(contactName);

// change the Contact Detail
detailpresenter.setContact(contact);


For the Contact Detail UI component, it would need to generate a link for its ‘Show More…’ link. It can define its own UrlGenerator to do so:




public static interface ContactDetailUrlGenerator{
public String generateShowMoreLink();
public String generateHideMoreLink();
}

Now our PlaceManager can implement ContactDetailUrlGenerator and help the Contact Detail UI Component be in the correct “place”.



In this post, we looked at how to bring “place management” out of the presenter and in to the AppController.

Friday, February 19, 2010

GWT’s Back Button and Bookmark Support

 

When we talk about an interactive web page, it means a user can do a lot of things on that single web page and, depending upon the application, the user reasonably expects that 1) the browser’s ‘Back’ button takes them to prior places they were within that same web page and 2) if the user has navigated to a particular place within page, they reasonably expect they can bookmark the current URL and return back to that page with that URL and the page will look similar to the point at which they bookmarked it. In this post, we’ll look at what GWT offers to enable an application to provide Back Button and Bookmark support.

Back Button Support

If we did nothing special to manage ‘Back’ support in the Contact Management application, the browser’s ‘Back’ button, no matter what the user had clicked on, would take the user back to the place they were before the Contact Management application. For example, the user opens their browser to their home page, www.google.com, then they go in to the Contact Management application. Then they click on Jim, then Joe, then Jane. When they clicked ‘Back’ at this point, they browser leaves the Contact Management application and returns to www.google.com. For our Contact Management application, it would be better if the ‘Back’ button in this case, returned them back through their clicks: from Jane back to Joe, and from Joe back to Jim. And only if they clicked ‘Back’ again, would they be returned to www.google.com.

The Browser’s ‘Back’ button really does nothing more than return the user to the prior URL they were on. So it makes sense that, in order for the Contact Management application to have Back support, each click from Jim to Joe to Jane will need the URL to change. This way, when the user clicks ‘Back’, the URL will go back through those previous URL’s. GWT has provided this capability with its History.newItem(String) method. When History.newItem(String) is called, the URL changes to reflect the new item. The String passed in to the method is not the entire URL, though. It is just a portion that GWT will append at the end of the URL after a ‘#’ symbol. Appending information to the existing URL after the ‘#’ symbol will make it so the browser doesn’t treat this as a new URL that needs to be requested from the server.

Here’s how it could look embedded in the click-handler of the Contact List UI Component:

	public void setContactList(Collection contacts){
this.contacts.clear();
for (final Contact contact : contacts){
final Text text = contactListView.addContact(contact.getFirstName());
text.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {
// when user clicks a Contact, add History item
History.newItem(contact.getFirstName());
eventBus.fireEvent(new ContactSelectedEvent(contact));
showContactAsSelected(contact);

}
});
this.contacts.put(contact, text);
}
}


Note: We haven’t seen the showContactAsSelected() in prior post, but all it does is change the style of the selected Contact to a ‘selected’ style and all other Contacts get a ‘normal’, unselected style.



Also, in order for the History class to be used the HTML host page must have a “special” iframe in it. With the iframe added for the Contact Management application, the HTML host page now looks like:



<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" language="javascript" src="com.gwtdesign.history.contactlist.ContactListTest.nocache.js"></script>
</head>
<body>
<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<h1>Contact List Test Page</h1>
</body>
</html>


With the special history iframe in the HTML page and the History.newItem() call from the Contact click-handler, the URL changes work! When the user clicks on ‘Jim’, the URL changes to look something like:

http://localhost:8888/com.gwtdesign.history.contactlist.ContactListTest/ContactListTest.html#contact=Jim



And then Joe:

http://localhost:8888/com.gwtdesign.history.contactlist.ContactListTest/ContactListTest.html#contact=Joe



And then Jane:

http://localhost:8888/com.gwtdesign.history.contactlist.ContactListTest/ContactListTest.html#contact=Jane



With this in place, now the user can click the ‘Back’ button without leaving the Contact Management application. Only the portion of the URL after the ‘#’ symbol will change. However, with just this use of History.newItem(), clicking ‘Back’ will not yet fully do what we want. We see the URL change as expected when we click ‘Back’, but the page doesn’t change at all to reflect the different URL’s. The page stays completely static through these ‘Back’ clicks. This is somewhat expected, since as we discussed above, a change to a URL where the only change is after the ‘#’ symbol is an indication to the Browser that it shouldn’t refresh the page with the new URL. This means, when the URL changes, it’s up to us to determine what the page should look like. And this also means we need to know when the URL changes in this way.



GWT provides a handle to the URL-changed event via the History. addValueChangeHandler(ValueChangeHandler) method. When the page loads, we can add a ValueChangeHandler. Then as the user clicks the back button, not only will the URL change based on the new items we’ve added to the History stack, but our event handler will also get called so that we can see have our code modify the page to reflect the user’s new location.



For the Contact List, we can accomplish this with some small changes and a refactor. The Contact click-handler will no longer fire the ContactSelectedEvent. It will only change the URL (i.e. call History.newItem()):



	public void setContactList(Collection contacts){
this.contacts.clear();
for (final Contact contact : contacts){
final Text text = contactListView.addContact(contact.getFirstName());
text.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {
History.newItem(contact.getFirstName());
}
});
this.contacts.put(contact, text);
}
}


During the ContactListPresenter’s constructor, we’ll add a History ValueChangeHandler so that the presenter is notified of URL changes. Then when the URL change is handled, at that point, we’ll raise the ContactSelectedEvent.



	// Constructor
public ContactListPresenter(ContactListView contactListView, final EventBus eventBus){
this.contactListView = contactListView;
this.eventBus = eventBus;

History.addValueChangeHandler(new ValueChangeHandler() {

public void onValueChange(ValueChangeEvent event) {
String selectedContactName = event.getValue();
if (selectedContactName == null || selectedContact.equals(“”)){
// do nothing
}else{
Contact contact = findContactByName(selectedContactName);

/*
* Prior to refactoring, this was on the click-handler.
* To provide 'Back' support, we will now do this on a URL
* change. All the click-handler does now is change the URL
* which, in turn, calls this History ValueChangeHandler.
*/
eventBus.fireEvent(new ContactSelectedEvent(contact));
showContactAsSelected(contact);
}
}
});
}


With these changes, the user can now click through various Contacts in the Contact Management application and the Back button will back the user up through those clicks!



Bookmark Support



Our Contact Management application is currently designed to display a list of Contacts on the left-hand side. In its initial state, there is no Contact selected. At this point, the user can select a Contact and the ‘Contact Details UI Component’ will display the selected Contact. If we did nothing special to add Bookmark support, the URL the user captures after their click to the selected-contact would not return them to a page where the contact was selected. It would simply return the user to the Contact List application in its initial state, having no Contact selected. For our Contact List application, it would be better if the URL the user bookmarked could return the user to a page where a particular contact was selected.



Considering what we added above for ‘Back’ support, there is a lot of overlap for what we need to get URL/Bookmark support. When the user goes in to the app initially, they are at a URL like this:

http://localhost:8888/com.gwtdesign.history.contactlist.ContactListTest/ContactListTest.html



With the ‘Back’ support we added above, they click on ‘Jim’ and the URL changes to look like this:

http://localhost:8888/com.gwtdesign.history.contactlist.ContactListTest/ContactListTest.html#Jim



For URL/Bookmark support, we now need to be able to capture the ‘Jim’ link, navigate to some random web page outside of the Contact List Application, and then be able to go back to the Contact List application with the ‘Jim’ link. With only the Back support that we’ve added, this will NOT work. Going back to the Contact List Application with the ‘Jim’ link puts the user in the initial state of the Contact List Application. The reason is that a History value-change event is not raised when the HTML host page is first loaded. Therefore, the History ValueChangeHandler we have created in our ContactListPresenter will not get called when the page first loads.



GWT has provided an API to force this History value-change event to be raised. It is the History.fireCurrentHistoryState(). This will typically be called at the end of the Entry Point’s onModuleLoad() since all the valueChangeHandlers are expected to be in place to handle the event.



By putting a call History.fireCurrentHistoryState() as the last line of our Entry Point’s onModuleLoad() method, we can see that the URL/Bookmark support is working!



Putting it all together for the Contact List, this is now approximately what happens when the user selects a Contact from the Contact List:



image



More Browser Navigation Support



In the prior sections, we made some enhancements to the Contact Management application so that we can have Back and Bookmark support. That’s good, but there’s still an issue. Even though the names in the Contact List sort of behave like links (click on them and they do what we want them to do), the names in the list don’t look like links. They just look like plain text.



We could treat this as a styling issue and make sure they have all the link styles (e.g. underline) to ensure they look like typical web links. However, doing this will still leave the Contact links missing some browser features that users commonly expect on links: Open in New Tab, Open in New Window, Copy Shortcut, etc.



Let’s make a few tweaks to the Contact List links so that these features are all available. Earlier in the document, we implemented the Contact List names as Anchors. To give them the desired behavior, we set the text on them to be the Contact’s name and put an onClick() listener on the links so we could change the page how we wanted when the user clicked. So the pseudo-HTML that gets generated sort of looks like this:



<a onClick=“showJimInContactDetail();”>Jim</a> 


By not have the href set, we lose the browser support we’re looking for to copy shortcut, open a new window, etc. The anchor doesn’t behave like a link. Specifically, the browser doesn’t even present the right-click context menu. We could in theory change it to look more like:



<a href=”javascript:showJimInContactDetail();”>Jim</a> 


Now the anchor will behave like a link in that the browser will present the right-click context menu but the navigation functions in that menu won’t work. If the user, for example, copies the shortcut of the link, all they are copying is the JavaScript call which will do nothing for them if they bookmark it and try to use it at a later date.



In order to get the browser behavior we want, the link will need to look more like this, where the HREF has the history token that our Contact Management application understands:



<a href=”#Jim”>Jim</a>


If the link looked like this and our Contact Management app continued to keep its GWT History interactions, then we’d have everything: the Back support, the Bookmark support, and the New Tab/New Window/Copy Shortcut/etc. support.



To do this, let’s have our ContactListView.addContact() return an interface on which the Presenter can do more than just add click handlers and change the text:



public interface ContactListView {
public IAnchor addContact(String contactName);
}


The IAnchor interface will extend HasClickHandlers, HasText as expected and we’ll also add a method to set an internal href:



public interface IAnchor extends HasClickHandlers, HasText {
public void setInternalHref(String anchor);
}


And the AnchorImpl will implement that method like so:



public class AnchorImpl extends Anchor {
public void setInternalHref(String anchor) {
super.setHref("#" + anchor);
}
}


Now we can go back to the ContactListPresenter and set that property on the link:



	public void setContactList(Collection contacts){
this.contacts.clear();
for (final Contact contact : contacts){
final IAnchor anchor = contactListView.addContact(contact.getFirstName());
anchor.setInternalHref(contact.getFirstName());
anchor.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {
History.newItem(contact.getFirstName());
}
});
this.contacts.put(contact, text);
}
}


If the user clicks on the link normally, the History.newItem() is called in the anchor’s ClickHandler and the Contact List Presenter will fire off a ContactSelectedEvent from its History.ValueChangeHandler. If the user were to right-click/New Window on the link, then the page will open using the anchor’s HREF. This re-loads the host-page with the anchor’s HREF. This means the Entry Point’s onModuleLoad() method will execute and the last part of the onModuleLoad() method will call in to GWT’s History.fireCurrentHistoryState(). At this point, the Contact List Presenter will fire off a ContactSelectedEvent from its History.ValueChangeHandler and the user will see the appropriate contact selected in their new page.



Now the links have the full browser navigation support our users would expect!



image



This technique we just used leveraged the GWT’s Anchor.setHref() and then our code made a call to History.newItem(). That was more of an illustration to progressively enhance what we already had. In fact, GWT’s Hyperlink class has some of this built in for free. We can construct the Hyperlink with a “targetHistoryToken” and it will wire up the event-handling to call History.newItem() if a user clicks on the link. Then if we used this, our ContactListPresenter would not need to add any click-handlers to the link. All it would need to do is pass the appropriate targetHistoryToken in to the Hyperlink.



Back and Bookmark Summary



In this post we looked at what the GWT framework offers an application to support the Browser’s Back button and support Bookmarking. This support is primarily provided by the through use of the following methods on the History class: addNewItem(), addValueChangeHandler(), and fireCurrentHistoryState().



Although the GWT History methods provide the underpinnings for an application to provide Back Button and Bookmark support, the way we used the History methods in this post is probably too low-level for any reasonably complex page. In the next post, we’ll discuss problems with how the History class was used in this post and also look at a ways to address those problems.

Thursday, February 18, 2010

Instance Creation and Dependency Injection and GIN

In the prior posts, we’ve taken a high-level look at the various Java classes we’d need to build the client side of an MVP Contact Management application. We saw how to build a testable ContactDetail UI component. We saw how to build a testable ContactList UI component. However, the thing that wires them together, the AppController, is not all that testable. It has code in it that looks like the following:
	private void initContactDetailPresenter(){
ContactDetailViewImpl contactDetailViewImpl = new ContactDetailViewImpl();
contactDetail = new ContactDetailPresenter(contactDetailViewImpl);
}

AppController is directly constructing a ContactDetailViewImpl and, therefore, we cannot mock the ContactDetailView in an attempt to test the AppController. One approach to solve this would be to create a factory that we could use to get the ContactDetailView implementation.

public interface AppFactory {
ContactDetailView getContactDetailView();
ContactListView getContactListView();
}

public class AppFactoryImpl implements AppFactory {
ContactDetailView getContactDetailView(){
return new ContactDetailViewImpl();
}
ContactListView getContactListView(){
return new ContactListImpl();
}
}

Now our initContactDetailPresenter() method could look like so:<

private void initContactDetailPresenter(AppFactory appFactory){
ContactDetailView contactDetailView = appFactory.getContactDetailView();
contactDetail = new ContactDetailPresenter(contactDetailView);
}

Then at test time, we could re-implement that factory so it returns a mock ContactDetailView.

public class MockAppFactory implements AppFactory{
ContactDetailView getContactDetailView(){
return createNiceMock(ContactDetailView.class);
}
ContactListView getContactListView(){
return createNiceMock(ContactListView.class);
}
}

One thing worth noting is that, as object construction goes, we’re not only creating a ContactDetailView, but we’re also injecting it in to the ContactDetailPresenter since ContactDetailPresenter has a dependency on a ContactDetailView implementation. This is DI -- dependency injection (see DI link for more information). We have used dependency injection frameworks in Java code to make each application unit testable and loosely coupled to the other units in the application. Such a framework would enable us to do things like have the ContactDetailPresenter already have the ContactDetailView injected in to it. In “normal” Java code, we might have accomplished this with the Spring dependency injection framework. However, Spring is not a GWT module so that is not available to use in client-side GWT code. It turns out that Google has developed a very capable Java dependency injection framework called Guice and this is also not a GWT module. However, it also turns out that they’ve developed a client-side equivalent to Guice which is called Gin and with Gin, we can do all the dependency injection we need.

Let’s keep looking at the Contact Management code to see what Gin will do for us. With our factory approach, we developed an AppFactory implementation which created the appropriate ContactDetailView and ContactListView implementations. Before we do anything, we’re going to change our terminology to use the word “injector” instead of factory. In an application that heavily uses DI, factories become less of a prominent feature so that’s one good reason to change terms. Also, the GIN framework and documentation and sample applications all use the term “injector” so it will be better if we are speaking the same language. The first thing Gin does is eliminate the need to implement factories. All that’s needed instead is a “module” to tersely say which implementation should be used for a particular interface.



public class AppGinModule extends AbstractGinModule{
@Override
protected void configure() {
bind(ContactListView.class).to(ContactListViewImpl.class);
bind(ContactDetailView.class).to(ContactDetailViewImpl.class);
}
}

Then our injector (previously factory) interface, via an annotation, specifies the module which has the configuration:

@GinModules(AppGinModule.class) 
public interface AppInjector extends Ginjector{
ContactDetailView getContactDetailView();
ContactListView getContactListView();
}

In our entry point, we can now call GWT.create() to have Gin return an implementation of our injector (previously factory). This injector’s methods now return the appropriate interface implementations based the module configuration:

AppInjector appInjector = GWT.create(AppGinModule.class);


This is sort of cool. We’ve defined our injector implementation with these bind().to() method calls in a configuration. Also, this configuration is fully within the core Java language, no XML files. This means it is fully type-safe, not possible to have spelling errors. This means that it is trivial using a Java IDE to find references to the ContactDetailViewImpl and see the Gin Module that is using it and how it is being used. It also means it gives us the ability to do safe refactoring if we need to rename classes, move them to different packages, etc.



But we can do more than just implementation selection. Gin can also construct ContactListPresenter and ContactDetailPresenter for us and inject its view implementation dependencies. Then our AppController doesn’t need to get the ContactDetailView from the AppInjector at all. All it needs is to do is get the ContactDetailPresenter from the AppInjector and Gin will take care of injecting the appropriate view in to the presenter.



There are two things we need to do to make this happen:



1) We need to add getContactListPresenter() and getContactDetailPresenter() methods to our AppInjector interface and



2) We need to annotate the presenters’ constructors with an @Inject annotation to let Gin know it can inject dependencies in to it.



Since ContactListPresenter and ContactDetailPresenter are not interfaces, the Gin Module configuration does not need to change at all. Also, since our AppController no longer needs to get instances of the views directly, those can be removed from the AppFactory interface. Now the interface looks like:



@GinModules(AppGinModule.class) 
public interface AppInjector extends Ginjector{
public ContactListPresenter getContactListPresenter();
public ContactDetailPresenter getContactDetailPresenter();
}


And the constructor to ContactDetailPresenter with its annotation looks like:



@Inject
public ContactDetailPresenter(ContactDetailView contactDetailView){
this.contactDetailView = contactDetailView;
}


Now the AppController can simply init its ContactDetailPresenter like so:



	private void initContactDetailPresenter(AppFactory appFactory){
contactDetail = appFactory.getContactDetailPresenter();
}


This highlights the high-level capabilities of Gin dependency injection. For the interfaces in the application, we configure the associated implementations. We annotate @Inject where we want Gin to inject dependencies and, at runtime, Gin will provide instances of classes all wired up with their dependencies injected. There are many additional capabilities for additional DI use cases. See this link for more details.



Although we saw the capabilities, we didn’t fully take advantage of them. One of the ideas of dependency injection is that factories need not be a prominent part of the application and we still have a factory sent in to the AppController so that the presenters can be acquired. The final thing we’d do here to take optimally take advantage of the DI capabilities is to have the ContactDetailPresenter and ContactListPresenter injected in to the AppController. Then all the injector needs to do is return an instance of the AppController and everything from the AppController all the way down to the views will be wired up for use.



@GinModules(AppGinModule.class) 
public interface AppInjector extends Ginjector{
public AppInjector getAppController();
}


And the entry point logic can look something like so:



	AppInjector appInjector = GWT.create(AppGinModule.class);
new AppController(appFactory).go(contacts);


With this, our Contact Management application does not create any presenters or views directly and does not managing wiring them up together. This goes a long way to creating loosely-coupled units of the overall application. Aside from that, the Gin framework has an innovative, crisp way of configuring the dependencies.



Testing



In order to get an injector implementation, our code called GWT.create(). GWT.create is a special object-creation utility in the GWT library which heavily depends upon the GWT environment. This means that, in order to create a GIN injector in a JUnit test, the JUnit must extend GWTTestCase and this is a barrier to testability since GWTTestCase is much slower than a “normal” JUnit. This does not have to be a problem as long as we consider it ahead of time. In our Contact Management AppController scenario, we removed “factories”/”injectors” out of most of our application code except the Entry Point. In that case, there really is no issue. At test time, we can wire our dependencies up however we want and we have no strong reliance on GIN in our JUnits. However, this may not be realistic in all applications and we may want to pass an injector in to parts of the application so that the Injector can operate behave more like a factory. An example of this may be a portal where the portal viewing area could display 1 of 20 different types of presenters. It may not be ideal to have GIN initialize/inject all 20 presenters when the application starts in which case, we’d want the portal to create the appropriate presenter as needed. In this case, it would be reasonable to pass an Injector in to the PortalPresenter so a injector/factory is available which can then help the PortalPresenter create the appropriate child-presenters when and if they are needed. In this case, we’ll want a GIN injector implementation that can behave how we want at test time to pass in to the PortalPresenter.



We mentioned earlier that Gin is the GWT-equivalent of Guice and at this time, it’s worth noting that the @Inject annotation we used is actually from the Java Guice library. This means that, outside of a GWT environment, we can use Guice as our DI framework. And since when testing, we do not want to be forced in to a GWT environment, Guice is a good choice to replace Gin at test-time. Guice also has the concept of a Module where we can bind implementations to interfaces and the methods/semantics are nearly comparable. For our Contact Management scenario, it could look like the following:



	public static class MockAppModule extends AbstractModule{

@Override
protected void configure() {
bind(ContactListView.class).toInstance(createNiceMock(ContactListView.class));
bind(ContactDetailView.class).toInstance(createNiceMock(ContactDetailView.class));
}
}


And here’s a tiny utility that will dynamically generate a Gin Injector implementation outside of a GWT context:



	/**
* Builds an implementation of the GinInjector which does not require a GWT runtime environment.
*


* This can be used in a JUnit that does not extend {@link GWTTestCase}.
*
* @param type of application injector to create
* @param guiceModule the Guice module
* @param appInjector type of application injector to create
* @return an implementation of the GinInjector which does not require a GWT runtime environment.
*/
public static T guiceCreate(Module guiceModule, Class appInjector){
Injector guiceInjector = Guice.createInjector(guiceModule);
return getServerSideGinInjector(guiceInjector, appInjector);
}

/**
* This creates the equivalent of a GinInjector without needing to call GWT.create().
* This can be useful for JUnits.
*
*/
public static T getServerSideGinInjector(final Injector injector, Class appInjector){
T result = (T)Proxy.newProxyInstance(Injector.class.getClassLoader(),
new Class[]{appInjector}, new InvocationHandler() {

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class returnType = method.getReturnType();
return injector.getInstance(returnType);
}
});
return result;
}



Now we can call guiceCreate() and it will create an implementation of the specified Gin Injector interface and it will be configured according the specified Guice module definition.



AppInjector mockAppInjector = guiceCreate(new MockAppModule(), AppInjector.class);
assertNotNull("The controller should be available outside of a GWT environment", mockAppInjector.getAppController());


Usage



GIN is not part of the core GWT library. It is an extension that was created and is well-supported by Google. In order to use it, a few things are needed:



1) GIN must be included in the application by inheriting it in the GWT application XML:



<inherits name="com.google.gwt.inject.Inject"/>



2) The GIN jar must be on the classpath at compile-time and run-time. The Guice and Aop Alliance jars must be on the classpath at compile and test-time.



Summary



In this post, we looked at how and why to use Dependency Injection. In particular, we looked at using GIN to loosely couple the pieces that make up our applications. Additionally, we looked at how to make this approach viable outside of a GWT environment so that we can have a good testing strategy.

Really Testing the View (Web Mode)

Although what we did in the last post was useful to see/test the view, we were not actually running through the real/production JavaScript. We were just running in “development” (a.k.a. Hosted) mode. In order to test the view through using real/production JavaScript, we need to go through a compile step, deploy that to a web server, and run the app. from there. This is called running in ‘Web Mode’. For the gory differences between Hosted and Web Mode, see this link: http://vinaytechs.blogspot.com/2009/09/google-web-toolkit-hosted-vs-web-mode.html .

To manually compile a project in Eclipse, select the ‘GWT Compile Project’ from the toolbar:

image

And we’ll get a dialog where we can usually accept the defaults:

image

After clicking ‘Compile’, GWT will do a lot of work and the Console will display details of that work. For example:

Compiling module com.gwtdesign.mvp.contactlist.ContactListTest
Compiling 6 permutations
Compiling permutation 0...
Compiling permutation 1...
Compiling permutation 2...
Compiling permutation 3...
Compiling permutation 4...
Compiling permutation 5...
Compile of permutations succeeded
Linking into C:\workspace\DesignStandards\war\com.gwtdesign.mvp.contactlist.ContactListTest.
Link succeeded
Compilation succeeded -- 27.812s


Now we can take the directory and move it in to any web server. In this screenshot, I show it moved in to an apache/tomcat web server:



image



And can hit the Tomcat-appropriate URL to see the page running the real/production Java code: http://localhost:8080/com.gwtdesign.mvp.contactlist.ContactListTest/ContactListTest.html



image



We have now run the app. in web mode and this is using the exact same code that we would deploy to a production server. Because our test relied on no server-side code, it was rather trivial to just move the HTML host page and compiled JavaScript in to any random web server that can serve up static resources. If the view has a reliance on server-side functionality, then a simple web server is not sufficient for the test and an app server will also need to be appropriately configured so the server-side of the application is available.



Debugging in Production Mode



A very cool feature of GWT is that, even in production mode, it maintains the ability to debug the JavaScript as Java. To do this, you start up the GWT app in Eclipse using ‘Debug As.. Web Application’:



image



Now, we can append the ‘gwt.codesvr’ parameter to the production URL (e.g. gwt.codesvr=127.0.0.1:9997) and that will now redirect the JavaScript execution to our Eclipse Java environment!!!



Here’s the full URL for this test (note that localhost:8080 is the Apache Tomcat server as opposed to the localhost:8888 we were previously using to run in Development mode): http://localhost:8080/com.gwtdesign.mvp.contactlist.ContactListTest/ContactListTest.html?gwt.codesvr=127.0.0.1:9997



image



With this capability, it really opens up our options. It essentially enables us to hook a Java-based debugger in to any user’s browser. Once the gwt.codesvr parameter is added to the URL, all the JavaScript is now run through our Eclipse environment. This, not only gives us the ability to troubleshoot an issue, but also the ability to test fixes since we can be code changes and they’ll be reflected on the browser in real-time. To illustrate, I’ve changed my Eclipse code to put ‘Sam’ in the list and have deployed NOTHING to my Apache Tomcat server. When I click refresh on my browser, I now see ‘Sam’ in the list:











image

Wednesday, February 17, 2010

Testing the View (Development Mode)

Now that we have a View implementation for the Contact List UI Component, it would be nice to see it rendered in a web page. We don’t have the full Contact List application ready so, at this point, we can only render the ContactListView implementation. Before starting to fill what’s needed to run this code, it will first be helpful to look at the anatomy of a GWT application:

image

For now, we’ll ignore the Production side of this diagram since we’re still filling out our development source, but feel free to refer back to it later as you look at the deployed application. To render a page that uses GWT-generated JavaScript, 4 primary things are needed in the development source:

  1. Client-side Java. This is what we’ve been building so far. The Models, Views, and Presenters were all part of the Client-Side Java which we ultimately want executed inside the browser as JavaScript.
  2. An Entry Point Java class, a class extending the GWT EntryPoint class. This is needed for any page that will execute GWT-generated JavaScript. It essentially bootstraps the page generating any initial HTML and wiring up all the event listeners to handle the user’s actions.
  3. A Module definition, an XML file that defines, among other things, what Java classes will be used to make up this JavaScript application.
  4. An HTML host page that will reference the GWT-generated JavaScript file.

To get this test started, we’ll initially build the ‘Entry Point’. For the ContactList UI Component, we have our View and Presenter implementations so the only things we need to mock for the View to be rendered are the Model objects.

	public void onModuleLoad() {

// wire up presenter with view implementation
ContactListViewImpl view = new ContactListViewImpl();
EventBus eventBus = new EventBusImpl();
ContactListPresenter presenter = new ContactListPresenter(view, eventBus);

// mock Contacts
Collection contacts = new ArrayList();
contacts.add(new ContactImpl("Jim"));
contacts.add(new ContactImpl("Joe"));
contacts.add(new ContactImpl("Jane"));

// apply contacts to view
presenter.setContactList(contacts);

// put contact list on page
RootPanel.get().add(view);
}


Next we’ll write our Module definition file. The Module definition file will be called ContactListTest.gwt.xml and looks like:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.0/distro-source/core/src/gwt-module.dtd">
<module>
<inherits name="com.google.gwt.user.User" />

<!-- Specify the app entry point class -->
<entry-point class='com.gwtdesign.mvp.contactlist.testui.ContactListTestEntryPoint'/>

<source path="client"/>
<source path="shared"/>
<source path="testui"/> <!-- this is where the entry point is in the test/src -->
</module>


The entry-point element references the Entry Point java class we wrote in the prior step. The source paths refer to the sub-packages with Java code that should be compiled in to JavaScript for our web page. The ‘inherits’ tag is analogous to a java import. com.google.gwt.user.User is a GWT Module that is leveraged by this Module. The ‘User’ Module must be imported in to every GWT Module. Other than what’s seen in this XML, there are a couple implicit elements not seen in the XML:




  • Because the ‘rename’ attribute was not specified for the ‘module’ element, the compiler assumes it should output the compiled JavaScript to a directory named com.gwtdesign.mvp.contactlist.ContactListTest in the web output directory. This is derived from the location and name of the Module file.


  • Because the ‘public’ element was not used, it is assumed that a directory named ‘public’ under the Module file will contain static resources for the web application.



Lastly, we need to define the HTML host file that will call the GWT-compiled JavaScript file. For our trivial test, it will look as follows:



<!DOCTYPE HTML> 
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" language="javascript" src="com.gwtdesign.mvp.contactlist.ContactListTest.nocache.js">
</script>

</head>
<body>
<h1>Contact List Test Page</h1>
</body>
</html>


Looking at the full directory structure, you’ll see that the test code is isolated to the test/src folder while the production code is in the main src folder:



image



One interesting thing when looking at the source tree is that the UI logic is contained in src/com.gwtdesign.mvp.contactlist.client yet the JUnits that test it are in a ‘test’ sub-package, test/src/com.gwtdesign.mvp.contactlist.test. This is non-standard. Typically, JUnits live in the same Java package as the Java code they test. I may find a better way to do this, but for now, this seemed like the best way to have the Entry Point and HTML host page live in the test/src. If I didn’t put the JUnits somewhere else, the <source path="client"/> in the Module file would cause the GWT-compiler to try compiling the JUnits in to JavaScript.



In Eclipse, we now can Run as... ‘Web Application’ and the page can be viewed:



image



After the Web Application starts, the ‘Development Mode’ window in Eclipse will look something like the following:



image



However, we did not put our HTML host page in the war directory, so the GWT Eclipse Plugin did not provide the appropriate URL for our test page. The URL we’ll use looks like: http://localhost:8888/com.gwtdesign.mvp.contactlist.ContactListTest/ContactListTest.html?gwt.codesvr=localhost:9997



And here is the beautiful page that we see when hitting the URL:



image



What we’ve just done is pretty cool!




  • From Eclipse, the Run As… Web Application did some magic and now we’re able to hit our web page. There is no big app server (e.g. JBoss, Weblogic, etc.) that we need to deploy to in order to run this type of test.


  • By launching the test using Debug As… Web Application, we can set a break point in any of our Java code and interactions with the web page will break in Java code as we would hope! Even though GWT compiled the Java in to JavaScript, GWT has still maintained the capability to debug the JavaScript as the Java code that we originally wrote.


  • We’ve built a test to render just one component of the Contact List application and we’ve rendered this single UI component in isolation. Not only have we rendered it in isolation, but it is all wired up to emit a ContactSelected event if the user clicks on one of the contacts. This demonstrates a few things about the design/implementation methodology:

    • Seeing this UI Component rendered in isolation with all its functionality demonstrates that this component is reusable in case we wanted to use it somewhere else. It’s clearly not coupled to the Contact Details UI Component.


    • A typical interactive web page is very complex, made up of many UI components. When a large web page is not behaving as expected, it may be quite useful to be able to render each component in isolation as a means to finding a hard-to-track down bug.





To quickly demonstrate that we can do something when a Contact is selected, I’ll tweak the Entry Point slightly by adding the following lines of code at the end:



		eventBus.addHandler(ContactSelectedEvent.TYPE, new ContactSelectedEvent.ContactSelectedEventHandler() {

public void handleEvent(ContactSelectedEvent contactSelectedEvent) {
Window.alert("Contact selected: " +
contactSelectedEvent.getSelectedContact().getFirstName());
}
});


And now we can click on ‘Jim’ and see the alert:



image



In this post, we saw how to build out our view implementation with core GWT Widgets and also learned how to manually test a UI Component in isolation.

Implementing the View

We’ve built and tested several parts of our Contact List web page yet we haven’t seen any actual HTML. Based on the responsibility of a View in MVP, we would expect the View to be where HTML is emitted. We have defined the interfaces of our views in prior posts and, in this post, we’ll start looking at the views’ implementations.

In a typical GWT application, a View is implemented by a Widget. A Widget in GWT does exactly what we described a View should do in our MVP definition. It generates HTML and support events that a user could take on that HTML. At the UI Component level, the ContactListView will be implemented by one Widget and the ContactDetailView will be implemented by another Widget. And within each of those UI Components, particular UI elements will also be implemented by Widgets.

GWT has many Widgets available in their core library. If a Widget is needed that GWT doesn’t have, there are multiple options. Most typically, though, we would either develop it ourselves or look to a third-party library that has already developed it. The GWT showcase (http://gwt.google.com/samples/Showcase/Showcase.html) demonstrates many of the Widgets that GWT delivers in its core library.

ContactListView

For our ContactListView implementation, we will extend a GWT Widget called VerticalPanel. This will layout the Contacts vertically in an HTML Table.

public class ContactListViewImpl extends VerticalPanel implements ContactListView{
public HasClickHandlers addContact(String contactName){
// TODO: implement
return null;
}
}


Immediately, we see that we have another Widget decision to make in order to return a HasClickHandlers implementation from the addContact() method. Remember that HasClickHandlers is an interface in the core GWT library and it is no coincidence that a Anchor Widget exists which implements this interface.



public class ContactListViewImpl extends VerticalPanel implements ContactListView{
public HasClickHandlers addContact(String contactName){
Anchor link = new Anchor();
link.setText(contactName);
super.add(link);
return link;
}
}

Testing the Presenter

In the prior posts, we discussed a Passive View for the purposes of testability and also talked about using an Event Bus to decouple one UI component from another. Remember that the ContactDetailPresenter functionally will be responsible for 1) displaying a selected Contact and 2) enabling a Contact to be updated. Given the design we used to build out the presenter, we should now be able to test, in isolation, that it correctly does both of those things. “In isolation” means that we want to test that the ContactDetailPresenter does what it’s supposed to do without having using a ContactListPresenter in the test. Since this is an automated, non-interactive test and we don’t have an actual browser, it will be important that we can mock the ContactDetailView. We threw around the word “mock” loosely before, but now that we’re actually writing tests, we need to be more clear about what this means and how to do it. For the tests written in this example, we will use EasyMock and that library will be implementing many methods you see in the tests such as createMock(), expect(), andReturn(), etc. It is not the scope of the post to describe EasyMock in detail, but know that having a good approach to mocking objects is a critically important aspect to writing/maintaining a solid automated test suite.

The first test validates that the ContactDetailPresenter will send a selected Contact’s first name to the ContactDetailView. The test starts out by 1) setting up its expectations that the view will receive a first name. Then 2) simulates a Contact-selection by posting a ContactSelectedEvent to the event bus and lastly 3) verifies that the View did, in fact, have the selected Contact’s first name applied to it. Here is the test:


public void testContactSelected (){
EventBus eventBus = new EventBusImpl();

String firstName = "mockFirstName";

// set up a Contact with a particular first name
Contact contact = createMock(Contact.class);
expect(contact.getFirstName()).andReturn(firstName);

// 1) set up expectation that view should be set with the first name
ContactDetailView view = createMock(ContactDetailView.class);
HasChangeHandlers mockHasChangeHandlers = createMock(HasChangeHandlers.class);
expect(view.setFirstName(firstName)).andReturn(mockHasChangeHandlers);

replay(view, contact);

ContactDetailPresenter presenter = new ContactDetailPresenter(view, eventBus);

// 2) now fire event and ensure that view is set with first name
ContactSelectedEvent contactSelected = new ContactSelectedEvent(contact);
eventBus.fireEvent(contactSelected);

// 3) verify the View had the Contact’s first name set on it
verify(view);
}


The next test validates that a user updating the first name in the Contact Detail UI will cause the ContactDetailPresenter to 1) change the first name of the Contact in the Model and 2) emit an event that the Contact was updated. To accomplish this, the test will first mock up the presenter’s dependencies to behave as needed for the test. Next, the test will simulate the first name change. Lastly, the test will verify its expectations.




public void testContactUpdated(){
String firstNameBefore = "mockFirstNameBefore";
final String firstNameAfter = "mockFirstNameAfter";

// mocks up view to have a TextInput that our test can control
ContactDetailView view = createMock(ContactDetailView.class);
final TextInput firstNameInputMock = new TextInputMock();
expect(view.setFirstName(firstNameBefore)).andReturn(firstNameInputMock);

/*
* set up a mock Contact to accept a firstName on setFirstname and
* return that same first name on getFirstName.
*/

Contact contact = createMock(Contact.class);
final Capture firstNameCapturer = new Capture();
contact.setFirstName(capture(firstNameCapturer));
expectLastCall().anyTimes();
expect(contact.getFirstName()).andAnswer(new IAnswer() {

public String answer() throws Throwable {
return firstNameCapturer.getValue();
}

}).anyTimes();

replay(contact, view);

EventBus eventBus = new EventBusImpl();

// add handler to event bus to listen for ContactUpdatedEvents
final ContactUpdatedEvent[] updatedEvent = {null};
eventBus.addHandler(ContactUpdatedEvent.TYPE,
new ContactUpdatedEvent.ContactUpdatedEventHandler() {

public void handleEvent(ContactUpdatedEvent contactUpdatedEvent) {
updatedEvent[0] = contactUpdatedEvent;
}
});

// wire up presenter with its dependencies
ContactDetailPresenter presenter = new ContactDetailPresenter(view, eventBus);
contact.setFirstName(firstNameBefore);
presenter.setContact(contact);

// simulate the first name change on the TextInput
firstNameInputMock.setText(firstNameAfter);

// verify expectations
assertNotNull("The ContactUpdatedEvent should have been emitted when the text was changed on the input", updatedEvent[0]);
assertEquals("The name of the Contact should have been changed to the new name",
firstNameAfter,
updatedEvent[0].getContact().getFirstName());
}


This is extremely powerful. We’ve tested some core aspects of our interactive web application without actually having a user interface written or even established. We have not yet built anything that resembles HTML. Given this, we can really start seeing the flexibility of this design. Since most of the Contact List UI Component works and is testable with no View, it really illustrates how little we are locked in to a particular UI layout.



In this post we looked at techniques for testing a Presenter. This is a critical component to test since it contains a lot of UI logic and, due to our MVP design pattern, it is testable.

Followers