Dave Johnson on open web technologies, social software and software development
In part one, I explained the basics of the example Usergrid-Ember "Checkin" app, how the index page is displayed and how login is implemented. In part two, I'll explain how Ember.js can be hooked into the Usergrid REST API to store and query JSON objects.
Ember.js includes a feature referred to as Ember-Data, which provides a persistence interface for storing and retrieving JavaScript objects that could be stored in memory, or stored on a server and accessed via REST API.
To use Ember-Data with your REST API you've got to define an Ember-Data model and add an Ember-Data REST adapter. If your REST API differs from what Ember-Data expects then you will probably have to extend the built-in REST adapter to handle your URL pattens, and extend the built-in REST serializer to handle your JSON format. By extending Ember-Data in this way, you can use it to store and query data from Usergrid without using the Usergrid JavaScript SDK at all. Below I'll explain what I had to do to make the Checkin app's Activities collection available via Ember-Data.
Ember-Data expects each of your REST API collections to have a defined data model, one that extends the DS.Model class. Here's what I added for the Activities collection:
From app.js (<a href="https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L18" >link)
App.Activity = DS.Model.extend({ uuid: DS.attr('string'), type: DS.attr('string'), content: DS.attr('string'), location: DS.attr('string'), created: DS.attr('date'), modified: DS.attr('date'), actor: DS.attr('string'), verb: DS.attr('string'), published: DS.attr('date'), metadata: DS.attr('string') });
The Ember-Data REST adapter expects a REST API to follow some common conventions for URL patterns and for JSON data formats. For example, if your REST API provides a collection of cats then Ember-Data will expect your REST API to work like so:
What Ember-Data expects for a cats collection:
Usergrid follows the above conventions for collections, but there are some exceptions. For example, the Usergrid Activities collection. A GET on the /activities
path will return the Activities of the users that you (i.e. the currently authenticated user) follow. You don't POST new activities there, instead you post to your own Activities collection at the path /users/{your-user-id}/activities
. It works like this:
Usergrid's Activities collection:
To adapt the Activities collection to Ember-Data, I decided to create a new model called NewActivity. A NewActivity represents the data needed to create a new Activity, here's the model:
From app.js (<a href="https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L132" >Link)
// Must have a special model for new activity because new // Activities must be posted to the path /{org}/{app}/users/activities, // instead of the path /{org}/{app}/activities as Ember-Data expects. App.NewActivity = DS.Model.extend({ content: DS.attr('string'), location: DS.attr('string'), actor: DS.attr('string'), verb: DS.attr('string') });
Then, in Checkin's custom REST adapter, I added logic to the pathForType()
function to ensure that NewActivities are posted to the correct path. Here's the adapter:
From app.js (<a href="https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L40" >Link)
App.ApplicationAdapter = DS.RESTAdapter.extend({ host: Usergrid.getAppUrl(), headers: function() { if ( localStorage.getItem("access_token") ) { return { "Authorization": "Bearer " + localStorage.getItem("access_token") }; } return {}; }.property().volatile(), // ensure value not cached pathForType: function(type) { var ret = Ember.String.camelize(type); ret = Ember.String.pluralize(ret); if ( ret == "newActivities" ) { // Must have a special logic here for new activity // because new Activities must be posted to the // path /{org}/{app}/users/activities, instead of the // path /{org}/{app}/activities as Ember-Data expects. ret = "/users/" + Usergrid.user.username + "/activities"; } return ret; } });
You can see a couple of other interesting things in the example above. First, there's the host
field which specifies the base-URL of the REST API for the Checkin app. Next, there's the headers()
function, which ensures that every request carries the access_token
that was acquired during login.
Ember-Data also has expectations about the JSON format returned by a REST API. Unfortunately, what Ember-Data expects and what Usergrid provides are quite different. The two examples below illustrate the differences:
Ember-Data vs. Usergrid JSON formats
Ember-Data expects collections like this: { cats: [{ "id": "6b2360d0", "name": "enzo", "color": "orange" },{ "id": "a01dfaa0", "name": "bertha", "color": "tabby" }] } |
Usergrid returns collections like this: { action: "get", path: "/cats", count: 2, entities: [{ "uuid": "6b2360d0", "type": "cat", "name": "enzo", "color": "orange" },{ "uuid": "a01dfaa1", "type": "cat", "name": "bertha", "color": "tabby" }] } |
|
Ember-Data expects individual objects like this: { cat: { "id": "a01dfaa0", "name": "bertha", "color": "tabby" } } |
Usergrid returns individual objects like this: { "id": "a01dfaa0", "type": "cat", "name": "bertha", "color": "tabby" } |
You can see two differences above. Ember-Data expects JSON objects to be returned with a "type key" which you can see above: the "cats" field in the collection and the "cat" field in the individual object. Also, Ember-Data expects an object's ID field to be named "id" but Usergrid returns it as "uuid."
The deal with these differences, the Checkin app extends Ember-Data's DS.RESTSerializer
. Here's the code:
From app.js (<a href="https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L75" >Link)
App.ApplicationSerializer = DS.RESTSerializer.extend({ // Extract Ember-Data array from Usergrid response extractArray: function(store, type, payload) { // Difference: Usergrid does not return wrapper object with // type-key. So here we grab the Usergrid Entities and stick // them under a type-key var typeKey = payload.path.substring(1); payload[ typeKey ] = payload.entities; // Difference: Usergrid returns ID in 'uuid' field, Ember-Data // expects 'id'. So here we add an 'id' field for each Entity, // with its 'uuid' value. for ( var i in payload.entities ) { if ( payload.entities[i] && payload.entities[i].uuid ) { payload.entities[i].id = payload.entities[i].uuid; } } return this._super(store, type, payload); }, // Serialize Ember-Data object to Usergrid compatible JSON format serializeIntoHash: function( hash, type, record, options ) { // Usergrid does not expect a type-key record.eachAttribute(function( name, meta ) { hash[name] = record.get(name); }); return hash; } });
In the code above you can see how the extractArray()
method moves the "entities" collection returned by Usergrid into a type-key field as expected by Ember-Data and how it copies the "uuid" field to add the "id" field that Ember-Data expects.
We also need to transform the data that Ember-Data sends to Usergrid. You can see this above in the serializeInHash()
function, which ensures that when data is POSTed or PUT to Usergrid, the type key is removed because that's what Usergrid expects.
To implement Add-Checkin, I added an HTML template called "add-checkin" to Checkin's index.html file. The template displays an Add-Checkin form with two fields: one for content and one for the location. Here's what it looks like in all its modal glory:
Both fields are simple strings (someday I'd like to extend Checkin to use location information from the browser). I won't go into detail here, but it took a bit of research to figure out how to make a Bootstrap modal dialog work with Ember.js. Below you can see the add-checkin controller, which provides a save()
function to save a new checkin.
From app.js (<a href="https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L390" >Link)
App.AddCheckinModalController = Ember.ObjectController.extend({ actions: { save: function( inputs ) { var content = inputs.content; var location = inputs.location; var target = this.get("target"); var activity = this.store.createRecord( "NewActivity", { content: content, location: location, verb: "checkin", actor: { username: Usergrid.user.username } }); activity.save().then( function( success ) { alert("Saved"); }, function( error ) { alert("Error " + error.responseJSON.error_description); } ); } } });
In the code above you can see how easy it is to access Usergrid data via Ember-Data now that we've got our custom REST adapter and serializer in place. We create a new Activity with a call to this.store.createRecord()
and to save it all we need to do is activity.save()
.
To sum things up, here are some closing thoughts and observations.
I appreciate any feedback you might have about this article, the Usergrid-Ember project and Apache Usergrid. If you want to see how the whole Usergrid-Ember project fits together, find it on GitHub here: Usergrid-Ember. Next up, I'll write about my experiences using Apache Shiro to replace Spring Security in Apache Roller.
Dave Johnson in Web Development
05:23AM Jan 26, 2015
Comments [0]
Tags:
asf
baas
ember
javascript
usergrid
The next one of my 2014 Side projects that Id like to share is Usergrid-Ember, an experiment and attempt to learn more about Ember.js and Apache Usergrid by implementing the Checkin example from my Usergrid mobile development talk. If you're interested in either Usergrid or JavaScript web development then I hope you'll read on...
Ember.js is one of the leading frameworks for building browser-based apps. It's one of many JavaScript Model View Controller (MVC) frameworks. Generally speaking, these frameworks let you define a set of routes or paths in your app, for example /index, /orders, /about, etc. and map each to some JavaScript code and HTML templates. Handling a route usually means using Ajax to grab some model data from a server and using a template to create an HTML view of the data that calls functions provided in a "controller" object.
JavaScript MVC frameworks are not simple and each has its own learning curve. Is it really worth the learning time when you can do so much with a little library like jQuery? For most projects I think the answer is yes. These frameworks force you to organize your code in a logical and consistent way, which is really important as projects grow larger, and they provide features that may save you a lot of development time.
Based on what I've seen on the net and local meet-ups, the leading frameworks these days are Ember.js and AngularJS. After I saw Yehudi Katzs talk at All Things Open, I decided to spend some time learning Ember.js.
The first thing you see when you visit the Ember.js site is a big button that says "DOWNLOAD THE STARTER KIT" and so that is where I started. The Starter Kit is a, a minimal Ember.js project with about twenty JavaScript, HTML and CSS files. It's a good way to start: small and simple.
Ember.js Starter Kit files:
Sidebar: I do hope they keep the Starter Kit around when the new Ember-CLI tool matures. Ember-CLI generates too many magic boiler-plate files and sub-directories for somebody who is trying to understand the basics of the framework. And this is an interesting point of view: Ember-CLI is Making You Stupid by Yoni Yechezkel.
I like to bite off more than I can chew, so I decided to use a couple of other tools. I used Bower to manage dependencies and Grunt to concatenate and minify those dependencies, and other things like launching a simple web server for development purposes. I also decided to use Bootstrap to provide various UI components needed, like a navbar and nicely styled list views.
I won't cover the details, but it was relatively easy to get Bower and Grunt working. Here are the config files in case you are interested: bower.json and Gruntfile.js. I did hit one problem: when I included Bootstrap as one of my dependencies the Glyphicons would all appear as tiny boxes, so I decided to pull Bootstrap from a CDN instead (looks like there is a fix for that now).
Every Ember.js app needs to define some routes. There is a default route for the "/" path which is called the index route, and you can add your own routes using the Router object. The snippet below shows what I needed to get started:
Part of app.js (link)// create the ember app object App = Ember.Application.create(); // define routes App.Router.map(function() { this.route("login", { path: "/login" }); this.route("logout", { path: "/logout" }); this.route("register", { path: "/register" }); });
Ember.js will look for the JavaScript Route and Controller objects as well as the HTML template using the names above. For example: Ember.js will expect the login route to be named App.LoginRoute
, the controller to be named App.LoginController
and the template to be named "login."
Let's talk about the index route. When a user arrives at your app theyll be directed to the index route. Ember.js will then look for a JavaScript object called App.IndexRoute
to provide the model data and JavaScript functions needed for the index page. Heres a partial view of the index route:
App.IndexRoute = Ember.Route.extend( { // provide model data needed for index template model: function() { if ( this.loggedIn() ) { return this.store.find("activity"); } return []; } });
The index page of the Checkin app shows the Checkin activities of the people that you follow. Above you can see how to route's model()
function makes that data available to the template for display. If the user is logged in we call the store.find(activity)
function to call the Usergrid REST API to get an array of the latest Activity objects. There is some serious Ember-Data magic going on there and I'll cover that in part two of this article.
To display the index route, Ember looks for an HTML template called index and will use that template to display the index page. Below is the index template. The template is a Handlebars template and the things that appear in double curly-braces are Handlebars expressions.
Part of index.html (link){{action 'showModal' 'add-checkin-modal' model }}>Add Checkin{{#each item in model}}
- {{item.content}} | {{item.location}}
{{/each}}
In the above template you can see a couple of {{action}}
expressions that call out to JavaScript methods defined in the Checkin app. The part of the code that uses the model is in the {{#each}}
loop which loops through each Activity in the model and dispays an HTML list with the the item.content and item.location of each Activity.
Here's what the above template looks like when displayed in a browser:
In Checkin, login is implemented using HTML Local Storage. Once a user has successfully logged in, the app stores the username and the user's access_token in Local Storage. When user arrives at the index page, we check Local Storage to see if that user is logged in and if not, we direct them to the login route, which in turn displays the login page using the template below.
Part of index.html (link)Please Login
Email address {{input class="form-control" type="text" valueBinding="username" placeholder="Username"}} Password {{input class="form-control" type="password" valueBinding="password" placeholder="Password"}} Login Register as new user.
The LoginController provides the functions needed by the Login page itself and there are two. There is a login()
function (called on line 27 above) that performs the login, and there is a register()
function (called on line 31 above) that directs the user to the New User Registration page. Here's a snippet of code from the App.LoginController
that provides these two functions:
App.LoginController = Ember.Controller.extend({ actions: { login: function() { // login by POST to Usergrid app's /token end-point var loginData = { grant_type: "password", username: this.get("username"), password: this.get("password") }; $.ajax({ type: "POST", url: Usergrid.getAppUrl() + "/token", data: loginData, context: this, error: function( data ) { // login failed, show error message alert( data.responseJSON.error_description ); }, success: function( data ) { // store access_token in local storage Usergrid.user = data.user; localStorage.setItem("username", loginData.username ); localStorage.setItem("access_token", data.access_token ); // clear the form this.set("username", ""); this.set("password", ""); // call route to handle post-login transition this.get("target").send("onLogin"); } }); }, register: function() { this.transitionToRoute("register"); } } });
The above code shows how to login to a Usergrid app using jQuery's Ajax feature. The login()
function takes the username and password values from the login form, puts those in a JSON object with grant_type "password" and posts that object to the /token
end-point of the Usergrid app. If that post succeeds, the response will include an access_token. We store that in Local Storage; we'll need to use it in all subsequent calls to Usergrid.
Usergrid fans will notice that I'm not using the Usergrid JavaScript SDK. That's because Ember.js provides Ember-Data, which acts as a very nice REST client and can be adapted to work with the URL structure and JSON formats of just about any REST API. I'll write about that in part two of this article.
Dave Johnson in Web Development
04:39AM Jan 20, 2015
Comments [0]
Tags:
asf
baas
emberjs
javascript
For various reasons, I've always got a couple of coding projects on the back burner, things that I hack around with on weekends and breaks. In 2014, I started four projects and learned about Ember.js, jQuery Mobile, Apache Shiro, Apache CXF and the Arquillian test framework.
I like to share my code, so I've put my code on GitHub and I'm going to write a brief post about each here on my blog. I'll provide links as I go and, of course, I welcome any criticisms and suggestions for improvement that you might have. First up: the Usergrid-Mobile project.
To be honest, Budapest was the goal of this project. In the Spring of 2014, I decided that the best chance of getting to ApacheCon EU in Budapest was to create a great "mobile development with Usergrid" talk, and to do that I needed a great example project. The resulting project shows how to create a dumbed-down Foursquare-style "checkin" app using HTML5, JavaScript, jQuery Mobile and Apache Cordova.
Luckily for me, my talk was accepted for ApacheCon EU and in November I traveled to Budapest (took some photos) and gave the talk there.
I also presented the talk at the All Things Open conference in Raleigh, NC and you can view a video of that talk, Mobile Development with Usergrid on YouTube.
You can find the code for usergrid-mobile on GitHub. I also created a Vagrant File to launch a local instance of Usergrid for demo purposes. It's called usergrid-vagrant.
That's all for now. Next up: Usergrid-Ember.
Dave Johnson in Open Source
03:37AM Jan 05, 2015
Comments [0]
Tags:
asf
javascript
usergrid
My eldest son Alex and his friend Austin have started a website design and creation business called Phoenix Websites and, of course, I think this is a great thing. They're not yet out of high school and just getting started, but they've already landed a couple of real live customers. They've got some skills and are not afraid of hard work, so if you're a Triangle-area small business owner and you need a nice new website, check them out.
Like any new business, they need some link love so here we go: Phoenix Websites: Website design and creation services in the Raleigh-Durham Triangle-area. Follow them on twitter at @phoenixrdu
Dave Johnson in Web Development
02:07AM Dec 01, 2014
Comments [0]
Tags:
asf
business
I travelled to Budapest, Hungary for a couple of weeks for a very nice vacation with my wife and to speak at ApacheCon EU. Here are the slides that I presented at ApacheCon EU:
(you can also view the presentation on Slideshare.)
And here is the session abstract:
Whether you are building a mobile app or a web app, Apache Usergrid (incubating) can provide you with a complete backend that supports authentication, persistence and social features like activities and followers all via a comprehensive REST API and backed by Cassandra, giving you linear scalability. All that, and Usergrid is open source too.
This session will explain how you can use Usergrid to provide a back-end for your application. Well start with an overview of Usergrid features, then explore in depth how to authenticate users, store data and query data with the REST API provided by a Usergrid server. Well develop a simple HTML5 app and package it as a native mobile app via Apache Cordova. We'll also cover how to run Usergrid locally for development and testing.
Dave Johnson in Open Source
05:09AM Nov 29, 2014
Tags:
apache
apachecon
asf
baas
I've been working at Apigee since September 2013 and one of the things I love most about my new job is the fact that I'm actively contributing to open source again.
I'm working on Apache Usergrid (incubating), an open source Backend-As-A-Service (BaaS) that's built on the Apache Cassandra database system. Apigee uses Usergrid as part of Apigee Edge (see the Build Apps part of the docs).
Apigee contributed code for Usergrid to the Apache Software Foundation back in October 2013 and Usergrid is now part of the Apache Incubator. The project is working towards graduating from the Incubator. That means learning the Apache way, following the processes to get a release out and most importantly, building a diverse community of contributors to build and maintain Usergrid.
One on the most important parts of building an open source community is making it easy for people to contribute and and that's why I submitted a talk to the ApacheCon US 2014 conference (April 7-9 in Denver, CO) titled How to Contribute to Usergrid.
The talk is intended to be a briefing for contributors, one that will lead you through building and running Usergrid locally, understanding the code-base and test infrastructure and how to get your code accepted into the Usergrid project.
Here's the outline I have so far:
I'm in the process of writing this talk now so suggestions and other feedback are most welcome.
Dave Johnson in Open Source
12:10PM Mar 16, 2014
Comments [0]
Tags:
apachecon
asf
baas
cassandra
java
opensource
usergrid
I'm not motivated to write new blog entries but for some reason I was motivated to update my blog's theme. This time I decided to go with Twitter Bootstrap + jQuery. It's responsive, so to speak. What do you think? I think it takes a little too long for the banner image to load.
Dave Johnson in Blogging
04:10PM Jan 19, 2014
Comments [2]
Tags:
bootstrap
roller
Just a quick note about this site:
Today I upgraded this site to the latest Roller 5.1.0-SNAPSHOT (unreleased) code base. I did this to fix a couple of vulnerabilities found recently by researchers from Coverity (thanks Coverity!).
The Roller team fixed the vulnerabilities reported by Coverity in both the Roller 5.1-SNAPSHOT (unreleased) and the Roller 5.0.x branch. If you're running Roller, you should upgrade to Roller 5.0.1 immediately.
See also: Apache Roller 5.0.2 security fix release now available.
It's been while since I upgraded this site (or even blogged here) so the upgrade was a little painful. When I first upgraded I found that the JSPWiki plugin was broken and the site would not even load. Turns out, I was using an archaic copy of the JSPWiki jar and it was compiled against an equally archaic version of Lucene. Since we recently upgraded the version of Lucene included in Roller, this broke things. I fixed this by upgrading the Roller JSPWiki plugin to use the latest code from Apache JSPWiki. I also created a Github repo with the new JSPWiki code, which you can find here: Roller JSPWiki Plugin on Github.
Dave Johnson in Roller 06:26AM Nov 03, 2013 Comments [3]
I've already mentioned this on Twitter and LinkedIn, but just in case you missed it: I'll be speaking tomorrow night at the Triangle AWS and Triangle DevOps joint meetup at Argyle Social in Durham, NC. I'll give a quick overview of cloud orchestration and Wayin Hub. Then I'll dive into the details of how we automate deployment, scaling and backups for Wayin Hub using AWS and AWS Cloud Formation.
As a little teaser, here's a GIF animation of my automated deployment slide:
For more information check the Triangle DevOps page for the event.
UPDATE: slide are now on SlideShare.
Dave Johnson in Web Development
12:16PM Jun 18, 2013
Comments [0]
Tags:
asf
aws
cloud
devops
orchestration
wayin
Newer versions of Apache Cassandra include CQL, an SQL-like query language that supports both query, update and delete statements as well as the Data Definition Language (DDL) statements like create and alter for tables and indexes. You can create tables (known as column families in Cassandra lingo) just like you can in a relational database, but there are some caveats.
[Read More]
Dave Johnson in Open Source
01:56PM May 23, 2013
Comments [2]
Tags:
asf
bigdata
cassandra
wayin
wayinhub
This is the sixth in my series of Web Integration Patterns. Check out the intro at this URL http://rollerweblogger.org/roller/entry/web_integration_patterns
This pattern is about integrating web sites and applications by using standard feed formats to convey timely information, updates, status messages, events and other things from one web application to another.
Dave Johnson in Web Development
06:38AM Oct 08, 2012
Comments [1]
Tags:
atom
feeds
rss
wip
Ten years ago on this day, O'Reilly published an article that I wrote called Building an Open Source J2EE Weblogger, the article that introduced the Roller weblogger (now known as Apache Roller) to the world. It changed my career and my life in a bunch of nice ways and 10 years later I'm still benefiting from my choice to create Roller and write that article. So you can get a taste of the times, here's the intro:
Building an Open Source J2EE Weblogger: As a Java developer, you should be aware of the tremendous wealth of open source development software that is available for your use -- even if you have no desire to release any of your own software as open source. In this article, I will introduce you to some of the most useful open source Java development tools by showing you how I used these tools to develop a complete database-driven Web application called Roller.
Roller fits into the relatively new category of software called webloggers: applications that make it easy for you to maintain a weblog, also known as a blog -- a public diary where you link to recent reading on the Web and comment on items of interest to you.
The Roller Web application allows you to maintain a Web site that consists of a weblog, an organized collection of favorite Web bookmarks, and a collection of favorite news feeds. You can define Web pages to display your weblog, bookmarks, and news feeds. By editing the HTML templates that define these pages, you have almost total control over the layout and appearance of these pages. Most importantly, you can do all of this without leaving the Roller Web application -- no programming is required.
I've written and talked about Roller and the history of Roller numerous times. If you're interested in learning more about it here's my most recent Roller presentation, which covers Roller history in some detail:
These days, Roller isn't really thriving as an open source project. Wordpress became the de facto standard blogging package and then micro-blogging took over the world. There are only a couple of active committers and most recent contributions have come via student contributions. Though IBM, Oracle and other companies still use it heavily, they do not contribute back to the project. If you're interested in contributing to Roller or becoming part of the Apache Software Foundation, then Roller needs YOU!.
Dave Johnson in Roller
03:41AM Apr 17, 2012
Comments [5]
Tags:
apacheroller
blogging
ibm
java
oracle
Congrats to the Apache Rave team on reaching top-level project status.
OpenSocial API Blog: Announcing Apache Rave: The project started only a year ago, March 1 2011, when entering the Apache Incubator as a collaborative effort by individuals from a wide range of corporations, non-commercial organizations, and institutes from around the world and was seeded by code donations from The MITRE Corporation, Indiana University Pervasive Technology Institute, SURFnet, OSS Watch, Hippo, and numerous individual developers.
Rave builds on open standards and leverages and aligns with other open source projects like Apache Shindig and Apache Wookie to deliver a lightweight, flexible, widget-based platform that easily scales across federated application integrations, social intranets, and multi-channel social communities with enhanced personalization and customized content delivery.
Dave Johnson in Social Software 04:54AM Mar 28, 2012
Interesting speculation on the make-up of Amazon's cloud:
Amazon EC2 cloud is made up of almost half-a-million Linux servers | ZDNet :
We know that Linux on servers is big and getting bigger. We also knew that Linux, thanks to open-source cloud programs like Eucalyptus and OpenStack, was growing fast on clouds. What he hadnt know that Amazons Elastic Compute Cloud (EC2), had close to half-a-million servers already running on a Red Hat Linux variant.
Huang Liu, a Research Manager with Accenture Technology Lab with a Ph.D. in Electrical Engineering whose has done extensive work on cloud-computing, analyzed EC2s infrastructure and found that Amazon EC2 is currently made up of 454,400 servers.
Dave Johnson in Web Development
03:18AM Mar 17, 2012
Tags:
amazon
cloud
JIRA's got a real REST API now:
REST easy with JIRA 5 | Atlassian Blogs: Now that JIRA 5 is out, lets talk about one of my favorite features of this new release, JIRAs new REST API. JIRA has supported remote APIs for many years with SOAP, XML-RPC, and JSON-RPC. However, telling developers that you support SOAP (and only SOAP) is like saying that you like writing applications with COBOL its out of style. Todays cool kids gravitate towards REST. Its clean, simple, and highly portable across languages and frameworks.
And checkout the nice looking API docs, which look like they were generated by WADL-to-HTML.
An alternative to Atlassian's new API is the recently release Rational OSLC Adapter for JIRA, which allows you to do more sophisticated integrations with JIRA including delegated UIs for issue creation and selection.
Dave Johnson in Web Development
04:20AM Mar 01, 2012
Tags:
jira
json
oslc
rest
This is the fifth in my series of Web Integration Patterns. Check out the intro at this URL http://rollerweblogger.org/roller/entry/web_integration_patterns
Allow other web sites and applications to integrate your site into their web pages by providing an embeddable user interface, commonly known as a Gadget or Widget, which allows users to view and interact with your site in the context of other sites.
Dave Johnson in Web Development
02:52AM Feb 22, 2012
Comments [0]
Tags:
asf
gadgets
widgets
This is such good news for the web that it gets its own blog entry. According to Dan Web, an engineer at Twitter:
@timhaines plus, now I'm in charge of undoing twitters hashbang URLs I can
confirm that all the issues in that article are very real.
@danwrong x months from now (when your project completes) Twitter will no
longer use hashbangs?
@timhaines correct. All gone. It was a mistake for several reasons.
PushState or bust.
The whole conversation is here:
http://storify.com/timhaines/hashbang-conversation
Here's an excellent chapter on HTML 5 history and PushState: http://diveintohtml5.info/history.html
And in case you've forgotten, here's why hashbangs suck.
Dave Johnson in Web Development 08:02AM Feb 21, 2012 Comments [0]
far as I can tell, clicking theFacebook "Like" button means "please spam me endlessly"
— Dave Johnson (@snoopdave) February 5, 2012
Dave Johnson in Social Software
11:42AM Feb 11, 2012
Comments [0]
Tags:
facebook
Worth a read and related to my Web Integration Patterns post on Embedded Properties in HTML:
HTML5 Microdata and Schema.org:HTML5 Microdata and Schema.org On June 2, 2011, Bing, Google, and Yahoo! announced the joint effort Schema.org. When the big search engines talk, Web site authors listen. This article is an introduction to Microdata and Schema.org. The first section describes what HTML5, Microdata and Schema.org are, and the problems they have been designed to solve. With this foundation in place section 2 provides a practical tutorial of how to use Microdata and Schema.org using a real life example from the cultural heritage sector. Along the way some tools for implementers will also be introduced. Issues with applying these technologies to cultural heritage materials will crop up along with opportunities to improve the situation.
Dave Johnson in Web Development
03:48AM Feb 09, 2012
Tags:
html5
linkeddata
wip
Worth a read:
Understanding Google's new privacy policy: When Google changed its privacy policy last week, they made a strong effort to ensure that everyone knew that a change had occurred, but if you tried to figure out what had actually changed, you had to wade through a lot of buzzwords and legalese. Now the Electronic Frontier Foundation's Rainey Reitman explains it in simple language.
Dave Johnson in Social Software
08:39AM Feb 02, 2012
Tags:
google
privacy
« Previous page | Main | Next page »