Matt RaibleMatt Raible is a writer with a passion for software. 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.
You searched this site for "linkedin". 58 entries found.

You can also try this same search on Google.

The good ol' Job Hunt

Just over two years ago, I wrote about the good ol' job hunt. Today, I find myself in a very similar situation. My Evite gig ends in a couple hours and I'm heading to The Cabin on Monday for a month of vacation. Similar to last time, there are opportunities out there, but most of them come through recruiters.

I have to admit - it seems like I got lucky the last couple times I tried to find a gig. I simply blogged I was looking and found myself negotiating with companies a few days later. Getting laid off from LinkedIn was awesome in that a few companies contacted me about hiring the whole team the next day. The ability to blog-and-get-a-gig was a great way to cut out the middle-man.

Unfortunately, I think I got spoiled by my blog-and-get-a-gig success. I figured it would happen again this time...

Not so much.

I don't know if it's because of the down economy or because I took the year off from speaking at conferences. Regardless, I'm in an interesting situation since I signed a 1-year lease on an office in downtown Denver. It's easy to market to companies in Denver, but if I land a gig here, there's a good chance the client is going to want me in the office everyday. That leaves me wondering: what's the best way to market to companies outside of Colorado? My ideal contract is one that 1) allows me to work remotely and 2) only requires me to travel once or twice a month.

I believe my ideal gigs are out there, but I think it's difficult to convince companies I'm a good remote worker. In an attempt to convince them otherwise, I'd like to offer recommendations from my last two clients.

"Matt contributed dramatically to the engineering practice at Evite, both directly and indirectly. Directly, he lead the effort to define and prove a successful new web UI architecture for us. Indirectly, he brought senior engineering talent into the organization, and energized the existing team. We are significantly better positioned to deliver on our Product goals as a result of having worked with Matt. I'd love to work with him again someday." David Thomas, VP of Technology, Evite

"Matt has unique abilities in the realm of software engineering. He brings great energy, an amazing breadth of knowledge in UI technologies, along with a can-do attitude that's refreshing to interact with. He is a great leader and communicator. In addition, Matt can apply his deep understanding of the technologies in question pragmatically to the engineering problem at hand, leading his team in execution and delivery. He's an excellent technical visionary to complement any team." Arnold Goldberg, Vice President Platform Engineering, LinkedIn

If you're looking to hire someone with my skills, let me know - there's a good chance you'll be glad you did. ;-)

Posted in Java at Jun 26 2009, 03:30:42 PM MDT 9 Comments

Implementing OAuth with GWT

I've heard about OAuth for quite some time, but never had an opportunity to implement it on a project. For a good explanation of what OAuth is, see its Introduction. Here's an excerpt:

...it allows you the User to grant access to your private resources on one site (which is called the Service Provider), to another site (called Consumer, not to be confused with you, the User). While OpenID is all about using a single identity to sign into many sites, OAuth is about giving access to your stuff without sharing your identity at all (or its secret parts).

The reason I needed OAuth was to interact with the Google Contacts API. I've always hated how sites make you import all your contacts from Gmail. I wanted to develop a system that'd let you simply read your contacts from Google in real-time.

Since the application I'm working on uses GWT, I chose to implement an OAuth client in GWT. After googling for "gwt oauth", I found two examples. Unfortunately, neither worked out-of-the-box.

The good news is I did manage to create a working solution. The bad news is it only seems to work at random. That's right folks, I created a solution that only works 50% of the time. I'm somewhat embarrassed to post it here, but I also realize the power of open source and community. By sharing, I hope we can find the flaws in my logic and come up with a solution for all GWT applications.

The best project for OAuth libraries seems to be oauth on Google Code. However, you'll notice that there is no JavaScript implementation listed on the homepage. I did look at the Java implementation, but quickly realized it wouldn't be usable in GWT. Therefore, I opted for the JavaScript implementation.

OAuth consists of several steps. The following diagram explains the authentication flow nicely.

OAuth Authentication Flow

In a nutshell, you have to complete the following steps:

  1. Get a token from the service provider.
  2. Redirect user to service provider to grant access and redirect back to application.
  3. Request access token to access protected resources.
  4. Access protected resources and pull/push data.

