David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler

    Web app developer since 1994 and Google Cloud Platform Instructor now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 228 other followers

  • Sleepless Nights…

    February 2020
    S M T W T F S
    « Nov    
  • Blog Stats

    • 1,007,781 hits

Chromebook deals under $350 for Black Friday 2019

Posted by David Chandler on November 11, 2019

It’s that time again! The Best Buy Black Friday ad once again has some spectacular deals on Chromebooks for all types of users.

My favorite this year is the new HP Chromebook 2-in-1 14″ i3 8GB, a new flip tablet with some of the beefiest specs of any Chromebook. At the Black Friday price of only $349 (reg. $599), it is hands down the best value on the market for moderate to power users. I purchased it on a preview sale and the only thing I don’t love is the weight. It comes in a little heavy at 3.7 lbs., but the 14″ full HD screen and excellent sale price more than make up for it IMHO. The backlit keyboard is a pleasure with lots of key travel and more mechanical feel. It has 2 USB-C ports and 1 USB-A port so you don’t need an adapter for your USB security key or external mouse. The trackpad is smooth and responsive, and the full HD screen, while not the brightest or most saturated in color, is sharp and adequate even under bright lights. It’s built solid, so there is no annoying give when you rest your hands on the keyboard. 8GB RAM is plenty generous for a Chromebook, and like most modern Chromebooks, it runs Android and Linux apps, as well.

A close second is the ASUS C434 flip tablet, which is similarly equipped. It has a thinner bezel than the HP but square edges, which I don’t prefer, and I don’t like the tablet fold as much. Costco now (Dec 6) has the ASUS on sale for $399 (reg. $549) with Core m3 (not as fast as the i3) and 4GB RAM (vs. 8GB for the HP). It’s a great price for a very nice machine, but not as good a value as the Black Friday price on the HP. The ASUS C433 (Best Buy exclusive) is about $40 cheaper than the ASUS C434, but feels a little less solid next to the trackpad.

On the lower end, the Lenovo 2-in-1 is a good value at the Black Friday price of $179. The Acer Spin 11 is a little bulkier, but offers more solid construction and performance. Its cousin, the Acer R11, has served our family very well for years. The Spin 11 features an upgraded processor (Celeron 3350), USB-C ports in addition to USB-A, generous battery life (10 hrs), and front/rear cameras for tablet mode. At the Black Friday (and beyond) price of $219, it is an excellent value. The very similar Lenovo C340 11.6″ 2-in-1 is in the Costco Black Friday ad for $229, also a great value. It feels more solid than its predecessor. The Lenovo’s N4000 processor is slightly (~30%) more performant than the Acer’s N3350, but the Acer is more symmetrical in tablet mode. Also the Lenovo, being a new model, has a couple years longer support from ChromeOS. The Lenovo screen is slightly brighter and crisper than the Acer.

For the most budget conscious, the Samsung 11.6″ 4GB model (not a flip tablet) at $119 is an excellent value. The rubberized case seems like it’s built to withstand some abuse, making it a good first machine for younger students.

To summarize, my top three Chromebooks under $350 this Black Friday are:

  • $349 HP Chromebook 14″ 2-in-1 8GB
  • $219 Acer Spin 11 4GB (Best Buy model with dual camera for tablet mode)
  • $119 Samsung 11.6″ 4GB

Happy hunting!

Posted in PC Tech | 1 Comment »

Magic Trackpad 2 works with ChromeOS!

Posted by David Chandler on May 3, 2019

Last October, Chrome Unboxed reported that support for Apple’s Magic Trackpad 2 was in the Chrome dev channel. It’s now in Chrome stable as of v73, and I’ve verified it with several popular Chromebooks including the Acer R11, ASUS C302, and Pixelbook.

Works with KVM switches, too

Why would you want an external trackpad when Chromebooks already have pretty decent trackpads built-in? Answer: when you’re sharing an external keyboard and trackpad between two computers. The previous Magic Trackpad was Bluetooth- and Mac-only, and, like the current Magic Trackpad 2, can pair wirelessly with only one device at a time. This makes it impractical to switch between computers. The Magic Trackpad 2 introduces a great innovation–a cord! (who knew?)–that is ideal for KVM switches. The trackpad cord features a standard USB-A plug used by most KVM switches. The Magic Trackpad 2 automatically pairs via Bluetooth with my 2015 Macbook Pro and also works wired through an IOGear DisplayPort USB KVM switch with my Pixelbook. It’s smart enough to send movements over only one channel (wired or wireless) at a time.


Guess which one is my work computer?

