Preparing Your AngularJS App for Deployment

angle photo

Photo by kevin dooley

I have recently been working on an AngularJS CRUD front end to a REST API (built with DropWizard).  I have been working off the angular-phonecat example app (from the tutorial).

After making a few changes, I wanted to deploy the app to a standalone web server (Apache2).  I naively checked out the codebase on the web server, and visited index.html.

I saw a blank screen.  Looking in the console, I saw this error message: ReferenceError: angular is not defined

Whoops.

“Looks like there’s more to deploying this application than I thought.”  Some searching around doesn’t reveal a lot, maybe because deployment is just taken for granted in the AngularJS community?  Or I don’t know what questions to ask?

Regardless, the fundamental fact of building AngularJS apps for deployment is that, at least with the angular-phonecat base, your dependencies are managed by bower and/or npm, and you need to make sure you bundle them up when you are running on a web server that isn’t the npm started web server.

In practice, this means writing a Gruntfile (or, actually, modify this Gruntfile), which is similar to an ant build.xml file–you write targets and then gather them together.

For my initial Gruntfile, I wanted to make things as simple as possible, so I stripped out some of the fanciness of the g00glen00b file.  In the end, I had two tasks:

  1. bowercopy to  copy my bower dependencies to a temp directory.  I tried to use the bower grunt task, but wasn’t able to make it work.
  2. compress to gather the files and build the zip file

These were bundled together in a ‘package’ task that looked like this: grunt.registerTask('package', [ 'bowercopy', 'compress:dist' ]);

The compress task is complicated and took some figuring out (this post was helpful, as was a close reading of the task’s readme page and the page detailing how file objects can be dynamically generated). Here’s an example of the dist task:

 compress: {
          dist: {
            options: {
              archive: 'dist/<%= pkg.name %>-<%= pkg.version %>.zip'
            },
            files: [{
              src: [ 'app/index.html' ],
              dest: '/',
              expand: true,
              flatten: true
            }, {
              cwd: 'dist/libs',
              src: [ '**' ],
              dest: 'bower_components',
	      expand: true,
            },
              // ... more files definitions 
            ]
          }
  }

I want to unpack this a bit. First, the options object specifies an archive file and the name of the file. You can see that it is dynamically created based on values from the package.json (which is read in earlier in the grunt config file).

Then, the set of files to be added to this archive is specified. The src attribute outlines the list of files to include in the zip file. src handles wildcards (* for all in the directory, ** for all in the directory and subdirectories). The dest attribute, in contrast, indicates the directory where the file is to land in the zip archive. The expand attribute lets grunt do dynamic file matching (more here). The flatten attribute removes all the leading paths from the source files–if you didn’t have flatten:true in the index.html entry, it would be placed at /app/index.html in the zip file. The dist/libs entry handles all the dependencies that were copied to that tmp directory by the bowercopy task. What the cwd attribute tells grunt is to act like it is in that directory for the src attribute. So, a file at dist/lib/foo/bar will be treated like it was foo/bar and, in the task above, copied to bower_components/foo/bar in the zipfile. This allows one to maintain the same directory structure in my index.html file in both dev and production.

Finally, you need to install grunt and run grunt package to get your zipfile with all dependencies, for deployment.

There are a lot of other beneficial changes grunt can make to your app before deployment, like concatenating css and minifying the javascript, and I encourage you to read this post for more information, but this was enough to get the app running in an environment without npm or any of the other angularJS toolchain.


Java REST API Framework Options

resting photo

Photo by shioshvili

I’ve been working with a couple of REST API solutions that exist in the Java tech stack.  I haven’t seen any great analysis of REST API solutions (though Matt Raible does mention some in this exhaustive slide deck about Java frameworks [pdf]), so wanted to share my on the ground experience.

First up is restSQL.  This framework makes it easy to get data from a database to a JSON or XML REST API and back.  If you have a servlet container available, you write two configuration files, one with a SQL query and one with db connection information, and you have a RESTful API.  For prototyping and database access, it is hard to beat.

Pros:

  • Quick to set up
  • Only SQL knowledge is required
  • No programming required
  • Allows simple mapping of db table to resource, but can include one to one and one to many mappings
  • Supports all four REST operations out of the box
  • Supports XML as well as JSON
  • Is an embeddable java library as well as a standalone framework
  • Project maintainer is engaged and the project is moving forward