To access a service provider's OAuth service, you'll likely need to start by registering your application. For Google, OAuth Authentication for Web Applications is an excellent resource. Google's OAuth Playground is a great way to with the Google Data APIs after you've registered.

Now that you know how OAuth works, let's look at how I implemented it with GWT. I started by adding the necessary JavaScript references to my *.gwt.xml file.

<script src="//oauth.googlecode.com/svn/code/javascript/oauth.js"/>
<script src="//oauth.googlecode.com/svn/code/javascript/sha1.js"/>

Next, I needed a way to sign the request. I tried to use Sergi Mansilla's OAuth.java for this, but discovered issues with how the parameters were being written with GWT 1.6. I opted for Paul Donnelly's makeSignedRequest function instead. By adding this to my application's HTML page, I'm able to call it using the following JSNI method:

public native static String signRequest(String key, String secret, String tokenSecret, String url) /*-{
    return $wnd.makeSignedRequest(key, secret, tokenSecret, url);
}-*/;

After the URL is signed, it needs to be sent to the provider to get a request token. To do this, I used GWT's RequestBuilder and created a send() method:

protected void send(RequestCallback cb, String URL) {
    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL);
    builder.setTimeoutMillis(10000);
    builder.setCallback(cb);
    
    Request req = null;
    try {
        req = builder.send();
    } catch (RequestException e) {
        cb.onError(req, e);
    }
}

If you try this with Google's Request Token URL in GWT's hosted mode, nothing will happen. Compile/browse to Safari and you'll still see nothing. Try it in Firefox and you'll see the following.

SOP Error

To workaround browsers' Same Origin Policy, I added a proxy servlet to send the requests. I started with Jason Edwards's ProxyServlet and modified it to fit my needs. I then registered it in both *.gwt.xml and web.xml.

<servlet path="/google/" class="org.appfuse.gwt.servlet.AlternateHostProxyServlet"/>

Now, before calling the send() method, I replace the start of the URL so the request would be routed through the servlet.

public void getToken(RequestCallback cb) {
    String url = signRequest(provider.getConsumerKey(), 
                             provider.getConsumerSecret(), 
                             "", provider.getRequestTokenURL());
    url = url.replace("https://www.google.com/", "/google/");
    send(cb, url);
}

When the request returns, I create two cookies by calling a createOAuthCookies() method with the payload returned:

public static String[] createOAuthCookies(String data) {
    String oauth_token = data.substring(data.indexOf("oauth_token=") + 12);
    oauth_token = oauth_token.substring(0, oauth_token.indexOf("&"));

    String oauth_token_secret = data.substring(data.indexOf("oauth_token_secret=") + 19);

    Cookies.setCookie("oauth_token", URL.decode(oauth_token));
    Cookies.setCookie("oauth_token_secret", URL.decode(oauth_token_secret));
    return new String[]{oauth_token, oauth_token_secret};
}

The next step is to authorize the token. This is where things got tricky with my proxy servlet and I had to add some special logic for GWT. Google was sending back a 302 with a Location header, but it wasn't hitting the onResponseReceived() method in my callback. For this reason, I had to change it to a 200 status code and add the redirect location to the body. I also discovered that sometimes they'd return an HTML page with a <meta http-equiv="refresh" ...> tag. When using Twitter, I discovered the full HTML for the allow/deny page was returned. Below is the callback I'm using. WindowUtils is a class I got from Robert Hanson and the gwt-widget project.