Why Magic Trackpad 2?

Mice bother me. Literally, they hurt my shoulder until I started switching mouse hands every other day to distribute the bodily wear. I’ve had much less trouble since using a trackpad. Plus, gestures are cool, and the Magic Trackpad 2 supports the four-finger gestures on the Mac and three-finger gestures on ChromeOS. Pinch zoom works in both. The Magic Trackpad 2 is huge, allowing me to move the pointer all the way across two displays with one motion. And it offers a definite “click” throughout the entire surface, with an additional level of “force click” that can be configured on the Mac (but not ChromeOS). Of course, tap-to-click works fine, too.

Kudos to Apple and the Chrome team for making this integration possible! It’s an ergonomic delight.

Posted in Ergonomics | 2 Comments »

In search of the perfect Chromebook on Black Friday

Posted by David Chandler on November 19, 2018

My family has been using Chromebooks for home and school for the last 5 years. There’s lots to like: super fast startup, no worries about viruses or backups, and they update automatically, which is super easy on me as my kids’ systems administrator. All the Google apps including Gmail now support offline use, and newer models can run Android apps and now even Linux apps (more below)! And of course, for basic computing from email and word processing to Facebook and Netflix, they’re cheap. As Black Friday approaches, I thought I’d highlight a few of my favorite models.

Most versatile around the house

The Acer R11 is my all-around favorite for home use. It has a great feel to it, solid and comfortable. I find the R11 on the kitchen counter serving up recipes, at the kitchen table answering emails, on the couch doing school work in Google Docs, and set up in tent mode in the living room for a video call over Hangouts or sharing photos with guests. The R11 doubles as a tablet which can run Android apps so you can download albums for offline listening using Google Play Music, read offline with Kindle, or explore a new area with Google Maps on a large screen in tablet mode. It has all the standard ports you’d expect (USB-A, HDMI, audio, SD card reader) so you don’t need adapters as with newer USB-C ports. Performance is reasonable for the Google apps and Web browsing. The available Celeron 3160 model is noticeably faster than the Celeron 3060, although both are decent when running productivity apps like Gmail and Kindle Reader. The R11 is small enough that you can fit it almost anywhere, and you can even find a $15 stylus on Amazon.com that works great on the touchscreen if you want to keep it clear of fingerprints. Costco had the 4 GB / 32 GB model with Celeron 3160 on sale for $199 a couple weeks ago, a really great value for a computer + Android tablet. Using the beta Linux apps support now available in Chrome 70, I even installed git, Java, maven, and IntelliJ on the R11. I would definitely not choose this as my primary machine for software development as an IDE like IntelliJ is very sluggish on the Celeron, but for text-based Linux tools, it’s more than adequate.

Best Buy currently has a similar model from Lenovo with an ARM-based chip (vs. Intel) on sale for $179. I have no personal experience with the Lenovo and its app compatibility, but the look and feel is great and the reviews are excellent.

Best traveler

The ASUS Chromebook C302 flip model, like the R11, runs Android apps (but not yet Linux, sadness). At just over two pounds, it travels lightly through airports on my back, and it’s thin enough to be quite comfortable as a tablet, as well. Its Intel Core m3 processor is quite a bit faster than the Celeron processors in low-end Chromebooks and handles most everyday tasks instantly. I really can’t imagine needing more power for anything but high-end games and software development. The backlit keyboard and sleek, silver design feels somewhat like a Macbook Air. I like the extra inch and a half of display over the Acer R11, but the R11 feels more durable because of its heavier textured plastic shell. For use on a desk or in my lap, the ASUS is my favorite. I was lucky to find an open box at Best Buy for $350, but they’re in the $450 range new.

Best movie screen under $300

The Acer Chromebook 15 (older model, not the latest) offers a large 15.6″ full HD display and excellent sound from the built-in speakers. It is heavy (almost 5 pounds!) and built like a tank, with durable fabric texture shell. It has all the same standard ports as the R11. The Celeron 3205U processor is more powerful than the N3160 on the Acer R11. Combined with a speedy Internet connection, my son uses it to remote in to a Windows machine in Google Cloud Platform to run Excel for business school. There is no noticeable lag. It is a great machine under $300 for students who don’t mind hauling it around. Unfortunately, the 3205U doesn’t yet run Linux apps. It does run Android apps even though it’s not a touchscreen.

For software developers