Cons:

  • Requires a servlet engine, and you have to restart it for changes to your configuration to be picked up
  • Output format has limited customization
  • Only works with mysql and postgresql databases (though there is some experimental support for Oracle and MS SQL)
  • Doesn’t work with views
  • The security model, while fine grained, isn’t modern/OAuth (can be solved with an API gateway (like 3scale, Tyk or ApiAxle) or proxy

The next framework I have experience with is Dropwizard.  This is a powerful framework that creates uberjars that you can run on any port as a standalone service.  It’s not limited to providing a JSON representation of database tables–if you can create a Java object, Dropwizard can serve it up as a JSON resource.

Pros:

  • Community support
  • Extreme output formatting flexibility, but be prepared to write a custom deserializer if you want to handle anything other than reads of custom formatted objects
  • Supports any database that hibernate supports
  • Built in testing support
  • Brings together ‘best of breed’ tools like Jersey, Jackson and Hibernate, so you don’t have to do the integration yourself
  • Great documentation

Cons:

  • Have to roll your own deployment solution (tarball, chef, puppet)
  • No services startup script provided
  • Shading can slow down development
  • Not yet at 1.0 release

The last one I don’t have familiarity with, but a colleague used it in the past.  It is Sparkjava.  This is a lightweight framework that fits when you have an existing Java library with functionality you want to expose.  I’m not competent to write pros/cons for this framework, but wanted to mention it.

The gorilla in the room that I haven’t had experience with (in terms of writing RESTful webs services) is Spring.  I would definitely include this in any greenfield solutions review.



#TBT: Business Process Crystallization

crystal photo

Photo by włodi

This is a repost from over a decade ago, about how software coalesces and defines business processes. The post is a little rough (“computerizing tasks”?), but hey, I’d only been blogging for months.

The ideas are sound, though. The longer I’ve been around this industry, the more the ideas in this post are reinforced.

————————————————————-

I’m in the process of helping a small business migrate an application that they use from Paradox back end to a PostgreSQL back end. The front end will remain written in Paradox. (There are a number of reasons for this–they’d like to have a more robust database, capable of handling more users. Also, Paradox is on the way out. A google search doesn’t turn up any pages from corel.com in the top 10. Ominous?)

I wrote this application a few years ago. Suffice it to say that I’ve learned a lot since then, and wish I could rectify a few mistakes. But that’s another post. What I’d really like to talk about now is how computer programs crystallize business processes.

Business processes are ‘how things get done.’ For instance, I write software and sell it. If I have a program to write, I specify the requirements, get the client to sign off on them (perhaps with some negotiation), design the program, code the program, test it, deploy it, make changes that the client wants, and maintain it. This is a business process, but it’s pretty fluid. If I need to get additional requirements specification after design, I can do that. Most business processes are fluid, with a few constraints. These constraints can be positive: I need to get client sign off (otherwise I won’t get paid). Or they can be negative: I can’t program .NET because I don’t have Visual Studio.NET, or I can’t program .NET because I don’t want to learn it.

Computerizing tasks can make processes much, much easier. Learning how to mail merge can save time when invoicing, or sending out those ever impressive holiday gift cards. But everything has its cost, and computerizing processes is no different. Processes become harder to change after a program has been written or installed to ‘help’ with them. For small businesses, such process engineering is doubly calcifying, because few folks have time to think about how to make things better (they’re running just as fast as they can to stay in place) and also because computer expertise is at a premium. (Realizing this is a fact and that folks will take a less technically excellent solution if it’s maintainable by normal people is what has helped MicroSoft make so much money. The good is the enemy of the best and if you can have a pretty good solution for one quarter of the price of a perfect solution, most folks will choose the first.)

So, what happens? People, being more flexible than computers, adjust themselves to the process, which, in a matter of months or years, may become obsolete. It may not do what they need it to do, or it may require them to do extra labor. However, because it is a known constraint and it isn’t worth the investment to change, it remains. I’ve seen cruft in computer programs (which one friend of mine once declared was nothing but condensed business knowledge), but I’m also starting to realize that cruft exists in businesses too. Of course, sweeping away business process cruft assumes the same risks as getting rid of code cruft. There are costs to getting rid of the unneeded processes, and the cost of finding the problems, fixing them, documenting them, and training employees on the new ones, may exceed the cost of just putting up with them.

“A computer lets you make more mistakes faster than any invention in human history – with the possible exceptions of handguns and tequila.” -Mitch Ratcliffe, Technology Review, April 1992

A computer, for the virtue of being able to instantaneously recall and process vast amounts of data, also crystallizes business processes, making it harder to change them. In additional to letting you make mistakes quickly, it also forces you to let mistakes stand uncorrected.


Headline: Android User Buys App

cash register photo

Photo by liewcf

A few weeks ago, I bought my first app on Google Play.  Wait?  I thought Android users don’t buy apps?  Well, what can I say, I like to break the mold.

Actually, I think I’m pretty typical for a high end Android phone owner.  I have had an Android phone since 2010–I paid hundreds of dollars for each of my phones.  My wife is a diehard iPhone owner.  At the time I purchased, she wondered why I wanted to buy an Android.  The application process for writing apps is one reason, and another is being able to write an app, on whatever computer I wanted, and install it on my phone.  Now I’m in Google’s ecosystem, and it would take a lot to pull me out of it.

Regardless, I finally bought an app!  I was looking for music on my phone, and have long been a fan of soma fm, ever since John Argo introduced me to them–about a decade ago.  Groove Salad is excellent for doing development.  I looked up their app, and it was $4.  soma fm is one of those organizations that I’ve been meaning to contribute to for years (like KGNU, they are listener supported and commercial free), but never got over the hump.

This was my chance to support the radio station which I loved!  Google made it easy–just had to enter a billing method (options included credit card, paypal, and bill to my phone account) and re-enter my password.  (Yes, I realize this was a small donation in the scheme of things.  The app has convenient links to the donation page.

So, what does this anecdote mean for people looking to make a living selling apps?

Don’t count on me, because the only app I’ve ever paid for was because it was a donation.

I had a long conversation with a friend about this and it appears to me that mobile apps are, in the vast majority of cases, complements to existing businesses, and not businesses themselves.  That was my experience at 8z as well. Being a complement is still a ginormous market, but it isn’t a goldrush for individuals.


Hard Numbers About My Book

numbers photo

Photo by MrHicks46

I self published a Developing Cross Platform Mobile Applications with Cordova CLI last fall. It’s about the Cordova command line tool (Cordova CLI). Cordova is a way for web developers to build mobile apps that are distributed via the various app stores and can access app functionality (your list of contacts, for instance). The CLI is the main method of interacting with Cordova–managing your files, building apps, etc.

You can see my take on writing the book and marketing it, but I wanted to give some hard numbers on the results.

I thought I’d share some lessons from this experience. I started on 8/29/2013, had my first purchase, for $4, on 9/3/2013 (Leanpub lets users buy in progress books and get any updates), and published the 100% complete version on 10/4/2013. The book is 54 pages long.

Sales numbers as of today:

  • 56 readers
  • 47 readers who paid for the book
  • 9 readers who received free copies (reviewers and members of the Cordova community, because I am grateful for the work they’ve done)
  • 2 refunds (Leanpub has a 45 day no questions asked “Happiness Guarantee” refund policy)
  • Price range: $4-$20
  • Current price range: $20
  • Total royalties: $572.73
  • Number of people who paid over list price: 2

Here’s a graph of when purchases took place:

Sales By Week for Developing With Cordova CLI

Visits/conversions from 8/29/2013 to 9/9/2014 to the leanpub page (note that these don’t match up with the above numbers because if someone disables Javascript or cookies from Google, Google Analytics won’t track the purchase, and also I didn’t enable conversion tracking until Sep 18, 2013):

  • 5897 sessions
  • 4731 visitors
  • 37 book purchases tracked
  • 0.63% conversion rate
  • 53.75% abandonment rate
  • 84.92% bounce rate
  • 79.67% new sessions

Traffic sources:

  • 59.4% of sessions are from organic search
  • 13.5% from referrals
  • 13.2% from social
  • 10.6% direct
  • 2.3% from “other”
  • 0.9% from paid search

Highest referral sites for visits:

  1. Stackoverflow
  2. mooreds.com
  3. devgirl.org (I wrote a guest post)
  4. twitter
  5. google groups
  6. cloudfour.com (I wrote a guest post)
  7. hacker news

Highest referral sites for conversions (out of 14 conversions):

  1. Direct
  2. devgirl.org
  3. Google (organic)
  4. mooreds.com (embed and referrals combined)
  5. twitter

Pricing matters.  I varied the price, depending on how close the book was to being complete. The vast majority of my royalties came when I priced the book at $20.  That felt fair to me for a fifty page ebook about a technical topic. If someone charges $60/hour and this book saves them an hour, they have a 3x ROI (yes, I probably should charge more).

Overall, writing a book has been a great learning experience (and the couple hundred dollars in my pocket feel good too).  I learned about writing, research, and marketing. I learned that very few people buy an ebook and return it. I learned that sometimes a single sentence in a book can take you an hour to verify. I learned that it can be fun to write and promote your book. In retrospect, the only thing I’d change would be to write on an evergreen topic.  Cordova is moving fast enough that, while there is still value in this book, it needs a refresh every six months or so to remain relevant.


Installing the AngularJS Docs on Your Computer

unplugged photo

Photo by jenny downing

If you want access to the AngularJS API docs offline, download the zipfile for the version you are using (latest as of writing is 1.2.23), unzip it it to a web server directory, and visit the URL in your browser.

The docs need to be served via http or https to work, so you can’t just download the zip file, unzip, and open up the index.html file in your browser.

I use the python simple web server.  If you are also using this simple web server, make sure to start the python web server in the top level directory of the unzipped files, not the docs directory.  The docs reach up a level and pull in javascript and css.

Obviously, you don’t get any links to outside blogs, articles or videos, but this does give you the API, the tutorial and the guide.  When I’m without internet access, having this on my computer gives me at least a fighting chance of solving any issues I run into.



I Want to Pay You Money! (Except When I Don’t)

money photo

Photo by 401(K) 2013

I saw this post from Kin Lane talking about Zapier and how one of the many advantages it has over similar services is its pricing.  I completely agree.  While I like free as much as the next person, when I’m building on something, I want to pay for it, or at least have it monetized in some fashion (Kin has a nice list of ways for API providers to monetize).  Paying for a service means:

  • the company can survive
  • great employees can be paid
  • when I complain, the company has an incentive to listen
  • the value I get from the service is above what I’m paying (aka consumer surplus), if I’m a reasonable facsimile of homo economicus.

All of these are really nice attributes of a technology I’m going to build on (not just ‘date’ as Kin says).  This is an interesting dichotomy, because the fastest way to growth is to provide a free service–then there’s no friction to signing up.

I guess the answer, at least for software products where the marginal cost is very very low, is a freemium offering, like Zapier.  Get the user in, show them how your value proposition works, and then ask them for money when they are hooked.  Just don’t make the freemium level unusable!


King Soopers, Please Fix Your HomeShop Service

 

King Soopers is leaving money on the table.

I tweeted about this a while ago, but thought it was worth expanding into a full blog post.

Now, first, let me say that I haven’t used new shopping services like Instacart, but I agree with Gary Vee (link is a video, you want to go to 6:50)–home shopping gives me more time and that is an extremely precious commodity that I am willing to trade money for.

King Soopers, for readers outside of Colorado, is one of the two major grocery store chains–it’s owned by Kroger, a name that may be more familiar to you.  (The other is Safeway, and they don’t do home delivery to my area.)  The King Soopers online shopping experience, is abysmal.

Let me count the ways:

  1. It’s difficult to find the link from their home page (here it is if you want to try King Soopers HomeShop).
  2. There is no clear delivery map–you have to enter your address and then you find out if they do deliveries to your location.
  3. The UI of the shopping experience hasn’t changed since 2009 (the first time I used it).
  4. Searching is tough–synonyms are not handled (searching for ‘scallions’ returns no produce results, whereas searching for ‘green onions’ does, even though they are the same vegetable).
  5. Product description for produce is unclear. For instance, here is the description some onions: “King Soopers/Onions Yellow Organic Fresh Produce (Each)“, but the price is is by the pound.  So, when I put in 1 into the quantity section, am I getting one onion or one pound of onions?  I don’t know.
  6. Sorting is limited to ‘Brand’ or ‘Description’.  That’s right folks, an ecommerce site where you can’t sort on price.
  7. Browse options are not clear–they have an ‘aisle’ metaphor, but organic produce is in a different category than regular produce.
  8. Product images are spotty.
  9. They don’t have a submit event fire when you hit ‘enter’ in the search box.  To be fair, this issue only affects FireFox.
  10. They don’t have every product a store has.  But wait, aren’t they fulfilling from the same warehouse?  I don’t know.

So, why would you ever use King Soopers HomeShop?  Because home delivery is so dang easy, and spending an extra $11 to not have to go to the store is worth it, especially for a big shopping trip.  There are other reasons as well:

  • No (or far fewer) impulse buys.  Maybe this is the reason they aren’t investing in this product?
  • You can save a list of staples and just re-order it.
  • Did I mention they deliver food to your house?  The drivers have been very nice, and even brought the bags into our house at times.
  • The UI for picking a pickup time is good, and I haven’t encountered any traffic jams.
  • I’ve been happy about the quality of non fungible items I’ve had picked out for me (such as lettuce).
  • They are good about substitutions.  If something you request is out of stock, there are three choices: ‘no substitutions, just omit’ or ‘please substitute’.  If you choose the latter, you can either accept or reject the substitution at delivery.

But the best reason for using HomeShop is the convenience of having your food delivered to you for a reasonable price.  As a busy person, this is huge.

I really really want King Soopers to repair the crappy parts of this service and make it amazing.  Heck, I’ll even consult with you on it.  Home delivery is a win in so many ways–please fix it, King Soopers.



© Moore Consulting, 2003-2014 +