public void onResponseReceived(Request request, Response response) {
    String text = response.getText();
    if (response.getStatusCode() == 200 && response.getText().startsWith("http")) {
        WindowUtils.changeLocation(response.getText());
    } else {
        // look for meta-tag that refreshes and grab its URL
        if (text.contains("";
            String url = text.substring(text.indexOf(tokenToStartWith) + tokenToStartWith.length());
            url = url.substring(0, url.indexOf(tokenToEndWith) + tokenToEndWith.length());
            WindowUtils.changeLocation(url);
        } else {
            // Twitter returns a full HTML page, so redirect to the authorize URL manually
            if (provider instanceof Twitter) {
                String url = provider.getAuthorizeTokenURL();
                url = url.replace("$1", OAuthRequest.getAuthToken());
                url = url.replace("$2", DefaultRequest.getCurrentLocation());
                WindowUtils.changeLocation(url);
            } else {
                onError(request, new RequestException(text));
            }
        }
    }
}

public void onError(Request request, Throwable caught) {
    Window.alert("Calling authorize token failed. " + OAuthPage.STANDARD_ERROR + "\n\n" + caught.getMessage());
}

The 3rd step is to get an access token. The most important thing to remember when you do this is to include the "oauth_token_secret" value when signing the request.

signRequest(provider.getConsumerKey(), provider.getConsumerSecret(), 
            getAuthTokenSecret(), url);

After this completes with a 200, I create the cookies again (since oauth_token and oauth_token_secret are returned in the body), then call the API to get a list of contacts. The ContactsRequests class is responsible for making the call. The DefaultRequest class contains the send() method as well as utility methods to get the cookie values of the oauth tokens.

public class ContactsRequest extends DefaultRequest {
    private static final String GOOGLE_CONTACTS_URL = 
        "http://www.google.com/m8/feeds/contacts/default/thin?oauth_token=$1";
    private OAuthProvider provider;

    public ContactsRequest(OAuthProvider provider) {
        this.provider = provider;
    }

    public void getContacts(RequestCallback cb) {
        String url = GOOGLE_CONTACTS_URL.replace("$1", getAuthToken());
        url = signRequest(provider.getConsumerKey(), provider.getConsumerSecret(), 
                          getAuthTokenSecret(), url);

        String proxiedURLPrefix = "/contacts/";
        // allow for deploying at /gwt-oauth context
        if (WindowUtils.getLocation().getPath().contains("gwt-oauth")) {
            proxiedURLPrefix = "/gwt-oauth" + proxiedURLPrefix;
        }

        url = url.replace("http://www.google.com/", proxiedURLPrefix);

        send(cb, url);
    }
}

If all goes well, the response contains the data you requested and it's used to populate a textarea (at least in this demo application). Of course, additional processing needs to occur to parse/format this data into something useful.

This all sounds pretty useful for GWT applications, right? I believe it does - but only if it works consistently. I sent a message to the OAuth Google Group explaining the issues I've had.

I'm trying to use the JavaScript API to authenticate with OAuth from a GWT application. I've got it working with both Google and Twitter's OAuth implementations. However, it seems to fail to sign the URL at random. In other words, it works 1 out of 3 times. ... Any idea why this could be happening?

I received a response with a cleaner makeSignedRequest() function. I tried it and, unfortunately, it seems to be equally unreliable. I suspect the problem is with the OAuth JavaScript implementation, GWT's interpretation of it, or that OAuth isn't as mature as it appears to be. I'd like to think one of the first two causes the problem.

To make it easier to create a robust example of GWT and OAuth, I created a gwt-oauth project you can download or view online. Please keep in mind the demo is likely to be flakey. If you're persistent and try enough times, it's likely to work. Firefox seems to succeed moreso than Safari or Chrome. If you have any suggestions for improving this example, please let me know.

Posted in Java at Jun 18 2009, 01:59:13 PM MDT 13 Comments

Enhancing Evite.com with GWT and Grails

Evite.com On my LinkedIn Profile, it says my current gig is a SOFEA consultant at a stealth-mode startup.

SOFEA Consultant, Stealth Mode Startup, Los Angeles, CA. December 2008 -- Present.

OK, I lied. It's not a startup, it's a well-known company that helps you plan parties. For the last 5+ months, my UI team from LinkedIn has been working with Evite.com to enhance portions of their site with a SOFEA architecture.

In January, we started evaluating Ajax Frameworks and came to the conclusion that GWT was right for us. After we chose the UI framework, other team members chose Grails and memcached to develop scalable RESTful services. The architecture we implemented involves using GWT's RequestBuilder to talk to Grails' services, which cache almost all their JSON output in memcached.

To see an example of a feature we developed with GWT, see Evite's Design Gallery. I personally worked on this feature and very much enjoyed becoming a GWT aficionado in the process. GWT's zero-turnaround feature made doing pure client-side work a lot of fun. It's definitely something I'd like to continuing doing at my next gig.

Everyone from Evite is very happy with what we've been able to do with GWT and Grails. We have a stateless architecture and are quickly able to develop both client-side and server-side features. We've learned to scale the client by using out-of-the-box GWT components. We've scaled Grails by caching as much as possible. We serve up Ads and Analytics using the same JavaScript mechanisms that traditional server-side frameworks use.

At the end of this month, my gig with Evite comes to an end. I'll be spending a few weeks at my family's cabin in Montana and then it's on to the next big thing. What's the next big thing? I'm not sure yet, hence the reason for writing this. If you're looking to develop a GWT application, introduce a SOFEA architecture at your company, or simply adopt some open source frameworks, I'd love to help out. Drop me a line and let's start a conversation.

Posted in Java at Jun 15 2009, 07:41:37 AM MDT 9 Comments

Creating a Facebook-style Autocomplete with GWT

Have you used the "To:" widget on on Facebook or LinkedIn when composing a message? It's an autocompleter that looks up contact names and displays them as you type. It looks like a normal textbox (a.k.a. <input type="text">), but wraps the contact name to allow you to easily delete it. Here's a screenshot of what Facebook's widget looks like.

Facebook Autocomplete

Last week, I was asked to create a similar widget with GWT. After searching the web and not finding much, I decided to try writing my own. The best example I found on how to create this widget was from James Smith's Tokenizing Autocomplete jQuery Plugin. I used its demo to help me learn how the DOM changed after you selected a contact.

GWT's SelectBox allows you to easily create an autocompleter. However, it doesn't have support for multiple values (for example, a comma-delimited list). The good news is it's not difficult to add this functionality using Viktor Zaprudnev's HowTo. Another feature you might want in a SelectBox is to populate it with POJOs. GWT SuggestBox backed by DTO Model is a good blog post that shows how to do this.

Back to the Facebook Autocompleter. To demonstrate how to create this widget in GWT, I put together a simple application. You can view the demo or download it. The meat of this example is in an InputListWidget. After looking at the jQuery example, I learned the widget was a <div> with a unordered list (<ul>). It starts out looking like this:

<ul class="token-input-list-facebook">
    <li class="token-input-input-token-facebook">
        <input type="text" style="outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;"/>
    </li>
</ul>

I did this in GWT using custom BulletList and ListItem widgets (contained in the download).

final BulletList list = new BulletList();
list.setStyleName("token-input-list-facebook");

final ListItem item = new ListItem();
item.setStyleName("token-input-input-token-facebook");

final TextBox itemBox = new TextBox();
itemBox.getElement().setAttribute("style", 
        "outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;");

final SuggestBox box = new SuggestBox(getSuggestions(), itemBox);
box.getElement().setId("suggestion_box");

item.add(box);
list.add(item);

After tabbing off the input, I noticed that it was removed and replaced with a <p> around the value and a <span> to show the "x" to delete it. After adding a couple items, the HTML is as follows:

<ul class="token-input-list-facebook">
    <li class="token-input-token-facebook">
        <p>What's New Scooby-Doo?</p>
        <span class="token-input-delete-token-facebook">x</span>
    </li>
    <li class="token-input-token-facebook">
        <p>Fear Factor</p>
        <span class="token-input-delete-token-facebook">x</span>
     </li>
     <li class="token-input-input-token-facebook">
         <input type="text" style="outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;"/>
     </li>
</ul>

To do this, I created a deselectItem() method that triggers the DOM transformation.

private void deselectItem(final TextBox itemBox, final BulletList list) {
    if (itemBox.getValue() != null && !"".equals(itemBox.getValue().trim())) {
        /** Change to the following structure:
         * <li class="token-input-token-facebook">
         * <p>What's New Scooby-Doo?</p>
         * <span class="token-input-delete-token-facebook">x</span>
         * </li>
         */

        final ListItem displayItem = new ListItem();
        displayItem.setStyleName("token-input-token-facebook");
        Paragraph p = new Paragraph(itemBox.getValue());

        displayItem.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                displayItem.addStyleName("token-input-selected-token-facebook");
            }
        });

        Span span = new Span("x");
        span.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                list.remove(displayItem);
            }
        });

        displayItem.add(p);
        displayItem.add(span);
        
        list.insert(displayItem, list.getWidgetCount() - 1);
        itemBox.setValue("");
        itemBox.setFocus(true);
    }
}

