<?xml version="1.0" encoding='utf-8'?>
<!-- 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
-->
<?xml-stylesheet type="text/xsl" href="https://rollerweblogger.org/roller-ui/styles/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom">
    <title type="html">Blogging Roller</title>
    <subtitle type="html">Dave Johnson on open web technologies, social software and software development</subtitle>
    <id>https://rollerweblogger.org/roller/feed/entries/atom</id>
        <link rel="self" type="application/atom+xml" href="https://rollerweblogger.org/roller/feed/entries/atom?tags=javascript" />
    <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/" />
    <updated>2026-05-18T08:23:39+00:00</updated>
    <generator uri="http://roller.apache.org" version="6.1.5">Apache Roller</generator>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/usergrid-ember-pt-2</id>
        <title type="html">Usergrid and Ember.js - part 2</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/usergrid-ember-pt-2"/>
        <published>2015-01-26T10:23:01+00:00</published>
        <updated>2018-02-16T12:48:34+00:00</updated> 
        <category term="Web Development" label="Web Development" />
        <category term="asf" scheme="http://roller.apache.org/ns/tags/" />
        <category term="baas" scheme="http://roller.apache.org/ns/tags/" />
        <category term="ember" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <category term="usergrid" scheme="http://roller.apache.org/ns/tags/" />
        <content type="html">&lt;p&gt;In &lt;a href=&quot;http://rollerweblogger.org/roller/entry/usergrid-ember-pt-2&quot;&gt;part one&lt;/a&gt;, I explained the basics of the example Usergrid-Ember &amp;quot;Checkin&amp;quot; app, how the index page is displayed and how login is implemented. In part two, I&amp;#39;ll explain how Ember.js can be hooked into the Usergrid REST API to store and query JSON objects.&lt;/p&gt;

&lt;a href=&quot;http://emberjs.com&quot;&gt;&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/87879b47-6b14-4c18-a17e-576a68bf62a0&quot; alt=&quot;Ember logo&quot; align=&quot;right&quot;&gt;&lt;/a&gt;

&lt;p&gt;Ember.js includes a feature referred to as &lt;a href=&quot;http://emberjs.com/guides/models&quot;&gt;Ember-Data&lt;/a&gt;, 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.&lt;/p&gt;

&lt;p&gt;To use Ember-Data with your REST API you&amp;#39;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&amp;#39;ll explain what I had to do to make the Checkin app&amp;#39;s Activities collection available via Ember-Data.&lt;/p&gt;


&lt;h3&gt;Define Ember-Data models&lt;/h3&gt;

&lt;p&gt;Ember-Data expects each of your REST API collections to have a defined data model, one that extends the DS.Model class. Here&amp;#39;s what I added for the Activities collection:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L18&amp;quot;
&amp;gt;link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.Activity = DS.Model.extend({
  uuid: DS.attr(&amp;#39;string&amp;#39;),
  type: DS.attr(&amp;#39;string&amp;#39;),
  content: DS.attr(&amp;#39;string&amp;#39;),
  location: DS.attr(&amp;#39;string&amp;#39;),
  created: DS.attr(&amp;#39;date&amp;#39;),
  modified: DS.attr(&amp;#39;date&amp;#39;),
  actor: DS.attr(&amp;#39;string&amp;#39;),
  verb: DS.attr(&amp;#39;string&amp;#39;),
  published: DS.attr(&amp;#39;date&amp;#39;),
  metadata: DS.attr(&amp;#39;string&amp;#39;)
});
&lt;/pre&gt;


&lt;h3&gt;Create a custom RESTAdapter&lt;/h3&gt;

&lt;p&gt;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:


&lt;p&gt;&lt;b&gt;What Ember-Data expects for a cats collection:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GET /cats&lt;/b&gt; - get collection of cats&lt;/li&gt;
&lt;li&gt;&lt;b&gt;POST /cats&lt;/b&gt; - create new cat.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GET /cats/{cat-id}&lt;/b&gt; - get cat specified by ID.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PUT /cats/{cat-id}&lt;/b&gt; - update cat specified by ID.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DELETE /cats/{cat-id}&lt;/b&gt; - delete cat specified by ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usergrid follows the above conventions for collections, but there are some exceptions. For example, the Usergrid Activities collection. A GET on the &lt;code&gt;/activities&lt;/code&gt; path will return the Activities of the users that you (i.e. the currently authenticated user) follow. You don&amp;#39;t POST new activities there, instead you post to your own Activities collection at the path &lt;code&gt;/users/{your-user-id}/activities&lt;/code&gt;. It works like this:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Usergrid&amp;#39;s Activities collection:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GET /activities&lt;/b&gt; - get Activities of all users that you follow.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;POST /user/{user-id}/activities&lt;/b&gt; - create new Activity for user specified by ID&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GET /user/{user-id}/activities&lt;/b&gt; - get Activities for one specific user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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&amp;#39;s the model:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L132&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;&lt;pre class=&quot;brush:js&quot;&gt;
// 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(&amp;#39;string&amp;#39;),
  location: DS.attr(&amp;#39;string&amp;#39;),
  actor: DS.attr(&amp;#39;string&amp;#39;),
  verb: DS.attr(&amp;#39;string&amp;#39;)
});
&lt;/pre&gt;

&lt;p&gt;Then, in Checkin&amp;#39;s custom REST adapter, I added logic to the &lt;code&gt;pathForType()&lt;/code&gt; function to ensure that NewActivities are posted to the correct path. Here&amp;#39;s the adapter:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L40&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.ApplicationAdapter = DS.RESTAdapter.extend({

  host: Usergrid.getAppUrl(),

  headers: function() { 
    if ( localStorage.getItem(&amp;quot;access_token&amp;quot;) ) {
      return { &amp;quot;Authorization&amp;quot;: &amp;quot;Bearer &amp;quot; 
          + localStorage.getItem(&amp;quot;access_token&amp;quot;) }; 
    } 
    return {};
  }.property().volatile(), // ensure value not cached

  pathForType: function(type) {
    var ret = Ember.String.camelize(type);
    ret = Ember.String.pluralize(ret);

    if ( ret == &amp;quot;newActivities&amp;quot; ) {
      // 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 = &amp;quot;/users/&amp;quot; + Usergrid.user.username + &amp;quot;/activities&amp;quot;;
    }
    return ret;
  }

});
&lt;/pre&gt;

&lt;p&gt;You can see a couple of other interesting things in the example above. First, there&amp;#39;s the &lt;code&gt;host&lt;/code&gt; field which specifies the base-URL of the REST API for the Checkin app. Next, there&amp;#39;s the &lt;code&gt;headers()&lt;/code&gt; function, which ensures that every request carries the &lt;code&gt;access_token&lt;/code&gt; that was acquired during login.&lt;/p&gt;


&lt;h3&gt;Create a custom RESTSerializer&lt;/h3&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ember-Data vs. Usergrid JSON formats&lt;/b&gt;&lt;/p&gt;
&lt;table&gt;
   &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Ember-Data expects collections like this:&lt;/p&gt;
&lt;pre&gt;
{
   cats: [{
       &amp;quot;id&amp;quot;: &amp;quot;6b2360d0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;enzo&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;orange&amp;quot;
   },{
       &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }]
}






&lt;/pre&gt;

      &lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Usergrid returns collections like this:&lt;/p&gt;
&lt;pre&gt;
{
   action: &amp;quot;get&amp;quot;,
   path: &amp;quot;/cats&amp;quot;,
   count: 2,
   entities: [{
       &amp;quot;uuid&amp;quot;: &amp;quot;6b2360d0&amp;quot;,
       &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;enzo&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;orange&amp;quot;
   },{
       &amp;quot;uuid&amp;quot;: &amp;quot;a01dfaa1&amp;quot;,
       &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }]
}

&lt;/pre&gt;

      &lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Ember-Data expects individual objects like this:&lt;/p&gt;
&lt;pre&gt; 
{
   cat: {
       &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }
}
&lt;/pre&gt; 

      &lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Usergrid returns individual objects like this:&lt;/p&gt;
&lt;pre&gt; 
{
   &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
   &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
   &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
   &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
}

&lt;/pre&gt; 

      &lt;/td&gt;
   &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;You can see two differences above. Ember-Data expects JSON objects to be returned with a &amp;quot;type key&amp;quot; which you can see above: the &amp;quot;cats&amp;quot; field in the collection and the &amp;quot;cat&amp;quot; field in the individual object. Also, Ember-Data expects an object&amp;#39;s ID field to be named &amp;quot;id&amp;quot; but Usergrid returns it as &amp;quot;uuid.&amp;quot;&lt;/p&gt;

&lt;p&gt;The deal with these differences, the Checkin app extends Ember-Data&amp;#39;s &lt;code&gt;DS.RESTSerializer&lt;/code&gt;. Here&amp;#39;s the code:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L75&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
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 &amp;#39;uuid&amp;#39; field, Ember-Data 
    // expects &amp;#39;id&amp;#39;. So here we add an &amp;#39;id&amp;#39; field for each Entity, 
    // with its &amp;#39;uuid&amp;#39; value.
    for ( var i in payload.entities ) {
      if ( payload.entities[i] &amp;&amp; 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;
  }
});
&lt;/pre&gt;

&lt;p&gt;In the code above you can see how the &lt;code&gt;extractArray()&lt;/code&gt; method moves the &amp;quot;entities&amp;quot; collection returned by Usergrid into a type-key field as expected by Ember-Data and how it copies the &amp;quot;uuid&amp;quot; field to add the &amp;quot;id&amp;quot; field that Ember-Data expects. &lt;/p&gt;

&lt;p&gt;We also need to transform the data that Ember-Data sends to Usergrid. You can see this above in the &lt;code&gt;serializeInHash()&lt;/code&gt; function, which ensures that when data is POSTed or PUT to Usergrid, the type key is removed because that&amp;#39;s what Usergrid expects.&lt;/p&gt;


&lt;h3&gt;Implementing Add-Checkin&lt;/h3&gt;

&lt;p&gt;To implement Add-Checkin, I added an HTML template called &amp;quot;add-checkin&amp;quot; to Checkin&amp;#39;s index.html file. The template displays an Add-Checkin form with two fields: one for content and one for the location. Here&amp;#39;s what it looks like in all its modal glory:&lt;/p&gt;

&lt;br&gt;
&lt;p&gt;
&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/5bc05437-f090-409e-90e4-c0fd978ea3ca&quot; alt=&quot;screenshot of add-checkin page&quot;&gt;
&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;Both fields are simple strings (someday I&amp;#39;d like to extend Checkin to use location information from the browser). I won&amp;#39;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 &lt;code&gt;save()&lt;/code&gt; function to save a new checkin.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L390&amp;quot;
&amp;gt;Link&lt;/b&gt;)&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.AddCheckinModalController = Ember.ObjectController.extend({

  actions: {

    save: function( inputs ) {

      var content = inputs.content;
      var location = inputs.location;
      var target = this.get(&amp;quot;target&amp;quot;);

      var activity = this.store.createRecord( &amp;quot;NewActivity&amp;quot;, {
        content: content,
        location: location,
        verb: &amp;quot;checkin&amp;quot;,
        actor: {
          username: Usergrid.user.username
        }
      });

      activity.save().then(
        function( success ) { 
          alert(&amp;quot;Saved&amp;quot;); 
        },
        function( error ) { 
          alert(&amp;quot;Error &amp;quot; + error.responseJSON.error_description); 
        }
      ); 

    } 
  }
});
&lt;/pre&gt;

&lt;p&gt;In the code above you can see how easy it is to access Usergrid data via Ember-Data now that we&amp;#39;ve got our custom REST adapter and serializer in place. We create a new Activity with a call to &lt;code&gt;this.store.createRecord()&lt;/code&gt; and to save it all we need to do is &lt;code&gt; activity.save()&lt;/code&gt;.&lt;/p&gt;


&lt;h4&gt;Time to wrap up...&lt;/h4&gt;

&lt;p&gt;To sum things up, here are some closing thoughts and observations.&lt;/p&gt; 

&lt;ul&gt;
   &lt;li&gt;If you are considering JavaScript MVC frameworks, then Ember.js is definitely worthy of  your consideration. The documentation makes it easy to learn and the community is friendly and helpful.&lt;/li&gt;
   &lt;li&gt;It would be great for Usergrid to provide an Ember.js SDK that makes it really easy to build apps with Ember.js and Usergrid.&lt;/li&gt;
   &lt;li&gt;Ember-Data is an integral part of Ember.js, something that you need to do pretty much anything, but it is treated as a separate package with separate documentation. That is somewhat confusing for a new user.&lt;/li&gt;
   &lt;li&gt;Ember-Data does not include built-in form validation so if your app includes a large number of non-trivial  forms, then you may prefer AngularJS over Ember.js. 
   &lt;li&gt;There is a &lt;a href=&quot;https://github.com/dockyard/ember-validations&quot;&gt;form validation plugin&lt;/a&gt; for Ember.js, but it requires the experimental &lt;a href=&quot;http://www.ember-cli.com&quot;&gt;Ember-CLI&lt;/a&gt; utility. I tried to use it, but Ember-CLI was unpleasnt enough that I gave up.&lt;/li&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;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: &lt;a href=&quot;https://github.com/snoopdave/usergrid-ember&quot;&gt;Usergrid-Ember&lt;/a&gt;. Next up, I&amp;#39;ll write about my experiences using Apache Shiro to replace Spring Security in Apache Roller.&lt;/p&gt;&lt;/p&gt;</content>
    </entry>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/usergrid-ember-part-1</id>
        <title type="html">Usergrid and Ember.js - part 1</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/usergrid-ember-part-1"/>
        <published>2015-01-20T09:39:47+00:00</published>
        <updated>2018-02-16T12:48:24+00:00</updated> 
        <category term="Web Development" label="Web Development" />
        <category term="asf" scheme="http://roller.apache.org/ns/tags/" />
        <category term="baas" scheme="http://roller.apache.org/ns/tags/" />
        <category term="emberjs" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <content type="html">&lt;p&gt;The next one of my &lt;a href=&quot;http://rollerweblogger.org/roller/entry/2014-side-projects&quot;&gt;2014 Side projects&lt;/a&gt; that I&#146;d like to share is Usergrid-Ember, an experiment and attempt to learn more about &lt;a href=&quot;http://emberjs.com&quot;&gt;Ember.js&lt;/a&gt; and &lt;a href=&quot;http://usergrid.incubator.apache.org&quot;&gt;Apache Usergrid&lt;/a&gt; by implementing the Checkin example from my Usergrid mobile development talk. If you&amp;#39;re interested in either Usergrid or JavaScript web development then I hope you&amp;#39;ll read on...&lt;/p&gt;


&lt;h4&gt;Why Ember.js?&lt;/h4&gt;

&lt;a href=&quot;http://emberjs.com&quot;&gt;&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/87879b47-6b14-4c18-a17e-576a68bf62a0&quot; alt=&quot;Ember logo&quot; align=&quot;right&quot;&gt;&lt;/a&gt;

&lt;p&gt;Ember.js is one of the leading frameworks for building browser-based apps. It&amp;#39;s one of &lt;a href=&quot;http://www.infoq.com/research/top-javascript-mvc-frameworks&quot;&gt;many JavaScript Model View Controller (MVC) frameworks&lt;/a&gt;. 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 &#147;model&#148; data from a server and using a template to create an HTML &#147;view&#148; of the data that calls functions provided in a &amp;quot;controller&amp;quot; object.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Based on what I&amp;#39;ve seen on the net and local meet-ups, the leading frameworks these days are Ember.js and AngularJS. After I saw &lt;a href=&quot;http://allthingsopen.org/talks/the-ember-js-framework-everything-you-need-to-know/&quot;&gt;Yehudi Katz&#146;s talk at All Things Open&lt;/a&gt;, I decided to spend some time learning Ember.js.&lt;/p&gt;


&lt;h4&gt;Getting started with Ember.js&lt;/h4&gt;

&lt;p&gt;The first thing you see when you visit the &lt;a href=&quot;http://emberjs.com&quot;&gt;Ember.js&lt;/a&gt; site is a big button that says &amp;quot;DOWNLOAD THE STARTER KIT&amp;quot; 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&amp;#39;s a good way to start: small and simple.&lt;/p&gt;  

&lt;p&gt;&lt;b&gt;Ember.js Starter Kit files:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/208a9957-5c35-4376-824a-1839f1dd6e02&quot; alt=&quot;screenshot of Starter Kit directory layout&quot;&gt;
&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Sidebar: I do hope they keep the Starter Kit around when the new &lt;a href=&quot;http://www.ember-cli.com&quot;&gt;Ember-CLI&lt;/a&gt; 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: &lt;a href=&quot;https://ca.non.co.il/index.php/ember-cli-is-making-you-stupid/&quot;&gt;Ember-CLI is Making You Stupid&lt;/a&gt; by Yoni Yechezkel.&lt;/i&gt;&lt;/p&gt;


&lt;h4&gt;Other stuff: Bower, Grunt and Bootstrap&lt;/h4&gt;

&lt;p&gt;I like to bite off more than I can chew, so I decided to use a couple of other tools. I used &lt;a href=&quot;http://bower.io&quot;&gt;Bower&lt;/a&gt; to manage dependencies and &lt;a href=&quot;http://gruntjs.com&quot;&gt;Grunt&lt;/a&gt; to concatenate and minify those dependencies, and other things like launching a simple web server for development purposes. I also decided to use &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; to provide various UI components needed, like a navbar and nicely styled list views.&lt;p&gt;

&lt;p&gt;I won&amp;#39;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: &lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/master/bower.json&quot;&gt;bower.json&lt;/a&gt; and &lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/master/Gruntfile.js&quot;&gt;Gruntfile.js&lt;/a&gt;. 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 &lt;a href=&quot;https://github.com/twbs/bootstrap/issues/9940&quot;&gt;fix&lt;/a&gt; for that now).&lt;/p&gt;


&lt;h4&gt;Defining Index Route, Model and Template&lt;/h4&gt;

&lt;p&gt;Every Ember.js app needs to define some routes. There is a default route for the &amp;quot;/&amp;quot; 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:&lt;/p&gt;

&lt;b&gt;Part of app.js (&lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L18&quot;&gt;link&lt;/a&gt;)&lt;/b&gt;
&lt;pre class=&quot;brush: js;&quot;&gt;
// create the ember app object
App = Ember.Application.create();

// define routes
App.Router.map(function() {
    this.route(&amp;quot;login&amp;quot;, { path: &amp;quot;/login&amp;quot; });  
    this.route(&amp;quot;logout&amp;quot;, { path: &amp;quot;/logout&amp;quot; });
    this.route(&amp;quot;register&amp;quot;, { path: &amp;quot;/register&amp;quot; });
});
&lt;/pre&gt;

&lt;p&gt;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 &lt;code&gt;App.LoginRoute&lt;/code&gt;, the controller to be named &lt;code&gt;App.LoginController&lt;/code&gt; and the template to be named &amp;quot;login.&amp;quot;&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s talk about the index route. When a user arrives at your app they&#146;ll be directed to the index route. Ember.js will then look for a JavaScript object called &lt;code&gt;App.IndexRoute&lt;/code&gt; to provide the model data and JavaScript functions needed for the index page. Here&#146;s a partial view of the index route:&lt;/p&gt;

&lt;b&gt;Part of app.js (&lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L175&quot;&gt;link&lt;/a&gt;)&lt;/b&gt;
&lt;pre class=&quot;brush: js;&quot;&gt;
App.IndexRoute = Ember.Route.extend( {

    // provide model data needed for index template
    model: function() {
        if ( this.loggedIn() ) {
            return this.store.find(&amp;quot;activity&amp;quot;);
        }
        return [];
    }

});
&lt;/pre&gt;

&lt;p&gt;The index page of the Checkin app shows the Checkin activities of the people that you follow. Above you can see how to route&amp;#39;s &lt;code&gt;model()&lt;/code&gt; function makes that data available to the template for display.  If the user is logged in we call the &lt;code&gt;store.find(&#147;activity&#148;)&lt;/code&gt; 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&amp;#39;ll cover that in part two of this article.&lt;/p&gt;

&lt;p&gt;To display the index route, Ember looks for an HTML template called &#147;index&#148; and will use that template to display the index page. Below is the index template. The template is a &lt;a href=&quot;http://handlebarsjs.com&quot;&gt;Handlebars&lt;/a&gt; template and the things that appear in double curly-braces are Handlebars expressions.&lt;/p&gt;

&lt;b&gt;Part of index.html (&lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/v2/index.html#L46&quot;&gt;link&lt;/a&gt;)&lt;/b&gt;
&lt;pre class=&quot;brush: js;&quot;&gt;


  
    &lt;div class=&quot;container-fluid&quot;&gt;

      &lt;div class=&quot;navbar-header&quot;&gt;
        Checkin
      &lt;/div&gt;

      
          {{action &amp;#39;showModal&amp;#39; &amp;#39;add-checkin-modal&amp;#39; model }}&amp;gt;Add Checkin
      

      &lt;ul class=&quot;nav navbar-nav navbar-right&quot;&gt;
        &lt;li&gt;Logout &lt;/li&gt;
      &lt;/ul&gt;

    &lt;/div&gt;
  

  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col-md-12&quot;&gt;

      &lt;ul class=&quot;list-group&quot;&gt;
        {{#each item in model}}
          &lt;li class=&quot;list-group-item&quot;&gt;
              {{item.content}} | {{item.location}}
          &lt;/li&gt;
        {{/each}}
      &lt;/ul&gt;

    &lt;/div&gt;
  &lt;/div&gt;


&lt;/pre&gt;

&lt;p&gt;In the above template you can see a couple of &lt;code&gt;{{action}}&lt;/code&gt; expressions that call out to JavaScript methods defined in the Checkin app. The part of the code that uses the model is in the &lt;code&gt;{{#each}}&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s what the above template looks like when displayed in a browser:&lt;/p&gt;

&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/d052ee9f-4c60-44ea-b41a-b462b2bef876&quot; alt=&quot;screenshot of checkin app index page&quot;&gt;
&lt;br&gt;
&lt;br&gt;

&lt;h4&gt;Implementing Login&lt;/h4&gt;

&lt;p&gt;In Checkin, login is implemented using HTML Local Storage. Once a user has successfully logged in, the app stores the username and the user&amp;#39;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.&lt;/p&gt;

&lt;b&gt;Part of index.html (&lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/v2/index.html#L46&quot;&gt;link&lt;/a&gt;)&lt;/b&gt;
&lt;pre class=&quot;brush: js;&quot;&gt;


  
    &lt;div class=&quot;container-fluid&quot;&gt;
      &lt;div class=&quot;navbar-header&quot;&gt;
        Checkin
      &lt;/div&gt;
    &lt;/div&gt;
  

  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col-md-3&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-md-6&quot;&gt;

        

         &lt;h2 class=&quot;form-login-heading&quot;&gt;Please Login&lt;/h2&gt;

         Email address
         {{input class=&amp;quot;form-control&amp;quot; type=&amp;quot;text&amp;quot; 
              valueBinding=&amp;quot;username&amp;quot; placeholder=&amp;quot;Username&amp;quot;}}

         Password
         {{input class=&amp;quot;form-control&amp;quot; type=&amp;quot;password&amp;quot; 
             valueBinding=&amp;quot;password&amp;quot; placeholder=&amp;quot;Password&amp;quot;}}
           
         
            Login
         

         Register as new user.
        

    &lt;/div&gt;
    &lt;div class=&quot;col-md-3&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;


&lt;/pre&gt;

&lt;p&gt;The LoginController provides the functions needed by the Login page itself and there are two. There is a &lt;code&gt;login()&lt;/code&gt; function (called on line 27 above) that performs the login, and there is a &lt;code&gt;register()&lt;/code&gt; function (called on line 31 above) that directs the user to the New User Registration page. Here&amp;#39;s a snippet of code from the &lt;code&gt;App.LoginController&lt;/code&gt; that provides these two functions:&lt;/p&gt;

&lt;b&gt;Part of app.js (&lt;a href=&quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L250&quot;&gt;link&lt;/a&gt;)&lt;/b&gt;
&lt;pre class=&quot;brush: js;&quot;&gt;
App.LoginController = Ember.Controller.extend({

  actions: {

    login: function() { 

      // login by POST to Usergrid app&amp;#39;s /token end-point

      var loginData = {
        grant_type: &amp;quot;password&amp;quot;,
        username: this.get(&amp;quot;username&amp;quot;),
        password: this.get(&amp;quot;password&amp;quot;)
      };

      $.ajax({
        type: &amp;quot;POST&amp;quot;,
        url: Usergrid.getAppUrl() + &amp;quot;/token&amp;quot;,
        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(&amp;quot;username&amp;quot;, loginData.username );
          localStorage.setItem(&amp;quot;access_token&amp;quot;, data.access_token );

          // clear the form
          this.set(&amp;quot;username&amp;quot;, &amp;quot;&amp;quot;); 
          this.set(&amp;quot;password&amp;quot;, &amp;quot;&amp;quot;);

         // call route to handle post-login transition
          this.get(&amp;quot;target&amp;quot;).send(&amp;quot;onLogin&amp;quot;); 
        }
      });
    },

    register: function() {
      this.transitionToRoute(&amp;quot;register&amp;quot;);
    }

  }
});
&lt;/pre&gt;

&lt;p&gt;The above code shows how to login to a Usergrid app using jQuery&amp;#39;s Ajax feature. The &lt;code&gt;login()&lt;/code&gt; function takes the username and password values from the login form, puts those in a JSON object with grant_type &amp;quot;password&amp;quot; and posts that object to the &lt;code&gt;/token&lt;/code&gt; end-point of the Usergrid app. If that post succeeds, the response will include an access_token. We store that in Local Storage; we&amp;#39;ll need to use it in all subsequent calls to Usergrid.&lt;/p&gt;

&lt;p&gt;Usergrid fans will notice that I&amp;#39;m not using the &lt;a href=&quot;https://github.com/snoopdave/incubator-usergrid/tree/master/sdks/html5-javascript&quot;&gt;Usergrid JavaScript SDK&lt;/a&gt;. That&amp;#39;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&amp;#39;ll write about that in part two of this article.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</content>
    </entry>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/2014-side-projects</id>
        <title type="html">2014 side projects</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/2014-side-projects"/>
        <published>2015-01-05T08:37:04+00:00</published>
        <updated>2018-02-16T12:57:41+00:00</updated> 
        <category term="Open Source" label="Open Source" />
        <category term="asf" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <category term="usergrid" scheme="http://roller.apache.org/ns/tags/" />
        <content type="html">
&lt;p&gt;For various reasons, I&amp;#39;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. &lt;/p&gt;


&lt;p&gt;I like to share my code, so I&amp;#39;ve put my code on GitHub and I&amp;#39;m going to write a brief post about each here on my blog. I&amp;#39;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.&lt;/p&gt;


&lt;p&gt;&lt;h3&gt;The Usergrid-Mobile project&lt;/h3&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/128ca398-027d-491d-9e0b-b24c77c8e9b9&quot; alt=&quot;ApacheCon EU logo&quot; align=&quot;right&quot; height=&quot;100&quot;&gt;&lt;br&gt;
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 &amp;quot;mobile development with Usergrid&amp;quot; talk, and to do that I needed a great example project. The resulting project shows how to create a dumbed-down Foursquare-style &amp;quot;checkin&amp;quot; app using HTML5, JavaScript, &lt;a href=&quot;http://jquerymobile.com&quot;&gt;jQuery Mobile&lt;/a&gt; and &lt;a href=&quot;http://cordova.apache.org&quot;&gt;Apache Cordova&lt;/a&gt;. &lt;/p&gt;


&lt;p&gt;Luckily for me, my talk was &lt;a href=&quot;http://apacheconeu2014.sched.org/event/edbc9c695e39c2960441690a8a23b5d3#.VKceecaZ7tE&quot;&gt;accepted&lt;/a&gt; for ApacheCon EU and in November I traveled to Budapest (took some &lt;a href=&quot;https://www.flickr.com/photos/snoopdave/15859954201/in/set-72157649019765409&quot;&gt;photos&lt;/a&gt;) and gave the talk there. &lt;/p&gt;


&lt;p&gt;I also presented the talk at the All Things Open conference in Raleigh, NC and you can view a video of that talk, &lt;a href=&quot;https://www.youtube.com/watch?v=DjFG-QbxxLw&quot;&gt;Mobile Development with Usergrid&lt;/a&gt; on YouTube.&lt;/p&gt;


&lt;p&gt;&lt;p&gt;&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;&lt;/p&gt;


&lt;p&gt;You can find the code for &lt;a href=&quot;https://github.com/snoopdave/usergrid-mobile&quot;&gt;usergrid-mobile&lt;/a&gt; on  GitHub. I also created a Vagrant File to launch a local instance of Usergrid for demo purposes. It&amp;#39;s called usergrid-vagrant.&lt;/p&gt;


&lt;p&gt;That&amp;#39;s all for now. Next up: Usergrid-Ember.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

</content>
    </entry>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/holiday_project_jmaki_for_roller</id>
        <title type="html">Holiday project: JMaki for Roller</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/holiday_project_jmaki_for_roller"/>
        <published>2008-01-02T13:12:54+00:00</published>
        <updated>2008-01-21T16:05:01+00:00</updated> 
        <category term="Java" label="Java" />
        <category term="java" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <category term="jmaki" scheme="http://roller.apache.org/ns/tags/" />
        <category term="roller" scheme="http://roller.apache.org/ns/tags/" />
        <content type="html">&lt;p&gt;
&lt;img src=&quot;http://rollerweblogger.org/roller/resource/jmaki-logo.png&quot; alt=&quot;JMaki seal&quot; align=&quot;right&quot;&gt;
Over the holidays I avoided doing anything directly related to my current set of work tasks. Sun went quiet, which helped, and I ignored the messages that piled-up in the Roller user and dev lists.  It was so quiet that I had time for a fun little project: a JMaki plugin for Roller.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://ajax.dev.java.net&quot;&gt;JMaki&lt;/a&gt; makes it easy to use JavaScript widgets (Dojo, Google, YUI, etc.) from PHP, JSP, JSF and now Roller. To use a widget, all you have to do is call a method or include a tag and JMaki takes care of including the right JavaScript files and generating the right HTML for you. That&amp;#39;s not all JMaki does, there&amp;#39;s also a pub/sub facility to make it easy to wire widgets together via events, there&amp;#39;s a proxy for fetching remote resources common table and tree data models. The theme is cool widgets with ease-of-development and that&amp;#39;s what I&amp;#39;d like to see in Roller. You can read more about the JMaki value proposition on the &lt;a href=&quot;https://ajax.dev.java.net/whyusejmaki.html&quot;&gt;Why Use JMaki page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s an example. Below is a Roller page template that uses two JavaScript widgest, the Dojo Clock and the YUI Data Table. All it takes is a single line of template code to include each widget, and one widget is dynamic i.e. the table is populated via an RSS feed.&lt;/p&gt;

&lt;pre&gt;

    &amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;JMaki test page&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;

        &amp;lt;h1&amp;gt;JMaki test: dojo.clock&amp;lt;/h1&amp;gt;
        $jmaki.addWidget(&amp;quot;dojo.clock&amp;quot;)

        &amp;lt;h1&amp;gt;JMaki test: yahoo.dataTable&amp;lt;/h1&amp;gt;
        $jmaki.addWidget(&amp;quot;yahoo.dataTable&amp;quot;, &amp;quot;/roller/xhp?id=rss&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)

    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;

&lt;/pre&gt;

&lt;p&gt;And here&amp;#39;s what that page looks like when displayed by Roller:&lt;/p&gt;

&lt;a href=&quot;http://www.flickr.com/photos/snoopdave/2143146264/&quot; title=&quot;JMaki Plugin for Roller w/Dojo and YUI by snoopdave, on Flickr&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2221/2143146264_2d39b97ff9.jpg&quot; width=&quot;500&quot; height=&quot;377&quot; alt=&quot;JMaki Plugin for Roller w/Dojo and YUI&quot;&gt;&lt;/a&gt;
&lt;br&gt;

&lt;p&gt;I&amp;#39;ll write more about the plugin once I install it on this site. If you want some details about how the plugin was developed, you can read the email that I sent to the JMaki dev list: &lt;a href=&quot;https://ajax.dev.java.net/servlets/ReadMsg?list=dev&amp;msgNo=2035&quot;&gt;JMaki for Roller issues and suggestions&lt;/a&gt;. It links to the Java source code for the plugin.&lt;/p&gt;

</content>
    </entry>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/groovy_roller_redux</id>
        <title type="html">Pluggable renderers and scripting languages in Roller</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/groovy_roller_redux"/>
        <published>2007-03-11T23:45:03+00:00</published>
        <updated>2007-03-12T18:51:20+00:00</updated> 
        <category term="Roller" label="Roller" />
        <category term="groovy" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <category term="jruby" scheme="http://roller.apache.org/ns/tags/" />
        <category term="roller" scheme="http://roller.apache.org/ns/tags/" />
        <category term="scripting" scheme="http://roller.apache.org/ns/tags/" />
        <summary type="html">My next ApacheCon talk is about &lt;a href=&quot;http://www.eu.apachecon.com/program/talk/87&quot;&gt;Roller and blogs as a web development platform&lt;/a&gt;.
One of the things I plan to discuss is using scripting languages within
Roller, something that&amp;#39;s possible now because Roller versions 3.0 and
later supports pluggable renderers. It&amp;#39;s undocumented and a little hacky right now, but by plugging in your own custom
renderers you can add support for new template and scripting languages
as alternatives to Roller&amp;#39;s built-in &lt;a href=&quot;http://velocity.apache.org/&quot;&gt;Velocity&lt;/a&gt;. Want to know more?&amp;nbsp;</summary>
        <content type="html">&lt;p&gt;My next ApacheCon talk is about &lt;a href=&quot;http://www.eu.apachecon.com/program/talk/87&quot;&gt;Roller and blogs as a web development platform&lt;/a&gt;. One of the things I plan to discuss is using scripting languages within Roller, something that&amp;#39;s possible now because Roller versions 3.0 and later allows pluggable renderers. It&amp;#39;s undocumented and a little hacky right now, but by plugging in your own custom renderers you can add support for new template and scripting languages as alternatives to Roller&amp;#39;s built-in &lt;a href=&quot;http://velocity.apache.org/&quot;&gt;Velocity&lt;/a&gt;. Here are some notes on the whys and hows.&lt;br&gt; &lt;/p&gt;&lt;p&gt;&lt;b&gt;Why would you want to plugin a new scripting or template language?&lt;br&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I can think of two reasons you might want to plug-in a new renderer to Roller. If you&amp;#39;re not happy with Velocity and want to plugin an alternative template language like Freemarker you can do it with a custom renderer. Or, if you&amp;#39;re developing sophisticated Roller templates and you need a more sophisticated programming language like Groovy, JRuby or Javascript then custom renderers are your best bet.&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;What can you do in an alternative scripting or template language?&lt;/b&gt;&lt;/p&gt;&lt;p&gt;In an alternative template or scripting language you can access the normal Roller model objects (see the &lt;a href=&quot;http://people.apache.org/~snoopdave/roller30-template-guide.pdf&quot;&gt;Roller Template Guide&lt;/a&gt; for a reference) and you can generate just about any type of content you want. However, you cannot access the Roller macros because they&amp;#39;re written in and require Velocity.&lt;br&gt; &lt;/p&gt;&lt;p&gt;It&amp;#39;s also worth noting that you can get in quite a bit of trouble with an alternative language. Roller&amp;#39;s built-in Velocity renderer allows users to access only a very limited set of objects, but other scripting and template languages might not be so safe. That&amp;#39;s why you might not want to make all plugin renderers available to all of your users.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;How do you implement scripting in a plugin renderer?&lt;br&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I plan on documenting the process at some point, but basically you implement two simple interfaces: &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/ui/rendering/RendererFactory.java?revision=443329&amp;amp;view=markup&quot;&gt;RendererFactory&lt;/a&gt; and &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/ui/rendering/Renderer.java?revision=443329&amp;amp;view=markup&quot;&gt;Renderer&lt;/a&gt;. So far, I&amp;#39;ve developed three plugin renderers: BSFRenderer, GroovletRenderer and GSPRenderer. Let&amp;#39;s discuss each so you can see how they work.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;A BSFRenderer example&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;http://jakarta.apache.org/bsf/&quot;&gt;Bean Scripting Framework&lt;/a&gt; (BSF)&amp;nbsp;  makes it easy to call a wide variety of scripting languages from Java and because it works with Java SE 5, it&amp;#39;s a better choice for Roller than the Java SE 6 scripting extensions. I developed a BSF renderer (&lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/bsf/src/org/apache/roller/scripting/BSFRendererFactory.java?revision=517070&amp;amp;view=markup&quot;&gt;BSFRendererFactory&lt;/a&gt; and &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/bsf/src/org/apache/roller/scripting/BSFRenderer.java?revision=517070&amp;amp;view=markup&quot;&gt;BSFRenderer&lt;/a&gt;) and with it, it&amp;#39;s theoretically possible to
support the use of just about any BSF scripting language in a Roller
template. I&amp;#39;ve tried Groovy and JavaScript and they both work fine, but JRuby has some conflicts with the version of Hibernate that we&amp;#39;re using in Roller so I&amp;#39;ll have to revisit JRuby later. &lt;/p&gt;&lt;p&gt;Unfortunately, with the BSFRenderer you&amp;#39;re stuck writing Servlet-like code like this Groovy example:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out.println(&amp;quot;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;quot;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out.println(&amp;quot;Hello World, my blog is ${model.weblog.name}&amp;quot;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out.println(&amp;quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;); &lt;/p&gt;&lt;p&gt;Ugh. Nothing to write home about, that&amp;#39;s for sure. Fortunately, there&amp;#39;s something better.&lt;/p&gt;&lt;p&gt;&lt;b&gt;A GroovletRenderer example&lt;/b&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;I also developed a GroovletRenderer and a Groovy Server Pages (GSP) GSPRenderer, which look more promising. These renderers call Groovy directly and behave like the &lt;a href=&quot;http://groovy.codehaus.org/Groovlets&quot;&gt;Groovlet&lt;/a&gt; and &lt;a href=&quot;http://groovy.codehaus.org/Groovy+Templates&quot;&gt;Groovy Template&lt;/a&gt; Servlets that come with Groovy.&lt;/p&gt;&lt;p&gt;With my new GroovletRenderer (&lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/groovy/src/org/apache/roller/scripting/GroovletRendererFactory.java?view=markup&quot;&gt;GroovletRendererFactory&lt;/a&gt; and &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/groovy/src/org/apache/roller/scripting/GroovletRenderer.java?view=markup&quot;&gt;GroovletRenderer&lt;/a&gt;), you can use the GroovyMarkup builder to build HTML. Here&amp;#39;s an example that displays a blog title, description and most recent entries:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; html.html { // html is implicitly bound to new MarkupBuilder(out)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; head {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; title(model.weblog.name)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; body {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; h1(model.weblog.name)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i(model.weblog.description)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map = model.getWeblogEntriesPager().getEntries();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.keySet().each() {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.get(it).each() {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; h2(it.title)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p(it.text)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; br()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;/p&gt;&lt;p&gt;Starting to look more interesting, no? &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;A GSPRenderer example&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I also developed a GSPRenderer &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/groovy/src/org/apache/roller/scripting/GSPRendererFactory.java?view=markup&quot;&gt;(GSPRendererFactory&lt;/a&gt; and &lt;a href=&quot;http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/scripting/groovy/src/org/apache/roller/scripting/GSPRendererFactory.java?view=markup&quot;&gt;GSPRenderer&lt;/a&gt;), which allows you to use a JSP like syntax with &amp;lt;% %&amp;gt; and &amp;lt;%= %&amp;gt;. Here&amp;#39;s the above example, but rewritten as a Roller GSP page:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;html&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;${model.weblog.name}&amp;lt;/title&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;lt;h1&amp;gt;${model.weblog.name}&amp;lt;/h1&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;i&amp;gt;${model.weblog.description}&amp;lt;/i&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% map = model.getWeblogEntriesPager().getEntries();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.keySet().each() { %&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% map.get(it).each() { %&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;h2&amp;gt;${it.title}&amp;lt;/h2&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;p&amp;gt;${it.text}&amp;lt;/p&amp;gt;&amp;lt;br /&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }%&amp;gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/html&amp;gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;That&amp;#39;s all I have time for tonight. Next I hope tackle JRuby and hopefully I&amp;#39;ll find some way to support some form of JRuby templating too. Where is all this going? I don&amp;#39;t know. I&amp;#39;m not sure these plugins will make it into the Roller 4.0 release, but I do hope to make it easier to drop them and renderer plugins like them into Roller 4.0. &lt;/p&gt;</content>
    </entry>
    <entry>
        <id>https://rollerweblogger.org/roller/entry/roller_json_and_dojo_via</id>
        <title type="html">Roller, JSON and Dojo via JMaki</title>
        <author><name>Dave Johnson</name></author>
        <link rel="alternate" type="text/html" href="https://rollerweblogger.org/roller/entry/roller_json_and_dojo_via"/>
        <published>2007-01-15T23:21:10+00:00</published>
        <updated>2007-01-16T07:40:40+00:00</updated> 
        <category term="Roller" label="Roller" />
        <category term="ajax" scheme="http://roller.apache.org/ns/tags/" />
        <category term="blogging" scheme="http://roller.apache.org/ns/tags/" />
        <category term="dojo" scheme="http://roller.apache.org/ns/tags/" />
        <category term="javascript" scheme="http://roller.apache.org/ns/tags/" />
        <category term="roller" scheme="http://roller.apache.org/ns/tags/" />
        <content type="html">&lt;p&gt;&lt;a href=&quot;http://blogs.sun.com/alexismp/entry/taking_roller_s_json_and&quot;&gt;Alexis Moussine-Pouchkine&lt;/a&gt; has taken my &lt;a href=&quot;http://rollerweblogger.org/roller/entry/generating_json_for_your_roller&quot;&gt;Generating JSON for your Roller blog&lt;/a&gt; post a few steps further down the road. He created a screen-cast to show how easy it is to use &lt;a href=&quot;http://www.netbeans.org/&quot;&gt;Netbeans 5.5&lt;/a&gt; and the &lt;a href=&quot;http://ajax.dev.java.net/&quot;&gt;JMaki&lt;/a&gt; widget wrappers to serve up Roller data in a a Dojo table. Cool stuff. I really need to find the time to take JMaki for a spin.&lt;br&gt;&lt;/p&gt;&lt;p&gt;And BTW, I&amp;#39;m still working on my Dojo table example, which will be similar to what Alexis has done but it will use Dojo directly within a Roller blog -- no IDEs or JSPs required.&lt;br&gt;&lt;/p&gt;</content>
    </entry>
</feed>