The biggest limitation of Chromebooks for developers has been the inability to install local developer tools. It’s been possible to run Linux on Chromebooks using dual boot or Crouton for a while, but this required switching to the ChromeOS dev channel, which does not have the stability or security of the stable channel. Now that Linux support (beta) has reached Chrome stable channel as of v69 (you’ll find the ability to enable Linux apps right by the Google Play option in Settings), it’s quite possible to install a typical Java developer stack on many Chromebooks. I’ve installed OpenJDK, maven, and IntelliJ on everything from the $199 Acer R11 to the $1,000+ Pixelbook. Older Celeron 30xx and 31xx processors are supported as well as the newer Core i3/i5/i7 chips and a handful of chips in the midrange–check the official Chromium page above.

Aside from the ultralight but spendy Pixelbook (BestBuy has the 8GB i5 model on sale for only $699 this week!), there is one midrange model great for developers, the Dell Chromebook 14, currently on sale for $499 at Best Buy. The display is stunning with vibrant color and resolution up to 2194 x 1234. The built-in sound is also surprisingly good, but the main attraction is the Core i3 processor, which is capable enough to run IntelliJ smoothly. It scores 34,600 on Octane v2, faster than my high-end Pixelbook with i7 processor (score 27k)!  It’s also a tablet, though a bit awkward for its size, and runs Android apps admirably. The provided stylus with built-in holder keeps the screen free of fingerprints and works well with pressure-sensitive drawing apps like Squid. The Dell Chromebook 14 weighs in at about twice the weight of a Pixelbook and is bulkier in shape, but I prefer the Dell’s wider display with thinner bezel. As long as I don’t have to wear it on my back too much, this is my “one Chromebook to rule them all.”

The $100 computer and one for Grandma, too

Lastly, I want to call out a couple deals in Best Buy’s Black Friday ad. The Samsung 11.6″ Chromebook with 2 GB RAM and 16 GB storage is only $99 this coming weekend. It’s a minimal machine, but certainly sufficient for Gmail, Google Docs, and Facebook. The 4GB model (preferred, as ChromeOS likes RAM) is only $129.

Older eyes will also appreciate several of Acer’s Chromebook 15 models that have 1366×768 resolution. While not as sharp as a full HD display, a large screen at lower resolution allows older eyes like mine to use the display at the default zoom level. And they’re cheap: this one is currently on sale for $169.

Happy deal hunting!


Posted in PC Tech | 2 Comments »

When frequent travel points (including United) ARE worth something

Posted by David Chandler on October 1, 2018

Having griped about United previously, I think it’s only fair to pass on the positives, as well. My wife, daughter, and I just got back from a trip to visit our son in college near Oklahoma City. We booked the trip on less than a week’s notice, found United award tickets to nearby Wichita, KS (where it was also cheaper for us to rendezvous with our daughter) for the minimum 20k miles, rented a car from National, and got a free upgrade to a RAV4 with my status (I love the Emerald Aisle, and although Wichita is too small to have one, they still gave me a choice of cars). I could have used free rental credits but decided to save them for a more expensive city later. We stayed two nights at Hyatt Regency Wichita using the minimum number of points and as a Hyatt Globalist, received parking and a very nice breakfast buffet with made-to-order omelet for free. As an aside, we were quite impressed with Wichita hospitality generally. Growing up in Kansas City, I generally believed Kansans were friendly. Even so, the folks at the Wichita Hyatt Regency, National Car Rental, United, and Hog Wild BBQ were especially helpful and friendly (and the BBQ was great).

Our return trip today was remarkably smooth. We got to the Wichita airport at 7:20am for an 8:25 flight. There was no traffic. National car return at the counter (haven’t done that for a while!) was the fastest ever, and they swapped my business credit card for personal credit card in <30s. United checked us and our bags (for free, Silver and up) in record time, there was literally no one in line at security, and the flight left on time. We sat in Premium Economy (book for free with Gold status up), which on the ERJ175 is quite roomy. They served coffee on board even though the flight was only an hour, and a friendly flight attendant presented my snack box on request with a sincere “thank you for being a Premier 1K member.” Our bags were waiting for us on the carrousel by the time we arrived. Back home in Denver, Canopy Airport Parking picked us up within 5 minutes. Indoor valet parking was free thanks to frequent parker points.

When it all works, it can be quite smooth, and I am thankful to be able to earn status and points on my employer’s nickel, then cash them in on my own. I find that travel points and status are not worth pursuing for their own sake–there are usually cheaper travel alternatives–but they do reduce the inconveniences of frequent business travel. And occasionally, they enable me to do things that otherwise would be prohibitively expensive or time-consuming, such as a last-minute trip to a smaller city with less competitive airfares.