This method is called after selecting a new item from the SuggestBox:

box.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
    public void onSelection(SelectionEvent selectionEvent) {
        deselectItem(itemBox, list);
    }
});

I also added the ability for you to type in an e-mail address manually and to delete the previous item when you backspace from the input field. Here's the handler that calls deselectItem() and allows deleting with backspace:

// this needs to be on the itemBox rather than box, or backspace will get executed twice
itemBox.addKeyDownHandler(new KeyDownHandler() {
    public void onKeyDown(KeyDownEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
            // only allow manual entries with @ signs (assumed email addresses)
            if (itemBox.getValue().contains("@"))
                deselectItem(itemBox, list);
        }
        // handle backspace
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
            if ("".equals(itemBox.getValue().trim())) {
                ListItem li = (ListItem) list.getWidget(list.getWidgetCount() - 2);
                Paragraph p = (Paragraph) li.getWidget(0);

                list.remove(li);
                itemBox.setFocus(true);
            }
        }
    }
});

I'm happy with the results, and grateful for the jQuery plugin's CSS. However, it still has one issue that I haven't been able to solve: I'm unable to click on a list item (to select it) and then delete it (with the backspace key). I believe this is because I'm unable to give focus to the list item. Here's the code that highlights the item and you can see the commented-out code that doesn't work.

