Matt RaibleMatt Raible is a Web Developer and Java Champion. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Modularizing GWT Applications with GWT-Maven

Last week, I spent some time modularizing the GWT application I'm working on. By modularizing, I mean splitting the code from one GWT module into a "core" and "webapp" module. The reason for doing this was so the "core" module could be used by another GWT application. Creating GWT Modules is fairly straightforward, but it wasn't as intuitive as expected when using the gwt-maven-plugin.

The hardest part of moving the code was figuring out how to run tests in the new "core" module. After getting it all working, it seems easy enough. Hopefully this post will make it easy for others. Here's the steps I'd recommend:

  1. Convert your GWT project into a multi-module project where you have a top-level pom.xml and two sub-modules (e.g. gwt-core and gwt-webapp).
  2. Do the normal single-to-multi-project Maven stuff like declaring the <parent> element in the modules and moving plugins/dependencies to the top-level pom.xml.
  3. Refactor your gwt-webapp project to push down all shared classes (and their tests) to gwt-core.
  4. In the gwt-core project, include *.xml and *.java in your JAR so GWT can extract/compile the source code when building gwt-webapp.
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
    
  5. In gwt-core/src/main/java, create a Core.gwt.xml that references the modules you'd like to use in all your applications. For example:
    <module>
        <inherits name="com.google.gwt.user.User"/>
        <inherits name="com.google.gwt.i18n.I18N"/>
        <inherits name="com.extjs.gxt.ui.GXT"/>
        <inherits name="pl.rmalinowski.gwt2swf.GWT2SWF"/>
    </module>
    
  6. Now the tricky part begins, mostly because of how the gwt-maven plugin currently works. In src/test/java, create a NoOpEntryPoint.gwt.xml that inherits your Core module and defines an EntryPoint.
    <module>
        <inherits name="com.company.app.Core"/>
        <entry-point class="com.company.app.NoOpEntryPoint"/>
    </module>
    
  7. Create a NoOpEntryPoint.java class in the same directory as NoOpEntryPoint.gwt.xml.
    public class NoOpEntryPoint implements EntryPoint {
        
        public void onModuleLoad() {
            // do nothing
        }
    }
    
  8. In any class that extends GWTTestCase (I usually create a parent class for all tests), reference the NoOpEntryPoint in the getModuleName() method.
        @Override
        public String getModuleName() {
            return "com.company.app.NoOpEntryPoint";
        }
    
  9. Lastly, in the gwt-maven plugin's configuration (in gwt-core/pom.xml), reference the NoOpEntryPoint in <compileTargets>, a non-existent file in <runTarget> and only the "test" goal in the executions.
    <plugin>
        <groupId>com.totsp.gwt</groupId>
        <artifactId>maven-googlewebtoolkit2-plugin</artifactId>
        <version>2.0-beta26</version>
        <configuration>
            <compileTargets>
                <value>com.company.app.NoOpEntryPoint</value>
            </compileTargets>
            <runTarget>com.company.app.NoOpEntryPoint/doesntexist.html</runTarget>
            <logLevel>INFO</logLevel>
            <style>OBF</style>
            <noServer>false</noServer>
            <extraJvmArgs>-Xmx512m</extraJvmArgs>
            <gwtVersion>${gwtVersion}</gwtVersion>
            <testFilter>*GwtTestSuite.java</testFilter>
            <testSkip>${skipTests}</testSkip>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>test</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