On the whole, I’ve been very well treated as a frequent customer with United, Hyatt, Hilton, National, and Canopy. In my experience (50+ trips over the last couple years), most of the customer-facing people in these organizations truly value the customer and provide efficient service, and the rewards programs really are rewarding. Per my previous post, Premier 1K has not been as rewarding as I had hoped in terms of upgrades (certainly in part because I fly mostly congested hub routes). However, United rewards Gold members and up with the ability to book Premium Economy for free (including companions), which I tremendously appreciate, and I likewise appreciate free checked bags for the whole family when on vacation. Also the Premier 1K One Call number is great–I’ve never waited more than a minute to make or change a reservation, etc. On the whole, I expected to be burnt out from ~50% travel after a year, but after almost two years, I still mostly enjoy my travels. Major inconveniences have been rare and trips like this one have indeed made it worthwhile to maintain brand loyalty.

Posted in Travel | Leave a Comment »

Why United Premier 1K status is basically worthless

Posted by David Chandler on September 11, 2018

This post is a gripe, and a very intentional one. It’s no way to start blogging again after years of not writing. Nevertheless it needs to get indexed in Google so when people search for info on United status they can learn the hard truths before committing to United. These are things I wish I’d known.

I have been a Premier 1K flyer for a year now. I live in Denver and fly mostly to major United cities (SFO, Chicago, DC, Seattle). As a Premier 1K, I’m eligible for Complimentary Premier Upgrades (CPUs). I’ve received 3 out of 70 some flights I have made, and those were only when not flying between hubs (OKC, anyone?). As a Premier 1K, I almost never get a complimentary upgrade when flying from Denver to a hub unless it’s Saturday at 6am. The official rules say that CPUs can be confirmed as early as 96 hours in advance. That has happened only twice. Usually I wait at the airport to find out I receive no upgrade. I’m often #1 on the upgrade list, but it doesn’t matter–they sell any remaining seats at the last minute via kiosk discount at checkin rather than give it to a Premier 1K.

I finished last year with 8 Regional Premier Upgrades (RPUs). I thought this would allow me to upgrade any domestic flight in advance. Wrong again. Regional upgrades are  waitlisted, so you don’t know if you actually get your upgrade until an hour before the flight or even on the plane! Starting with 8 RPUs, I’ve tried to use them on my last 30 flights or so. So far, my upgrade has been confirmed only 3x using an RPU. So they’re pretty much worthless, too. United doesn’t open up the upgrade seats until a few days or even hours before the flight. If there is any chance somebody might buy the first class seat, they’re not going to let you have it with an upgrade. Which shows how much they really appreciate your business as a Premier flier with over 100k miles per year. They’ll give you the seat if it costs them exactly nothing.

Global upgrades (GPUs) are likewise near worthless. They are waitlisted until 4-6 days before the flight on the routes I fly, so I can’t know until it’s too late whether I have a lie-flat seat for those long-haul overnight trips. Worse, upgrades for an international flight with a connection are restricted by the domestic leg. So while Houston to Lima might have 9 upgrades available, Denver to Lima has only 2 available, even though the IAH-LIM leg is the very same flight. Maddening.

Premier 1Ks are supposed be able to get “instant upgrades” on Y-, B-, and even M-class fares. But guess what? When you read the fine print, instant upgrades are subject to capacity controls. And only eligible for domestic flights. That don’t have a lie-flat seat. And every time I’ve looked, the M-class fare is higher than the discount first-class fare. So this benefit, too, is a lie.

What about miles? Don’t Premier 1K members get better availability on MilleagePlus award tickets? Yes, and credit card members, and…? My experience is that you can almost never use the saver awards (25k miles) in advance to popular destinations. They seem to open them up at the last minute, so I have been able to use miles to attend a funeral, for example, which would have otherwise been an $800 ticket. But for vacation planning more than a couple weeks in advance, forget it. If you want a red-eye flight or multiple stops, sure, you can find those, and maybe even a relatively out-of-the-way place. I took my family to Toronto in June using miles and we really enjoyed the time, so maybe try to use your miles to Toronto.

In my experience, the only United benefit actually worth something is the ability to book Premium Economy seats for free at time of booking with Gold status, and this I do value greatly. If they ever take that away, I might as well fly Southwest. At least that way, I would get to choose the size of people I sit next to. Also it’s nice that Premier 1K members get Group 1 boarding so you don’t have to wait for your carryon on the other end. Otherwise, “priority” boarding is a joke. Groups 1 and 2 are typically more than half the plane in Denver.