displayItem.addClickHandler(new ClickHandler() {
    public void onClick(ClickEvent clickEvent) {
        displayItem.addStyleName("token-input-selected-token-facebook");
    }
});

/** TODO: Figure out how to select item and allow deleting with backspace key
displayItem.addKeyDownHandler(new KeyDownHandler() {
    public void onKeyDown(KeyDownEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
            list.remove(displayItem);
        }
    }
});
displayItem.addBlurHandler(new BlurHandler() {
    public void onBlur(BlurEvent blurEvent) {
        displayItem.removeStyleName("token-input-selected-token-facebook");
    }
});
*/

If you know of a solution to this issue, please let me know. Feel free to use this widget and improve it as you see fit. I'd love to see this as a native widget in GWT. In the meantime, here's the GWT Facebook-style Autocomplete demo and code.

Posted in Java at Jun 05 2009, 07:05:10 AM MDT 25 Comments

The End of the Colorado Software Summit

It looks like the Colorado Software Summit has come to an end.

To Our Friends and Supporters,

In these challenging economic times, business has slowed, many companies have had to resort to layoffs and/or closures, and everyone has been tightening their belts. Unfortunately, Colorado Software Summit has not been immune to this downturn. As have so many companies and individuals, we too have experienced a severe decline in our business, and as a result we are not able to continue producing this annual conference.

This year would have been our 18th conference, and we had planned to continue through our 20th in 2011, but instead we must end it now. [Read More]

I first attended this conference in October 2005. I enjoyed it so much, I returned again in 2006, 2007 and 2008. As I mentioned last year, this was my favorite conference.

The reason I like it so much is because it's an annual gathering (this will be my 4th year) with friends and it's somewhat like a vacation, except you get to learn a lot.

While I'm sad to see it go, I completely understand Wayne and Peggy's decision. If you ever attended this conference, I encourage you to join the Colorado Software Summit LinkedIn Group. To see all my posts from the talks I attended at this conference, see my softwaresummit-tagged entries.

To Wayne and Peggy: thanks for all the great memories and for putting together such an excellent conference. Cheers to you both!

Posted in Java at Jun 04 2009, 02:39:20 PM MDT 2 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

How To Setup Your Own Software Development Company

This post was originally titled "FTE vs. Contract in this Economy", but it didn't seem to capture the essence of this entry. I wanted to write about why I think contracting is better in this down economy, but I also wanted to write about how you you might go about setting up your own company. Starting a company is relatively easy from a legal standpoint, and hopefully I can provide some resources that'll make it even easier.