The results of modularizing your application are beneficial (shared code) and detrimental (you have to mvn install gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I'd love to hear about it.

Posted in Java at Mar 23 2009, 10:36:08 AM MDT 11 Comments

GXT's MVC Framework

For the past couple of months, I've been developing a GWT application using a mix of plain ol' GWT and GXT widgets. When I first started developing it, I didn't know how to best organize my code and separate the logic. The solution I came up with was to adopt some sort of MVC framework. Since I was already using GXT, I opted for GXT's lightweight MVC implementation.

As mentioned in Testing GWT Applications, GXT's MVC doesn't have much documentation. The best reference documentation seems to be Christian's Getting started with Ext-GWT: The Mail reference application.

Page Transitioning with Dispatcher
After working with GXT MVC for a couple months, I'm still not sure I fully understand how navigation and event dispatching works. The biggest point of confusion for me is how to best use GXT's Dispatcher class.

The problem with Dispatcher is it has a two methods that seem to do the same thing.

  • forwardEvent (4 variations)
  • dispatch (3 variations)

In addition to these methods in Dispatcher, there's two fireEvent methods in GXT's View class. According to my calculations, that means there's 9 different options for transitioning from one view to the next. Which one is best to use?

From what I've learned, I think it's best to use fireEvent in Views and forwardEvent in Controllers and other widgets. IMO, dispatcher should never be used except in your HistoryListener's implementation onHistoryChanged method. The important thing to realize about this method is it should only work if the View's Controller is registered for the event.

  protected void fireEvent(AppEvent event) {
    Controller c = controller;
    while (c != null) {
      if (c.canHandle(event)) {
        c.handleEvent(event);
      }
      c = c.parent;
    }
  }

However, fireEvent seems to work even when the View's Controller isn't registered for that event. This is because onHistoryChanged gets called in the EntryPoint. For experienced GXT MVC users, does this navigation handling mesh with your findings?

The most important thing for navigation to work successfully is enabling History support. The next section talks about how to do this effectively.

Enabling History Support
To help explain things better, I created a simple GWT MVC Example application and used Maven to create an archetype with it. You can create a project from the archetype using the following command:

mvn archetype:create -DarchetypeGroupId=org.appfuse.archetypes \
-DarchetypeArtifactId=gwt-mvc -DarchetypeVersion=1.0-SNAPSHOT \
-DgroupId=com.mycompany.app -DartifactId=myproject \
-DremoteRepositories=http://oss.sonatype.org/content/repositories/appfuse-snapshots

To enable history support in this application, I implemented HistoryListener in my EntryPoint (Application.java) and added the following logic to initialize:

// If the application starts with no history token, redirect to 'home' state
String initToken = History.getToken();
if (initToken.length() == 0) {
    History.newItem(HistoryTokens.HOME);
}

// Add history listener
History.addHistoryListener(this);

// Now that we've setup our listener, fire the initial history state.
History.fireCurrentHistoryState();

In this example, HistoryTokens is a class that contains all the URLs of the "views" in the application.

public class HistoryTokens {
    public static final String HOME = "home";
    public static final String CALENDAR = "calendar";
    public static final String NOTES = "notes";
    public static final String SEARCH = "search";
}

In order to make URLs like http://localhost:8080/#calendar go to the calendar view, the following logic exists in the onHistoryChanged method.

        Dispatcher dispatcher = Dispatcher.get();

        if (historyToken != null) {
            if (historyToken.equals(HistoryTokens.HOME)) {
                dispatcher.dispatch(AppEvents.GoHome);
            } else if (historyToken.equals(HistoryTokens.CALENDAR)) {
                dispatcher.dispatch(AppEvents.Calendar);
            } else if (historyToken.equals(HistoryTokens.NOTES)) {
                dispatcher.dispatch(AppEvents.Notes);
            } else if (historyToken.equals(HistoryTokens.SEARCH)) {
                dispatcher.dispatch(AppEvents.Search);
            } else {
                GWT.log("HistoryToken '" + historyToken + "' not found!", null);
            }
        }

Controllers are registered in the EntryPoint as follows:

        final Dispatcher dispatcher = Dispatcher.get();
        dispatcher.addController(new CalendarController());
        dispatcher.addController(new HomeController());
        dispatcher.addController(new NotesController());
        dispatcher.addController(new SearchController());

Controllers respond to events they're registered for. This is done in their constructor:

    public CalendarController() {
        registerEventTypes(AppEvents.Calendar);
    }

In order for navigation to work, you have to create links with history tokens1. For example, here's a link from the HomeView class:

	Hyperlink notesLink = new Hyperlink("Notes", HistoryTokens.NOTES);
	notesLink.addClickListener(new ClickListener() {
	    public void onClick(Widget widget) {
	        Dispatcher.get().fireEvent(AppEvents.Notes);
	    }
	});

You'll notice in this example, I'm using Dispatcher's fireEvent method. If I wanted to pass some data with your event, you'll need to use forwardEvent. Here's an example from CalendarView:

    Button submit = new Button("Submit");

    submit.addSelectionListener(new SelectionListener<ButtonEvent>() {
        public void componentSelected(ButtonEvent ce) {
            AppEvent<Date> event = 
                new AppEvent<Date>(AppEvents.GoHome, date.getValue(), HistoryTokens.HOME);
            Dispatcher.forwardEvent(event);
        }
    });

In this example, you could also use Dispatcher.dispatcher(), but I believe this will cause the transition to happen twice because the onHistoryChanged method gets called too. This doesn't matter for the most part, except when you start to use DispatcherListeners.

Hopefully this article has helped you understand how GXT's MVC framework works. I'm interested in learning how other GWT MVC frameworks work. If you've used one, I'd love to hear about your experience.

Friday Fun Test
Here's a test for those interested in digging into the GXT MVC example. There's a bug in this application that prevents something from happening. I'll buy a drink for the person that finds the bug and I'll buy two drinks for the person that comes up with a solution. ;-)