There is one more Premier 1K benefit that’s worth a few pennies: you get a drink (alas, I don’t drink) and an overpriced snack box for free. Twice I got a hamburger, the rest of the time beef jerky or the variety box. It’s something, but not definitely not worth my airline loyalty.

The crazy thing is, United service hasn’t been that bad. The flight attendants are usually friendly. The Premium Economy seats allow me enough room to open my laptop, and on Airbus aircraft, they’re actually comfortable (Boeing not so much). Every third flight or so is delayed, but usually I still arrive the same day. And they’ve lost my bag only when I’ve checked it up front, but they always get it back to me within a couple days. I could actually tolerate these things. But the promise of benefits like RPUs and GPUs only to find out I can’t actually use them except at the last minute–that makes me feel I’ve been cheated every single time I book a ticket.

So forget about your upgrades, and enjoy your snack box.

Posted in Travel | 5 Comments »

Speeding up enterprise GWT development

Posted by David Chandler on May 12, 2015


  • -draftCompile
  • <collapse-all-properties />

GWT developers are always looking for ways to speed up the development cycle. Colin Alworth has written an excellent blog post on GWT compiler options that can be used to select for faster builds or smaller output. In this post, I want to highlight the two most useful options for speeding up GWT development and show how to select them using a maven profile.

Speed up super dev mode (SDM) launch

GWT super dev mode, which is now well integrated in IntelliJ Ultimate Edition and (soon!) Google Plugin for Eclipse, does incremental compilation to bring page refresh time down to a few seconds for most applications. However, the initial compilation can still take a minute or more depending on the size of your app. Typically, about half the time is spent creating any required permutations. Normally, the browser request that triggers initial compilation in super dev mode will include enough information (such as user agent and language) to select a single permutation; however, if your application includes properties that generate additional permutations, you can use a tag in your gwt.xml to collapse them all into a single permutation. Simply include this in your gwt.xml:

<collapse-all-properties />

If you’re currently seeing SDM build multiple permutations, this will likely cut your initial SDM launch time by half.

Speed up full compilation

The <collapse-all-properties /> switch is always useful when doing a full compilation because in this case, the compiler must otherwise build all the permutations. Keep in mind that the resulting output is 15-20% larger than any single permutation would be so this is not recommended for your final production build. However, for a quick development build, it’s very useful.

In addition, when you are doing a development build, you can use the -draftCompile option to get about a 25% reduction in compile time at the expense of less optimized output. For testing or debugging, this is a great tradeoff.

The combination of <collapse-all-properties /> and -draftCompile will normally result in a 60-70% reduction in compile time.

Setting gwt.xml properties for development only

When you are using <collapse-all-properties /> or other techniques such as setting a single user agent in gwt.xml, you don’t want to accidentally leave these options in place when compiling for production. A simple way to avoid this is to create an additional gwt.xml which inherits all properties from the base gwt.xml. Both gwt.xml files should use the rename-to attribute with the same module name. The development-only version should inherit everything from the base module and set or override properties which apply to development only. Here is a simple example from my contactmgr example project:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN"
<module rename-to="contactmgr">
    <!-- Inherit the core Web Toolkit stuff.                        -->
    <inherits name='com.google.gwt.user.User' />
    <!-- Other module inherits                                      -->
    <inherits name="com.google.gwt.i18n.I18N"/>
    <inherits name="com.turbomanage.gwt.Util" />
    <inherits name="com.googlecode.objectify.Objectify" />
    <inherits name="com.google.gwt.place.Place" />
    <inherits name="com.google.gwt.activity.Activity" />
    <inherits name="org.fusesource.restygwt.RestyGWT"/>
    <inherits name="com.google.gwt.logging.Logging"/>
    <!-- Specify the app entry point class.                         -->
    <entry-point class='com.example.contactmgr.client.ContactManager' />


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN"
<module rename-to="contactmgr">
	<!-- Inherit the core Web Toolkit stuff.                        -->
    <inherits name='com.example.contactmgr.contactmgr' />

    <collapse-all-properties />

In your IDE, you can then create a run configuration specifically for the -dev.gwt.xml. Using this simple technique, you can continue to manage all your module dependencies and properties in the main gwt.xml while setting development-only properties such as logging switches and <collapse-all-properties /> in a separate file.

Configure IntelliJ to use the dev-only GWT module

Configure IntelliJ to use the dev-only GWT module

In the next section, we’ll look at how to select development options using a maven profile.

Setting development options in a maven project