First of all, I believe that contracting is better in this economy for a very simple reason:

When you're a contractor, you're prepared to be let go.

There's really nothing like being laid off. It sucks. It often shocks you and makes you depressed. The good part is you usually get a good afternoon's worth of drinking out of it, but that's about it. Severance is cool, but let's face it - you'd much rather be employed.

As a contractor, you're always looking for your next gig. You're prepared for the worst. You're more motivated to learn marketable skills. You're constantly thinking about how you can market yourself better. Writing (blogging, articles, books) is an excellent way to do this and I believe it's rare that FTE are as motivated to do these kinds of things.

Being a contractor forces you to better yourself so you're more marketable.

People's biggest fear of contracting is that they'll have a hard time finding their next gig. In my career, I've rarely had an issue with this. There's always contracts available, it's just a matter of how much you're going to get paid. Yes, I've had to suck-it-up and make $55/hour instead of $125/hour, but that was back in 2003 and $55/hour is still more than I would have made as a FTE.

The other thing that makes me believe contracting is better in this economy is I believe companies are hiring more short-term contractors than employees. I don't know if this is because they consider employees liabilities and contractors expenses, but something about it seems to make the books look better.

So you've decided to take my advice and try your hand at contracting. Should you setup your own Corporation or LLC?

Starting a Company
Yes, you should absolutely start your own company. As a Software Developer, chances are you're going to make enough to put you in the highest tax bracket. If you're a Sole Proprietor (no company), you will pay something like 35% of your income to taxes and you can be sued for everything you own by your clients.

Should you create an LLC or Corporation? I started Raible Designs in May 1998. I started out as an LLC and later converted to an S Corp. For the first few years, I made $30-$55/hour and this seemed to work pretty well. I believe this was similar to having a Sole Proprietorship (because I was the only employee), except that I was protected from lawsuits.

In 2001, I got my first high-paying gig at $90/hour and my Accountant suggested I change to an S Corp to save 10K+ on self-employment tax. I'm certainly not an expert on the different types of business entities, but this path seemed to work well for me. It was $50 to convert from an LLC to an S Corp. I'm not sure if you can go from an S Corp to an LLC. The beauty of an S Corp is the corporation typically gets taxed at 15%, so you can run a lot of things through your business and pay less taxes. Date nights can be business meetings, vacations can be Shareholders Meetings, seasons tickets can be client entertainment and you can write off your car and fuel costs.

There's lots of good resources on the web that describe the different business entity options. My favorite is A List Apart's This Web Business IV: Business Entity Options. Another good resource is How to form an LLC.

The hardest part of starting a new business is coming up with a good name. My advice is to make sure the domain name is available and pick something you like. I chose Raible Designs because I designed web sites at the time. Raible is a pretty unique name, so that's worked well having it as part of my business name. Googlability is important - don't choose a generic name that will make you difficult to find. Potential clients should be able to google your business name and find you easily.

Once you've picked a name, the business establishment part is pretty easy. In Colorado, you can File a Document with the Secretary of State. Their site also allows you to reserve a name if you're not quite ready to make the leap.

You'll also need to get a Federal Employer Identification Number (FEIN) from the IRS. The IRS has a good Starting a Business article and also allows you to Apply for an Employer Identification Number (EIN) Online.

Once you've got all the documents setup, you'll want to create a bank account for your business. I'm currently using Wells Fargo and really like how software-friendly they are. Their online banking is clean and easy to use. They also support QuickBooks for the Mac. They have Payroll Services to allow you to pay your quarterly taxes online as well as setup direct deposit, but I'm not using them.

For payroll, I use PayCycle and have nothing but good things to say about them (see update below). I have the Small Business Package at $42.99 per month. This package allows me to pay myself and employees + up to 5 sub-contractors with direct deposit. It also allows me to pay both Federal and State quarterly taxes online. Of course, if you can also get an Accountant to do this for you.

Having a good Accountant and Financial Advisor (for your retirement plan) will likely be an essential part of your business.. LinkedIn's Service Providers is a good way to find recommended professionals in your area. For example, click here to search for Accountants and then click the change location link in the top right corner to specify your zip code.

Finally, you'll need insurance. The Hartford has a good Small Business package that costs around $500/year. It's liability limits have worked for all of my clients and I'm covered if my laptop ever gets stolen. For Health Insurance, I recommend using eHealthInsurance.com to find a good provider for you. I don't get sick or hurt much, so I typically get a disaster prevention plan with a $5K deductible. For dental insurance, brush your teeth. Vision insurance typically sucks, so I wouldn't buy it. Yes, our health care system in the US needs work and I believe if everyone had a small business, it might get more affordable a lot quicker.

Over the next few days, I'll post some additional advice I've received on retirement plans, deducting a home office, drawing up contracts and how to come up with a good rate. If you're an Independent Software Developer and have any additional advice, I'd love to hear it.

Update: I take back what I said about PayCycle. After having a couple of insufficient funds when re-activating my account in January (they were pulling from the wrong account), they've changed my direct deposit lead-time to 5 days for the next 6 months. This means I forget to create checks on time since their reminder gets sent 2 days before. Time to try Wells Fargo.

Update October 2009: I never left PayCycle and I continue to use them to this day. I'm a satisfied customer, but do believe it still takes too long to make changes to your electronic services setup.

Posted in Java at Feb 10 2009, 12:23:10 PM MST 36 Comments

Dojo/Comet support in Java Web Frameworks

Dojo Logo This week I'm doing a research project for a client. The main purpose of the project is to find out which Java-based web framework works best with Dojo and Comet. Here's the key requirement from the client:

It's all about Comet, we want Comet everywhere we can put it, but we want to isolate the icky bits of fiddling with pages with JavaScript. We're kind of wed to the Dojo implementation of the client-side bit, so we may as well use more of the Dojo widgets for a richer UI. For us, "works best with" needs to pay a certain amount of consideration to "fits naturally with", if you understand what I mean. I know that any framework that lets you spit out raw HTML will let you hand code in your Dojo / Comet, but that's certain to become very tiresome very quickly.

The candidate frameworks they asked me to look at are Wicket and Tapestry 5. They're willing to upgrade to Struts 2 since they're already using Struts 1. However, they don't feel that action-based frameworks naturally lead to rich UIs, so they'd prefer a component-based framework. They're currently using Seam for an administration-type application and feel it's too heavy for their customer-facing application.

Here's what I've found so far in my research. Please let me know if anything is incorrect.

  • Tapestry 5 doesn't have Dojo or Comet support (Prototype and Scriptaculous are the baked-in Ajax frameworks).
  • Struts 2 has old (version 0.4.3) and somewhat deprecated Dojo support. The developers seem to be in favor of removing it and promoting people hand-code Dojo instead. Struts 2 doesn't have support for Comet.
  • Wicket has support for Dojo 1.1 that includes Comet support. This was written by Stefan Fußenegger and posted to the mailing list last month. I e-mailed Stefan and asked him about documentation. His response: "I lost my ambition to document it properly since I didn't receive any feedback on the mailing list. :)"

At this point, it seems that if the client really wants to use Dojo, they should use Wicket, and possibly pay Stefan to document it properly. However, they're willing to consider other options, as long as they have Comet support.

One option I thought of is to use DWR and its Reverse Ajax/Comet support. Another option would be to add better Dojo support to Tapestry 5. However, I don't think this is possible since the Prototype/Scriptaculous code is generated by the framework and would likely require a changes to switch it to Dojo.

Are there any other Java-based web frameworks that support easily creating Dojo widgets and working with Comet? Keith Donald tweeted that Spring MVC has Dojo support. However, I believe it's only for widgets and it still requires you to write JavaScript. If your framework doesn't have Dojo/Comet support, how hard would it be to add it?

Update: I also posted this question on LinkedIn. Make sure and check my question for additional thoughts from folks.

Posted in Java at Dec 18 2008, 03:58:37 PM MST 19 Comments

What's Next

It's been three weeks since I joined the realm of the unemployed. Fortunately, I didn't stay unemployed for long. In fact, after writing the aforementioned post, I received 5 offers the next day. Of the opportunities I received, the most interesting ones were those from companies interested in hiring the whole team. Not only that, but LinkedIn hired me back as a contractor through the end of the year. The goal of the LinkedIn contract: finish up projects that my team had started in the previous months.

At the end of the first week after the LinkedIn layoffs, we all had individual opportunities, but we also had two team opportunities. The following week (last week), I flew to NYC to meet with one potential client while the other potential client flew to Denver to meet with the rest of the team. After flying to NYC, I traveled to Mountain View to do some on-site work at LinkedIn. At the end of the week, it seemed like most of the remaining tasks at LinkedIn could be done by someone else. I told them I thought it was best that I move onto other things, while staying available for support questions. On the way to the airport, I spoke with both our team opportunities. Following those conversations, I was very pumped about both projects and confident about pending offers. You can imagine my disappointment when my flight was delayed for 5 hours.

After a fun weekend with Abbie, Jack and friends, I woke up Monday morning without a job and it felt great. However, things changed quickly. Monday morning many opportunities landed in my inbox: a 3-day gig this week (helping write open-source training), a 1-week gig in December (evaluating how well Tapestry 5, Wicket and Struts 2 integrate with Dojo/Comet for a client in Europe), a 1-week training gig in Europe next year and a 3-month gig for the whole team. I accepted all these opportunities and am very happy I'll get to work with Jimbo, Country and Scotty again next year. The 3-month gig should be a lot of fun. We're helping build a SOFEA-based architecture that leverages appropriate client technologies (to be determined) to build a kick-ass web application. I look forward to talking about the technologies we use and things we learn along the way.

Costa Rica, courtesy of Rob Misek So the good news is I've entered The Golden Period. The Golden Period is when you don't have a job, but you do have a start date. Unemployment is absolutely blissful during this time. The Golden Period exists a couple times for me over the next 6 weeks.

I'll be traveling to Costa Rica tomorrow for a best friend's wedding. I'm leaving both my laptop and my iPhone at home. Next week, I'll be loving life with my parents in Costa Rica and Panama. The following week, I'll be working on AppFuse all week and hope to make great progress on developing 2.1. Then I have the 1-week Web Framework Analysis gig, followed by 2 weeks of vacation in Oregon. My Golden Period begins this afternoon (for 3 weeks) and happens again over Christmas (for 2 weeks).

Yeah, life is good. Damn good. :-D

Posted in Java at Nov 26 2008, 03:19:18 PM MST 12 Comments

LinkedIn Cuts 10% (a.k.a. The Journey is Over)

This morning, my co-workers and I discovered that LinkedIn decided to trim 10% of its employees. The Denver Office was among those that were laid off. I can't say we didn't see the writing on the wall. In fact, on the evening of October 15, I sent the following e-mail to my co-workers:

LinkedIn's top investor[1] is Sequoia Capital and they recently posted this presentation on the web.

http://www.slideshare.net/eldon/sequoia-capital-on-startups-and-the-economic-downturn-presentation?type=powerpoint

Notice the reduce head count recommendations. ... Oh well, life goes on. ;-)

Raible

[1] http://www.linkedin.com/static?key=investors

So, as of today, there is no LinkedIn Denver office. While I had a lot of fun being a UI Architect and managing Engineers, I'm somewhat happy this has happened. After all, now I get to enjoy the best perk about being an employee: the good ol' severance package!

If you're looking for good Engineers, I highly recommend all of the guys who worked for me during this journey. You can read more about the skills they possess and what they're looking for by viewing their LinkedIn Profiles:


Scott Nicholls

Bryan Noll

James Goodwill

As for me, I'm definitely in the market as well. You can view My LinkedIn Profile to see if I might be a good fit for your organization. I'm willing to travel up to 25%, but would prefer not to. After all, ski season is right around the corner. ;-)

Lastly, I just wanted to say that I really enjoyed working at LinkedIn. I've never worked with a smarter group of Engineers, nor been so excited about a company's product and vision. I know that LinkedIn will be highly successful and I hope to use their site to find gigs for many years to come.

Posted in Java at Nov 05 2008, 03:10:06 PM MST 16 Comments