1. If you use the default constructor on Hyperlink and use setText(), make sure to call setTargetHistoryToken() too. If you don't, a blank history token will be used and # causes the browser to scroll to the top before a page transition happens.

Posted in Java at Mar 13 2009, 11:48:41 AM MDT 25 Comments

GWT and AppFuse

Someone recently sent me the following e-mail asking about GWT integration in AppFuse.

I see from your blog that you're spending some time with GWT at the moment. What's your plan, are you going to integrate GWT as another UI Option for AppFuse?

The reason I'm asking is that I actually checked out all of the AppFuse code from the svn repository yesterday, with the intention of starting off adding some GWT stuff in there. My intention was to start by getting a basic Maven archetype together for GWT as an AppFuse UI.

However, if you're planning on doing this yourself in the near future, then there's no point in me starting doing it, I'd have to learn how to write archetype's for a start (not that it looks too difficult) but you'd obviously do it much quicker.

Being a good open-source developer, I moved the discussion to the developer mailing list and replied there:

It's likely I'll create a version of AppFuse Light with GWT, but I doubt I'll do it in the near future. I hope to release AppFuse 2.1 first (which will include "light" archetypes). I wouldn't get your hopes up in waiting for me to do the work. However, I'd be happy to assist you in doing it. AppFuse Light is now modular and uses the AppFuse backend.

http://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven

Here's how I believe GWT should be integrated:

  1. Create an appfuse-ws archetype that serves up RESTful services (http://issues.appfuse.org/browse/APF-897).
  2. Create an appfuse-gwt archetype that consumes those services. This archetype would contain a proxy servlet that allows #1 to be on a separate host/port.

In addition to #1, I hope to convert the Struts 2 and Spring MVC archetypes to use those frameworks' REST support.

For #2, we could use SmartGWT or GXT. SmartGWT might be better since Sanjiv is a committer on this project. ;-)

I know I've been slacking on AppFuse development, but it is ski season and running to work seems to drain my late-night coding ambitions. With that being said, I'm committed to getting AppFuse 2.1 released by JavaOne (hopefully sooner). I figure it's a good week's worth of work and I'll probably have to do it late at night to find the time. That's OK though, I usually really start to enjoy it once I get into it.

Posted in Java at Mar 04 2009, 10:50:26 PM MST 5 Comments

GWTTestSuite makes builds faster, but requires JUnit 4.1

Earlier this week, I spent some time implementing GWTTestSuite to speed up my project's build process. In Hudson, the project was taking around 15 minutes to build, locally it was only taking 5 minutes for mvn test. In IDEA, I could run all the tests in under a minute. While 15 minutes isn't a long time for a build to execute, a co-worker expressed some concern:

Does Maven have to run GWT test and individual Java processes? (See target/gwtTest/*.sh) This arrangement and the overhead of JVM launches is another reason why builds take so long. As we add more GWT tests we are going to test that LinkedIn record for the slowest build ever.

After this comment, I started looking into GWTTestSuite using Olivier Modica's blog entry as a guide. It was very easy to get things working in IDEA. However, when I'd run mvn test, I'd get the following error:

Error: java.lang.ClassCastException

No line numbers. No class information. Zilch. After comparing my project's pom.xml with the one from the default gwt-maven archetype, I noticed the default used JUnit 4.1, while I had the latest-and-supposedly-greatest JUnit 4.4. Reverting to JUnit 4.1 fixed the problem. Now Hudson takes 3:15 to execute the build instead of 15 minutes.

The reason for this blog post is this doesn't seem to be documented anywhere. Hopefully other developers will find this entry when googling for this issue.

Related to making GWT faster, I also added the following line to my Application.gwt.xml file:

<set-property name="user.agent" value="safari" />

This dropped the gwt:compile time from 1 minute to 25 seconds. As explained in the documentation, you can use the "user.agent" setting to only generate one JS file for your app instead of 4. The strange thing about adding this setting was I pretty much forgot about it since everything seemed to work fine on both Safari and Firefox. When I started testing things in IE6, I started seeing a lot of JavaScript errors. After debugging for an hour or so, I realized this setting was there, removed it, and everything started working great in all browsers.

Now if I could just figure out how to use safari-only for development, but remove the line when building the WAR. Suggestions welcome.

Posted in Java at Feb 27 2009, 11:58:12 AM MST 6 Comments

Enhancing your GWT Application with the UrlRewriteFilter

Last week, I spent some time trying to change the location of my cache/nocache HTML files in my GWT project. I started the project with the gwt-maven-plugin's archetype. The message I posted to the gwt-maven Google Group is below.

Rather than having my application's HTML file in src/main/java/com/mycompany/Application.html, I'd like to move it to src/main/webapp/index.html. I tried copying the HTML and adding the following to my index.html, but no dice:

<meta name="gwt:module" content="com.mycompany.Application"/>

Is this possible with the gwt-maven-plugin? I'd like to have my main HTML and CSS at the root of my application.

The good news is I figured out a solution using the UrlRewriteFilter that 1) allows hosted mode to work as usual and 2) allows your app to be served up from the root URL (/ instead of /com.company.Module/Application.html). Here's the urlrewrite.xml that makes it all possible.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCENGINE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
        "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">

<urlrewrite>
    <rule>
        <from>^/$</from>
        <to type="forward" last="true">/com.mycompany.app.Application/Application.html</to>
    </rule>
    <rule>
        <from>/index.html</from>
        <to type="forward" last="true">/com.mycompany.app.Application/Application.html</to>
    </rule>
    <-- This last rule is necessary for JS and CSS files -->
    <rule>
        <from>^/(.*)\.(.*)$</from>
        <to type="forward">/com.mycompany.app.Application/$1.$2</to>
    </rule>
</urlrewrite>

If you're using the gwt-maven plugin, this file goes in src/main/webapp/WEB-INF. In addition, you'll need to add the following to your web.xml.

    <filter>
        <filter-name>rewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>rewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Finally, add the UrlRewriteFilter dependency in your pom.xml:

    <dependency>
        <groupId>org.tuckey</groupId>
        <artifactId>urlrewritefilter</artifactId>
        <version>3.1.0</version>
    </dependency>

Please let me know if you have any questions.

Update: Jeff posted an alternative configuration that allows you to eliminate the last rule in urlrewrite.xml, as well as use the beloved mvn jetty:run command. To use cleaner WAR packaging and the Jetty plugin, add the following to your pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <webappDirectory>
            ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
        </webappDirectory>
    </configuration>
</plugin>
<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.14</version>
    <configuration>
        <webAppConfig>
            <contextPath>/</contextPath>
            <baseResource implementation="org.mortbay.resource.ResourceCollection">
                <resourcesAsCSV>
                    ${basedir}/src/main/webapp,
                    ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
                </resourcesAsCSV>
            </baseResource>
        </webAppConfig>
        <scanIntervalSeconds>3</scanIntervalSeconds>
        <scanTargets>
            <scanTarget>${basedir}/src/main/resources</scanTarget>
            <scanTarget>${basedir}/src/main/webapp/WEB-INF</scanTarget>
            <scanTarget>
                ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
            </scanTarget>
        </scanTargets>
    </configuration>
</plugin>

Then you can trim your urlrewrite.xml down to:

<urlrewrite>
    <rule>
        <from>^/$</from>
        <to type="forward" last="true">/Application.html</to>
    </rule>
    <rule>
        <from>/index.html</from>
        <to type="forward" last="true">/Application.html</to>
    </rule>
</urlrewrite>

Of course, you could also change the welcome-file in your web.xml or use index.html and the <meta http-equiv="REFRESH"> option. Personally, I have so much affection for the UrlRewriteFilter that I like having it in my project. I'm sure I'll need it someday.

Thanks Jeff!

Posted in Java at Feb 23 2009, 05:02:29 PM MST 13 Comments

Testing GWT Applications

Last week, I did some research on GWT, how to test it and code coverage options for tests that extend GWTTestCase. The reason I did this is because I've found that most of the GWT tests I write have to extend GWTTestCase and I'd like to have code coverage reports. Read below for more information on my findings for testing GWT classes.

There are quite a few articles about testing GWT applications. Here are a few samples:

The main gist of these articles is that you should structure your code to make the core functionality of your application testable without having to depend on GWTTestCase.

All of them also advocate using an MVC or MVP (Model View Presenter) pattern. Currently, I'm using GXT and its MVC Framework. Unfortunately, GXT's MVC doesn't have much documentation. The good news is there is a good article that explained enough that I was able to refactor my project to use it.

The unfortunate side of this refactoring was I discovered that classes that extend GXT's MVC Framework have to be tested with GWTTestCase. The downside to extending GWTTestCase is there is it's difficult to create code coverage reports.

GWT's issue 799 has some patches that should make code coverage possible. I tried to implement code coverage with Eclipse and EclEmma using this README, but failed. In the process, I discovered an issue with Eclipse 3.4 and JUnit on OS X. Reverting to Eclipse 3.3 solved this problem, but I was still unable to make EclEmma work with GWT.

After failing with Eclipse, I tried to use the emma-maven-plugin. I was also unable to get this to work, with my findings documented in this thread.

Finally, I did have some luck with getting IDEA's built-in code coverage feature working. However, after getting it to work once, it failed to work for the rest of the day and I haven't had success since.

Code Coverage and GWT
Because of these issues with GWT 1.5 and code coverage, I think I'll wait until GWT 1.6 to worry about it. The good news is 1.6 M1 was released last Friday. If continuing to use GWTTestCase becomes an issue, I may write my own MVC Framework that doesn't use classes that call native JavaScript. Hopefully GXT MVC's framework will provide a good example.

In addition to trying to get code coverage working, I used the internets to figure out how run GWT tests inside of Eclipse and IDEA. I don't remember the resources I used, but hopefully this up-to-date documentation will help others. The nice thing about using an IDE to run these tests is they typically execute much faster.

Running GWT Tests in Eclipse
You should be able to run most of your GWT tests from within Eclipse using the following steps.

  1. Right-click on a test that extends GWTTestCase and go to Run As > JUnit Test. It's likely you will see the error message below.
    Invalid launch configuration: -XstartOnFirstThread not specified.
    
    On Mac OS X, GWT requires that the Java virtual machine be invoked with the
    -XstartOnFirstThread VM argument.
    
    Example:
      java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
    
  2. To fix this error, go to Run > Open Run Dialog. Click on the Arguments tab and add the following values. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error.
    -XstartOnFirstThread -Xmx512M
  3. When you re-run the test, you will probably see the following error:
    com.google.gwt.junit.JUnitFatalLaunchException: The test class 'org.richresume.client.home.HomeControllerGwtTest' 
    was not found in module 'org.richresume.client.Application'; no compilation unit for that type was seen
      at com.google.gwt.junit.JUnitShell.checkTestClassInCurrentModule(JUnitShell.java:193)
      at com.google.gwt.junit.JUnitShell.runTestImpl(JUnitShell.java:628)
      at com.google.gwt.junit.JUnitShell.runTest(JUnitShell.java:150)
      at com.google.gwt.junit.client.GWTTestCase.runTest(GWTTestCase.java:219)
    
  4. To fix this, open the Run Dialog again, click on the Classpath tab and click on User Entries. Click on the Advanced button and select Add Folders. In the Folder Selection dialog, select your source and test directories (e.g. src/main/java and src/test/java).
  5. Run the test again and you should see a green bar in your JUnit tab.
  6. To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to "All Tests" and select the 2nd radio button to run all tests in the project.
  7. Click Run to execute all the tests in the project.

Running GWT Tests in IDEA
You should be able to run your GWT tests from within IDEA using the following steps.

  1. Right-click on a test that extends GWTTestCase and go to Run "TestNameGwtTes...". It's likely you will see the error message below.
    Invalid launch configuration: -XstartOnFirstThread not specified.
    
    On Mac OS X, GWT requires that the Java virtual machine be invoked with the
    -XstartOnFirstThread VM argument.
    
    Example:
      java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
    
  2. If you get a compiler error instead, you may need to add the GWT Facet to your project. To do this, right-click on your project's top-most folder in the left pane. Select Module Settings > Facets and enable GWT for your module.
  3. To fix the -XstartOnFirstThread issue, go to Run > Edit Configurations. Add the following values to the VM Arguments field. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error.
    -XstartOnFirstThread -Xmx512M
    NOTE: If you still get a compiler error, see this page for a possible solution.
  4. Run the test again and you should see a green bar in your Run tab.
  5. To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to "All Tests" and change the Test configuration to search for tests in the whole project.
  6. Run the new configuration to execute all the tests in the project.

Testing GWT applications isn't as straightforward as writing JUnit tests, but I do believe it's getting better. If you have any additional tips and tricks, please let me know.

Posted in Java at Feb 09 2009, 03:27:36 PM MST 6 Comments

Choosing an Ajax Framework

This past week, my colleagues and I have been researching Ajax Frameworks. We're working on a project that's following SOFEA-style architecture principles and we want the best framework for our needs. I'm writing this post to see 1) if you, the community, agree with our selection process and 2) to learn about your experiences with the frameworks we're evaluating. Below is the process we're following to make our choice.

  1. Choose a short list of frameworks to prototype with.
  2. Create an application prototype with each framework.
  3. Document findings and create a matrix with important criteria.
  4. Create presentation to summarize document.
  5. Deliver document, presentation (with demos) and recommendation.

For #1, we chose Ext JS, Dojo, YUI and GWT because we feel these Ajax libraries offer the most UI widgets. We also considered Prototype/Scriptaculous, jQuery and MooTools, but decided against them because of their lack of UI widgets.

For #2, we time-boxed ourselves to 3 days of development. In addition to basic functionality, we added several features (i.e. edit in place, drag and drop, calendar widgets, transitions, charts, grid) that might be used in the production application. We all were able to complete most of the functionality of the application. Of course, there's still some code cleanup as well as styling to make each app look good for the demo. The nice thing about doing this is we're able to look at each others code and see how the same thing is done in each framework. None of us are experts in any of the frameworks, so it's possible we could do things better. However, I think it's good we all started somewhat green because it shows what's possible for someone relatively new to the frameworks.

For #3, we're creating a document with the following outline:

Introduction

Ajax Framework Candidates
(intro and explanation)

  Project Information
  (history)
  (license / cost)
  (number of committers)
  (support options)
  (mailing list traffic (nov/dec 2008))

Matrix and Notes

Conclusion

For the Matrix referenced in the outline above, we're using a table with weights and ranks:

Weight Criteria Dojo YUI GWT Ext JS Notes
# Important Criteria for Customer 0..1 0..1 0..1 0..1 Notes about rankings

Our strategy for filling in this matrix:

  • Customer adjusts the weight for each criteria (removing/adding as needed) so all weights add up to 1.
  • We rank each framework with 0, .5 or 1 where 0 = doesn't satisfy criteria, .5 = partially satisfies, 1 = satisfies.

The list of criteria provided to us by our client is as follows (in no particular order).

  • Quality of Documentation/Tutorials/Self Help
  • Browser support (most important browsers/versions based on web stats)
  • Testability (esp. Selenium compatibility)
  • Licensing
  • Project health/adoption
  • Performance
  • Scalability
  • Flexibility/extensibility
  • Productivity (app dev, web dev)
  • Richness of widget/component library
  • Charting capability
  • Ability to create new widgets
  • Match to existing Java team skill-set
  • Ease of deployment (on Ops, QA, Users)
  • Degree of risk generally
  • Ability to integrate with existing site (which includes Prototype)
  • Easy to style with CSS
  • Validation (esp. marking form elements invalid)
  • Component Theme-ing/Decoration
  • CDN Availability (i.e. Google's Ajax Libraries API or Ext CDN)

What do you think? How could this process be improved? Of course, if you have framework answers (0, .5 or 1) for our matrix, we'd love to hear your opinions.

Posted in Java at Jan 08 2009, 09:36:22 PM MST 39 Comments

RESTful Web Applications with Subbu Allamaraju

Subbu works at Yahoo! developing standards, patterns and practices for HTTP web languages. In the past, he was a web service and Java developer. He was also a standards contributor at BEA and an author of books on Java EE. His current passion is HTTP and REST. Subbu confesses that he's not a web developer, has no interest in the internals of programming models used for web frameworks and he's only interested in the visible aspects of the architecture.

"The Web is Mostly Restful"

Being RESTful in an abstract sense means:

  • Resources are named by URIs
  • Resources have representations (Atom, HTML, JSON, XML)
  • Resources contain contextual links to allow navigation of state
  • There's a Uniform Interface

In the web today, some resources and URIs are personalized, but most are not. Some depend on sessions, but most do not. The consequence of a personalized UI with a non-unique URI is you cannot rely on browser caching.

The web is full of different representations (HTML, XML, JS, PDF, CSS, Flash). The problem with HTML is you can't tell links that you want a particular representation based of a link. The links are hard-coded to be a particular content-type. However, some media types on responses are ignored. This is often a problem with browsers and whether the user has plugins installed.

The Uniform Interface for the web is HTML and primarily links and forms (GET and POST). There's still some misconceptions (e.g. POST is secure). However, it's not about security, it's about idempotency and safety. You need to make sure you only use POST when you're changing data. POSTs are not repeatable. GET URIs are not always refreshable, which is quite unfortunate. Users shouldn't have to fight the back button.

Caching is a fundamental aspect of the web. Even in a personalized site, most of the content can be cached. The web is read-only for the most part. However, many enterprise web applications don't take advantage of caching. This is fine when there's not that many users, but it's bad when you want to scale to thousands of users. There's several frameworks that use cache-busting and prefer backend caching over HTTP caching. These frameworks are not using the web like they should.

Backend caching (e.g. Memcached) uses a non-uniform interface and you need to explicitly program to it. Frontend/HTTP caching has a uniform interface that's pluggable. Backend caching is generally more expensive to develop and deploy. There are cases where data should be cached on the backend, but you shouldn't focus all on backend caching w/o doing some frontend caching.

With Ajax, you get more opportunities to be RESTful. XMLHttpRequest is another HTTP client that can be programmed to. It has full support for the uniform interface, which allows content negotiation, optimistic concurrency and caching. Cross-domain hacks can be done with <script> and <iframe> to tunnel requests over GET. The W3C has been working for the last two years on how to do cross-domain Ajax w/o using hacks. The problem with current cross-domain implementations is they often use GET for everything, which isn't very RESTful. Subbu recommends using a proxy on the same domain if you do need to talk to other domains. This will allow your Ajax code to remain RESTful.

Web Frameworks
Web development is hard because of all the moving pieces that exist. Because of this, many web frameworks have been created to solve the various problems. In 1997, there were servlets. They provided basic plumbing and closely reflected HTTP/1.1. Servlets provided a poor programming model, but it allowed a lot of frameworks to be built on top of it. We don't use servlets to write applications, only to write application frameworks. The second era came about in 2001 when Action-oriented frameworks became popular. In 2004, JSF and friends came to play. JSF is a component-based framework with known limitations (complex, slow, uses POST for almost everything, Ajax is difficult). These limitations have resulted in a number of third-party patches being developed to solve these issues.

JSF was designed to use the request to create a component tree that maintains state. Unfortunately, the state is not something the developer has control over. It's not the state of the application, it's the state of the components. The client's knowledge of the state is mentioned with a cookie and the server keeps the state in the session. The problem with JSF is you don't have a choice of state in your application - you can't write stateless applications like you can with servlets.

JSF uses overloaded URIs for its resources. When you have one URI with multiple representations, there's no way to tell how a representation was chosen. JSF's compromise is to allow client-side state saving. However, they do this by putting hidden field in the form and requiring POST for navigation.

JSF vs. REST
Basically, these two are at opposite extremes. JSF is focused heavily on a UI component model. The people that developed it misinterpreted how the web works and made some fundamental questionable choices. You can patch it, but you can not fix it.

Web 2.0 Frameworks
GWT is a cross-compilation based framework. You write Java to generate JavaScript (b/c everyone hates writing JavaScript). It mashes client and server code into a single source. These layers communicate using GWT-RPC. Typical RPC concerns do not apply since code generation handles coupling and the client is downloaded from the same application. GWT-PRC does POSTs to the server and uses HTTP like a transport layer. To be fair, GWT does allow you to use a RequestBuilder to use the web like it should be used. This class allows more control over HTTP requests, it supports GET and POST and it allows so-called RESTful layers (GWT-REST and GET-Restlet). GWT is focused heavily on ease-of-use, which is good. It's modeled after RPC and breaks the uniform interface and focuses on backend caching. Unlike JSF, GWT is fixable, but the community tends to use RPC instead of RequestBuilder.

SOFEA has a central promise of SOA. Business logic is a reusable service that changes less often. The presentation application calls those services and changes more often. The nice thing about this type of architecture is it allows a separation of concerns and loose coupling. However, it doesn't embrace REST like it should. Appcelerator is an implementation of SOFEA that has a Ruby on Rails-like usability. However, it uses a SOAP/HTTP style with messaging and POSTs to a single URI. Appcelerator is interesting, but it introduces a different style of coupling. It breaks URI opacity and client deals with POX instead of links.

Conclusion
Don't fight the architecture of the web. Innovate and enhance instead of breaking. If nothing else, break judiciously. As developers, we should demand more from our frameworks and make sure they use the web and HTTP like it should be used.

Posted in Java at Oct 24 2008, 09:52:02 AM MDT 16 Comments

Building Rich Applications with Appcelerator

This afternoon, I delivered my Building Rich Applications with Appcelerator talk for the 3rd time at Colorado Software Summit. When I first proposed this topic, I hadn't used Appcelerator and saw this as a good opportunity to learn more about it. I'm glad I did.

IMO, Appcelerator is a lot like Dojo in how it parses pages and turns HTML with special attributes into JavaScript widgets. I can't help but think a pre-compilation step would be nice to speed things up. I like Appcelerator's extensive Widget Library, and I especially like that they re-use many widgets rather than re-creating their own. Finally, I really dig the "SOA in a browser" approach where everything is a message and you can easily publish and subscribe to events - on the client and server. Below is my presentation, please let me know if you have any questions.

Posted in Java at Oct 22 2008, 04:18:42 PM MDT 9 Comments

Xebia RIA Framework Contest

Last year, I blogged about the Xebia Web Framework Contest where Struts 2, GWT, Wicket and MyFaces (JSF) were all used to develop the same applications. It seems they've done it again this year, comparing RIA frameworks (English translation) this time.

Five teams were formed, five frameworks have been selected:

  • Flex 3 Flex 3
  • Silverlight 2.0 beta 2 Silverlight 2.0 beta 2
  • Google GWT 1.5 Google GWT 1.5
  • Echo3 Echo3
  • JavaFX Preview SDK JavaFX SDK Preview

The number of teams is limited, the list of frameworks is also selected, and we have therefore necessarily set aside some frameworks that would have certainly had their place in the contest. Examples Ext JS, Yahoo! UI, Curl, XUL, ZK or OpenLaszlo. If you have experience on one of these frameworks, feel free to share in the comments on this article! [Read More »]

The winner? Flex - which doesn't surprise me a whole lot.

After this day, the Flex team, has clearly demarcated from its competitors. After two sprints of development and ownership, it could devote the third and final sprint to get rich quick and easy application, focusing only on the features and user experience. It is thanks to the wealth of high-level components, the wealth of documentation available and a maturity framework that the team has made the Flex application's most successful.

Good stuff - thanks Xebia!

Posted in Java at Oct 07 2008, 08:06:48 AM MDT 1 Comment