In a maven project using gwt-maven-plugin, we can build on this technique to set compiler options using a maven profile. In my projects, I set the default gwt-maven-plugin configuration to use -draftCompile and the -dev.gwt.xml. I use a separate release profile to do the slower production build with all permutations, optimization, obfuscation, etc. Here’s a snippet from the contactmgr sample pom.xml showing the technique:

                    <extraJvmArgs>-Xmx1g -Xms64M</extraJvmArgs>
                    <!-- Doesn't affect super dev mode, only gwt:compile -->
                        <!-- For GPE -->

                            <extraJvmArgs>-Xmx1g -Xms64M</extraJvmArgs>

Note that the default configuration of gwt-maven-plugin specifies the development-only GWT module (contactmgr-dev) while the release profile specifies the base version. To do a full production build, use mvn -Prelease; otherwise, maven will use -draftCompile and the -dev.gwt.xml to reduce compile time.

If you project is particularly large and you use a continuous integration server like TeamCity or Jenkins, you may want to consider using -draftCompile and <collapse-all-properties /> in your builds for pull requests (commits) so you can get build status quicker. For example, using -draftCompile and <collapse-all-properties />, the GXT Explorer project builds in about 6 minutes vs. 18 minutes. There’s likely no reason why you need to build fully optimized and obfuscated output every time someone submits a code change.

Using these techniques in your enterprise GWT projects should help your team to be more productive in GWT development.

Posted in Google Web Toolkit | 1 Comment »

A good time for GWT

Posted by David Chandler on November 19, 2014

Just a quick note to the let the GWT community know that I’m really pleased to be joining Sencha as Developer Advocate for GXT. This is an exciting time for GWT and I’m glad to be part of it again. A lot of the stuff we’ve been hearing about for the last year is really starting to take shape. My own projects are already benefitting from the much faster super dev mode in GWT 2.7.0-rc1. Thanks to incremental compilation, small changes often take only a second to refresh. JSInterop looks promising and I’m happy to see that several companies continue to invest in GWT, including Google, as evidenced by lots of new stuff in GWT 2.7 and its use in the Google Inbox Web app (which, by the way, looks very promising). Sencha’s Brandon Donnelson has contributed a lot to super dev mode support in Eclipse, and the IntelliJ folks have made it really slick to launch super dev mode in IntelliJ 14. I am told that GXT 4 will have some nifty new stuff, too, but more on that later…

I look forward to seeing you at GWT.create 2015!

Posted in Google Web Toolkit | 3 Comments »

Painless REST+JSON API with Jersey and RestyGWT

Posted by David Chandler on July 23, 2014

It’s been a while since I’ve been active in GWT programming, but I recently picked up an old GWT + App Engine project and dusted it off. This time around, I need a service layer that will work with native mobile apps as well as the GWT desktop app: in other words, a REST+JSON API.

The server side

I decided to use Jersey on the server, which makes it incredibly easy to create REST services, especially in combination with the fabulous objectify-appengine. Here’s one of my services:

public class UserDao extends ObjectifyDao&amp;lt;User&amp;gt;
    public User getMe() {
        return AuthFilter.getUser(); // long live ThreadLocal!

All the other standard CRUD methods (list, get, delete, etc.) are inherited from a generic DAO. A servlet filter verifies user authentication, XSRF tokens, etc. At only one class per entity, I find this much more agreeable than the four classes per entity I used to write with gwt-dispatch (Action, Result, Handler, DAO).

The GWT REST+JSON client

On the client side, GWT developers have long needed something which combines:

  1. The convenience of GWT-RPC (automatic serialization of pretty much everything)
  2. JSON data format
  3. Simple verb-based service APIs
  4. Benefits of the command pattern such as request caching and batching
  5. Minimal boilerplate

RestyGWT delivers on all counts.

The interface is actually simpler than GWT-RPC because you don’t have to define a synchronous and asynchronous method, only async (although you can reuse the server interface and call it using DirectRestService if it helps you sleep better). Here’s a sample interface using RestyGWT. This is a generic CRUD API which I simply extend for each entity class.

public interface RestApi&amp;lt;T&amp;gt; extends RestService {

    public void getForOwner(MethodCallback&amp;lt;T&amp;gt; callback);

    public void get(@QueryParam(&amp;quot;id&amp;quot;)Long id, MethodCallback&amp;lt;T&amp;gt; callback);

    public void listAll(MethodCallback&amp;lt;ListResponse&amp;lt;T&amp;gt;&amp;gt; callback);

    public void save(T obj, MethodCallback&amp;lt;T&amp;gt; callback);


Here’s a sample service API and the GWT code that calls it:

public class UserPrefsService
    private static final UserPrefsRestService service = GWT.create(UserPrefsRestService.class);

    public interface UserPrefsRestService extends RestApi&amp;lt;UserPrefs&amp;gt; {
        // just in case you missed it, all the CRUD methods are inherited

    private UserPrefs prefs;

    public void loadUserPrefs()
        service.getForOwner(new AppCallback&amp;lt;UserPrefs&amp;gt;() {
            public void handleSuccess(UserPrefs result) {
                prefs = result;
                App.getEventBus().fireEvent(new UserPrefsLoadedEvent(prefs));

I really like the benefits of the Command pattern from the old gwt-dispatch framework such as the ability to do caching and queuing centrally. The downside of the Command pattern is the proliferation of classes associated with turning every API method into two or more classes (in the case of gwt-dispatch, an Action and Result class for every service method). GWT’s RequestFactory (the GWT team’s “final answer” to RPC after GWT-RPC and deRPC) used generators to remove some of the boilerplate, but I wasn’t in love with having to call someSingleton.getRequestFactory().someRequest().create(BeanProxy.class) each and every time I wanted a new Bean. And it uses a proprietary data format, not REST+JSON.

This is where RestyGWT really shines. It lets you define simple API interfaces using methods, but uses a Command pattern dispatcher under the covers with an ingenious filter mechanism for adding capabilities like XSRF protection, caching, and retries. The magic is possible thanks to RestyGWT’s generator classes which transform your annotated service methods into MethodRequest classes that get sent by a dispatcher. To add caching capability to all your APIs, for example, just put this in your GWT onModuleLoad():

DispatcherFactory factory = new DispatcherFactory();

For a look at some of the other dispatcher options, have a look at the RestyGWT User Guide and the example DispatchFactory class.

Tips for success with Jersey + RestyGWT

Just a couple final notes to ease your migration to Jersey + RestyGWT.

If you’re using RestyGWT with Jersey + Jackson on the server, you’ll want to set the default date format to avoid Date serialization errors. Put this in your GWT’s onModuleLoad():


Similarly, recent versions of Jersey complain about “self-referencing cycles” or some such with Objectify’s Ref properties, so you’ll probably want to annotate those in your server-side entities with @JsonIgnore. If you need the id of a related object, use a differently named getter instead. Jersey will create a corresponding JSON property. Example of an Objectified entity on the server:

package com.my.server.domain;

public class UserPrefs {
    private long id;
    private Ref&amp;lt;User&amp;gt; ownerKey;
    public long getOwnerId() {
        return ownerKey.get().getId();

Then on the client you can reference the ownerId property:

package com.my.client.domain;

public class UserPrefs
    public Long id;
    public long ownerId;

I would prefer to use the same object representation on client and server, but RestyGWT makes using DTOs about as painless as possible. The client-side object is a class not an interface, so you can create a new instance anywhere you need it vs. having to GWT.create(BeanProxy.class). I could probably hack Jersey and maybe objectify-appengine to automatically replace all Refs with a long id, but honestly, it’s easy enough just to copy the server entities and replace Refs with long ids on the client.

Also, here’s a pair of classes you may find useful for sending any type of list from server to client. For security purposes, a JSON response should always return a root object, not an array directly. The ListWrapper (server) and ListResponse (client) serve as this root object, having a single field containing the list.

package com.my.server.domain;

 * Wraps a List&amp;lt;T&amp;gt; in a JSON root object.
public class ListWrapper&amp;lt;T&amp;gt; {
    private List&amp;lt;T&amp;gt; list;

    public ListWrapper(List&amp;lt;T&amp;gt; list) {
        this.list = list;
    public List&amp;lt;T&amp;gt; getList() {
        return list;

Use it like this in one of your Jersey-annotated methods:

    public ListWrapper&amp;lt;Subscription&amp;gt; findAll() {
        User user = AuthFilter.getUser();
        List&amp;lt;Subscription&amp;gt; userAll = this.listByOwner(user);
        return new ListWrapper&amp;lt;Subscription&amp;gt;(userAll);

Using ListWrapper this way has the additional advantage of causing Objectify to fetch any lazily loaded properties such as Refs used in the getOwnerId() method above while producing the JSON. If you were to return the List directly, this would not occur!

Here’s the corresponding representation on the client:

package com.my.client.domain;

public class ListResponse&amp;lt;T&amp;gt; {

    public List&amp;lt;T&amp;gt; list;


See the RestApi example earlier for how it’s used.


Jersey and RestyGWT in combination make a powerful and easy way to create a REST API for your GWT client and mobile apps, combining all the benefits of a request dispatcher with straightforward service interfaces and minimal boilerplate.

Happy coding!

Posted in AppEngine, Google Web Toolkit | 9 Comments »

Debug an Android annotation processor with gradle and IntelliJ (or Eclipse)

Posted by David Chandler on June 9, 2014

Alex Gherschon and I have recently added maven support to storm-gen (note: I plan to push to Maven Central this week). You can now build and install storm-gen to your local maven repository with

git clone https://github.com/turbomanage/storm-gen.git
cd storm-gen/storm-apt
mvn clean install

Since gradle can pull in maven artifacts, you can then include storm-gen in your gradle build file like this:

apply plugin: 'android'
apply plugin: 'android-apt'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile 'log4j:log4j:1.2.17'
    compile 'javax.persistence:persistence-api:1.0'
    compile 'com.turbomanage.storm:storm-api:0.98'
    apt 'com.turbomanage.storm:storm-impl:0.98'

Now here’s the fun part. Previously, in order to debug and set breakpoints in the annotation processor itself, I used Eclipse RCP and ran it as an Eclipse plugin. Fortunately, there’s now an easier way using Java remote debugging. There are several variations on this technique (configuring an annotation processor directly in IntelliJ or debugging a gradle script). Unfortunately, Android Studio rejected my adding the Xdebug JVM args directly to the gradle script. However, I found this workaround. It is not fully integrated with AS, but does allow me to debug the annotation processor on demand by running the gradle script.

Add these lines to your ~/.gradle/gradle.properties:


Then do something that causes the gradle daemon to start.

gradle --daemon

Now you can go into IntelliJ or Android Studio and attach a remote debugger. I use IntelliJ because AS won’t import the storm-gen maven projects and the whole point of this exercise is to set breakpoints in the storm-gen annotation processor. The screenshot shows configuring a remote debugger in IntelliJ. Just accept the defaults and make sure the port number matches your gradle.properties. It should also work in Eclipse.

remote debug config

Configure a remote debugger in IntelliJ

The remote debugger should attach to the running gradle daemon. You can then tickle the annotation processor by running a build. For example, this runs the storm-gen tests on an already-running emulator or connected device:

cd storm-test
gradle clean connectedCheck

When the annotation processor runs, your breakpoint in IntelliJ (or Eclipse) should fire.

One caution with this technique is that Android Studio will also use the gradle daemon because it’s now configured in your gradle.properties. But if you launched the daemon from the command line, AS will try to launch it again and you’ll see an error message about the port already in use. In that case, simply kill the running gradle process and AS should be happy.

Posted in Android, IntelliJ | 1 Comment »

GWT, App Engine, maven, and… IntelliJ!

Posted by David Chandler on June 5, 2014

I’ve been putting off migrating to Android Studio for a while now because I’m frankly loathe to learn a new IDE. I’ve used Eclipse for a decade and grew to become very productive in it. But a completely different team at Google may have just well forced me into it.

When I joined the GWT Developer Relations team in 2010, I worked closely with the Google Plugin for Eclipse team to get maven support into GPE. With their excellent work, we eventually achieved the holy grail: you could import a POM containing maven-gae-plugin and gwt-maven-plugin into Eclipse and all the GWT + GAE stuff from GPE like launching dev mode would just work (well, if you had the right supporting plugins like m2e-wtp). So the other day, I picked up a POM that worked in those days and tried it out on Kepler + GPE + m2e-wtp. Amazingly enough, the GWT stuff still works. Google now supports its own appengine-maven-plugin, so I swapped out the old GAE plugin for the new. It’s supposed to work with GPE and WTP, but so far no dice. It will be great when they get the kinks worked out. Funny thing is, I remember seeing exactly the same problem with GAE-maven integration way back in my GWT days. Only then, I could just walk over to Rajeev’s desk and he would fix it 🙂

In the mean time, imagine my surprise to discover that I could just import the POM into IntelliJ (full edition) and everything works. The maven project imported, I can launch GWT dev mode, set breakpoints and debug, etc. It’s funny to me that JetBrains can keep up to date with Google App Engine better than the GPE team, but that’s how big companies move sometimes….

So I’m off to learning new keyboard shortcuts (I could use the Eclipse keymap, but I had customized Eclipse, too. It’s easier than I thought to learn new tricks). And I have to say, the performance of IntelliJ is impressive. A couple of my teammates way back at Intuit will no doubt be glad to hear that I finally came around to maven + IntelliJ, not to mention some of my Android DevRel mates. We’ll see how this goes, but so far, I’m impressed.


Posted in AppEngine, Eclipse, Google Web Toolkit | 1 Comment »

%d bloggers like this: