Category Archives: Uncategorized

Sending Data to a Server-Side Service with Shindig

We will break the talking to the server bit into two pieces. First we will send / set some data on the server and then in the next post we will retrieve data form the server.

The thing that we need to understand is that server requests are asynchronous. As much as we RPC loving server dudes want to make synchronous calls – resist it. Accept and embrace asynchronous calls – in Ajax it is the only way. And as we will see in the next post, batched Ajax is the only way. Since widgets are tiny and they will be on lots of screens, for performance reasons and decent user experience, batched asynchronous requests are essential.

I will use code snippets throughout the next few blog posts so you might want the entire files right away. Understand that these are the complete files and will have the complete solution in them that will be explained in the next few posts.

In this exercise, we add a new server-side service to Shindig to be accessed using the osapi feature. I may have jacked-in at the wrong place – but this will get you started.

java/social-api/src/main/java/org/apache/shindig/social/opensocial/service/LearningHandler.java

package org.apache.shindig.social.opensocial.service;

import org.apache.shindig.protocol.Service;
import org.apache.shindig.protocol.Operation;

@Service(name = "learning")
public class LearningHandler {

  @Operation(httpMethods = "GET")
  public void setOutcome(SocialRequestItem request) {
    System.out.println("Param = "+request.getParameter("outcome","default"));
    // Do something clever here like call and SPI...
  }
}

Now of course, we would do something more clever than just printing out out parameter – but that detail is up to the container. But this short bit of code is enough to see the round-trip to the server.

Then modify this file:

java/social-api/src/main/java/org/apache/shindig/social/core/config/SocialApiGuiceModule.java


import org.apache.shindig.social.opensocial.service.PersonHandler;
import org.apache.shindig.social.opensocial.service.LearningHandler;

   protected Set<Class<?>> getHandlers() {
     return ImmutableSet.<Class<?>>of(ActivityHandler.class, AppDataHandler.class,
       PersonHandler.class, MessageHandler.class, LearningHandler.class);
   }

This makes sure our service and methods are included in osapi as osapi.learning.setOutcome. And yes, it would be nice if there were a way of doing this without jacking in at a code level. Perhaps there is such a way that I missed or perhaps it is simply ‘yet to be invented’.

Good Comment from Michael Young Instead of modifying SocialApiGuiceModule you can extend it (ie LearningGuiceModule) and replace this module in web.xml.

Just because we are in a hurry, we will compile this and see if our server call works before we alter our learning feature. So compile and start Jetty:

mvn
mvn -Prun

And navigate to http://localhost:8080/samplecontainer/samplecontainer.html

You should see the “Social Hello World” gadget. Now lets edit this file:

vi ./target/work/webapp/samplecontainer/examples/SocialHelloWorld.xml

And add these lines:

   gadgets.window.setTitle('Social Hello World');
   osapi.learning.setOutcome({'outcome' : '123456'}).execute(function (result) {
        if (result.error) {
            alert('Error, unable to send outcome to server.');
        }
    } ) ;
     var hellos = new Array('Hello World', 'Hallo Welt', 'Ciao a tutti',
...

Actually you will note that to do this we do not need the learning feature because we have fully provisioned the server-side learning service into the osapi helper. When the gadget starts up, osapi pulls down all its services from the server and registers them. This is independent of gadget registration which the Require accomplishes.

When you press refresh (or whatever you need to to force a full reload) on the container and watch the log on the server, you will see a cute litle line scroll by in your server log:

Param = 123456

Very simple – but very cool.

Now lets alter our learning feature to call the service on our behalf in the setOutcome method. We will give the user the option to provide a handler or let the learning feature do the handling.

We edit the setOutcome method in learning_client.js from the last post as follows:

        setOutcome : function(data, handler) {
            if ( handler === 'silent' ) handler = (function (result) { } );
            if ( handler === undefined ) handler = (function (result) {
                if (result.error) {
                    alert('Error, unable to send outcome to server.');
                }
            } ) ;
            osapi.learning.setOutcome({'outcome' : data}).execute(handler);
        },

It is pretty simple stuff, the user can give us the handler, or we provide a simple alert on error, or we can provide a completely silent handler at the user’s request.

We also need indicate that we want access to the osapi service:

taming.js

var tamings___ = tamings___ || [];
tamings___.push(function(imports) {
  ___.grantRead(gadgets.learning, 'getContextLabel');
  ___.grantRead(gadgets.learning, 'getContextName');
  ___.grantRead(gadgets.learning, 'setOutcome');
  caja___.whitelistFuncs([
    [osapi.learning, 'setOutcome']
  ]);
});

This makes sure that we have access to our service call when running through Caja. (I think I am saying this properly).

Once we have done this and recompiled Shindig, started Jetty and started the container, we make the following changes to the “Social Hello World” gadget. Now lets edit this file:

vi ./target/work/webapp/samplecontainer/examples/SocialHelloWorld.xml

And add two lines:

   <Require feature="osapi"></Require>
   <Require feature="learning"></Require>
   <Require feature="settitle"/></Require>
…

   gadgets.window.setTitle('Social Hello World');
   gadgets.learning.setOutcome('0.97');
     var hellos = new Array('Hello World', 'Hallo Welt', 'Ciao a tutti',
...

We are just using our learning gadget method to send the outcome to the server. By omitting the second parameter, the learning feature will give us a little alert if it has trouble sending data to the server.

Again, we press refresh and in the log we see:

Param = 0.97

So that completes our look at a simple call to the server to send some data. In the next post, we will get a little deeper into how to retrieve data from the server. The bit that gets complex is the requirement that things be done asynchronously and if at all possible with multiple batched requests in a single request.

So the code will initially look a little obtuse – at its core it is simple – but the asynchronous pattern takes a little getting used to. And since I only figured it out in the last 24 hours, I might have missed a bit in the pattern as well. Of course comments and improvements are welcome.

Next post in the series

Adding a New Feature to Shiding for Learning

In this exercise, we add a new feature to Shindig. I may have jacked-in at the wrong place – but this will get you started.

First we move into the feature directory:

cd features/src/main/javascript/features

Create a new directory named learning and put three files into it.

learning_client.js

gadgets['learning'] = (function() {

    return {
       getContextLabel : function() {
            return 'SI124';
        },
    
        getContextName : function() {
            return 'Social Computing';
        },
    
        setOutcome : function(data) {
            alert('setOutcome belongs here');
        }
    };

})();

This creates our client code and defines three methods in the client. For now they are simple stubs to keep life simple.

taming.js

var tamings___ = tamings___ || [];
tamings___.push(function(imports) {
  ___.grantRead(gadgets.learning, 'getContextLabel');
  ___.grantRead(gadgets.learning, 'getContextName');
  ___.grantRead(gadgets.learning, 'setOutcome');
});

I am a little foggy on this file – it basically works with Caja to make sure that you are explicit as to what you want to really expose to JavaScript callers.

feature.xml

<feature>
  <name>learning</name>
  <dependency>globals</dependency>
  <gadget>
    <script src="learning_client.js"/>
    <script src="taming.js"/>
  </gadget>
  <container>
    <script src="learning_client.js"/>
    <script src="taming.js"/>
  </container>
</feature>

This file names your feature and defines the source files that make it up.

Then edit the file features.txt and add a line:

features/xmlutil/feature.xml
features/com.google.gadgets.analytics/feature.xml
features/learning/feature.xml

There is a way to do this using a script, but for now, lets just jack-in directly.

At this point you need to rebuild Shindig. And you might get syntax errors during the build which you need to fix. Somehow the Javascript for features is compiled / processed at mvn time and put into a more run-time format.

mvn

once it compiles and installs, start Jetty again

mvn -Prun

And navigate to http://localhost:8080/samplecontainer/samplecontainer.html

You should see the “Social Hello World” gadget. Now lets edit this file:

vi ./target/work/webapp/samplecontainer/examples/SocialHelloWorld.xml

And add two lines:

   <Require feature="osapi"></Require>
   <Require feature="learning"></Require>
   <Require feature="settitle"/></Require>
…

   gadgets.window.setTitle('Social Hello World');
   alert(gadgets.learning.getContextLabel());
     var hellos = new Array('Hello World', 'Hallo Welt', 'Ciao a tutti',
...

This requests that the container load the new learning feature and then we call the learning feature when the JavaScript starts up in the gadget and you should see the dialog box pop up once you save the SampleHelloworld.xml and do a refresh.


Up next – talking to code inside the server…



Next post in the series

Getting Oriented with Shindig (i.e. Shindig Hacking for Dummies)

First check out a copy of Shindig from Apache.

svn checkout http://svn.apache.org/repos/asf/shindig/trunk/ shindig

Then compile it. The first compile will take a long time and will download a lot of artifacts. You will want to be on a quick network connection

mvn

If your compile fails a unit test, try mvn -Dmaven.test.skip=true

You can also take a look at the BUILD-JAVA file in the main directory if you are having problems getting it to compile.

Then start the Jetty server:

mvn -Prun

You best friend will be the Shindig Getting Started page – it has lots of hints on what to do to explore your container.

We will just hack a single bit of a gadget running in the sample container so click here:

http://localhost:8080/samplecontainer/samplecontainer.html

You should see the “Social Hello World” gadget. Now lets edit this file:

vi ./target/work/webapp/samplecontainer/examples/SocialHelloWorld.xml

And make the following change:

   gadgets.window.setTitle('Social Hello World');
   alert('Hello Chuck');
     var hellos = new Array('Hello World', 'Hallo Welt', 'Ciao a tutti',

You should see your little alert box when the page refreshes. That is the end of “getting started”.

Note that the SocialHelloWorld.xml file gets overwritten each time you recompile Shindig – so keep your modifications handy elsewhere to reapply after each mvn install – I like editing the gadget in target because then I just keep doing a refresh.

To shut down the Jetty server, simply kill it (i.e. press CTRL-C in the command window on Mac/Linux).

Now here is a little weirdness when you change the gadget code. I am never sure what exactly is needed to really do a full refresh. Here are the things I generally try:

  • Press Refresh in the Browser
  • Press the “Reset All” button
  • Clear the browser history if all else fails and your changes don’t seem to be getting reloaded

It seems as though there is *lots* of caching going on at several levels and you have to take increasingly drastic measures to get past it as you drop your code bits in.

Next post in the series.

Playing with Shindig/OpenSocial Adding a New Feature and a Service

I have been talking recently with folks at the Open University (UK), Open University of Catelonia, Ian Boston from Sakai 3, and a few other organizations about the emergence of an “OpenSocial Learning Gadget”. We had a nice Gadget BOF at the Sakai Conference in Denver where Ian Boston (also a Shindig committer) gave a little tutorial on Shindig Architecture and how to add a Shindig feature and plug Shindig into something like Sakai.

It seemed really clear and obvious and it felt to me that there was a nice way forward to build a Shindig feature (i.e. extension) to define a learning gadget and perhaps line up all of these disparate efforts across vendors and projects and make it so a “learning gadget” could run in any LMS that had Shindig with the learning extension.

So two weeks ago with some help from Ian, I downloaded the source to Shindig and started banging around with Shindig. Ian helped me a lot and the Apache Shindig developer list also gave me some wise advice at key moments where I would get lost and confused.

I had three goals in mind as I went through the Shindig code:

(1) Add a “feature” – an extension loaded into the browser that makes an API available to the Javascript code running in the widget.

(2) Add a run-time server-side service to support the feature – the code of the client-side feature would call this server-server API/service to retrieve things like course name, role of current user, set outcomes, etc. I need do find out how to write a service and register it both in the server Java code and in the client JavaScript code.

(3) Bang around until I understood the security model and the provisioning and launching of gadgets from the container (i.e. the LMS)

I also wanted to explore how the SPI (Server Program Interface) pattern worked in Shindig. Pluto 1.1 used the SPI pattern and it was really well done and made it really straightforward to add JSR-168 support to Sakai 2 back in the 2.4/2.5 days.

Part of my investigation was to take notes as I went along and possibly propose a general capability for Shindig list to add these features without touching any core Shindig code. It may be tricky because even though there is Javascript, there is compile and run-time bits needed.

Along the way, I banged away at Apache Shiro – the generic Authentication and Authorization project. I found Shiro kind of interesting and I particularly liked its feature where Session can exist even if a web browser is not involved in the interaction. In one of my early explorations, I tried to hack Basic LTI Provider code in to Shiro and came up with some ways to improve the plug-ability of Shiro – but then I realized it had little to do with what I was investigating with Shindig – so I dropped my Shiro investigation and went back to Shindig.

I am happy to report that Shindig is pretty cool and well structured internally. It was pretty easy to find all of the necessary places to plug my code in. It is not all too well documented and it is not set up to add features or services without modifying source code.

I promised to write someShindig documentation regarding how this all worked which I will do in a couple of blog posts over the next week after I clean up the code a bit to make it more presentable.

Next post in the series.

Steven Githens: Etherpad And Basic Learning Tools Interoperability

At the Sakai Conference last week, Steve Githens spent a little over a day and built simple prototype Basic LTI support for EitherPad.

http://etherpad.org/

In his blog post:

http://githens.org/blog/?p=83

he describes what he has done and gives a nice screen cast demonstrating Etherpad in Sakai. It is awesome work. I think that Etherpad is the coolest piece of software to be integrated into an LMS using Basic LTI. And in particular, it would be really difficult to integrate Etherpad into an LMS directly as it is pretty specialized software.

I add screenshots of Etherpad running in Moodle and Blackboard below:

OLNet Report: Integrating Cohere into Moodle Using IMS Basic LTI

I am very honored to have been selected as an OLNet Expert fellow:

http://olnet.org/fellowships

My proposal was to bring my interest in interoperability for learning applications and content and help OLNet in its investigation of applicability and use of Open Educational Resources (OER).

We decided that the best way to structure my fellow work was to have several visits to the Open University to do joint work. My first visit to the Open University was July 8-11, 2010. In this visit, I worked with Simon Buckingham Shum, Michelle Bacher, and others to design and build IMS Basic Learning Tools Interoperability Provider for the Cohere idea mapping tool (cohere.open.ac.uk).

The video includes an overview of the visit and demonstration of Cohere integrated into Moodle using Basic LTI.

http://www.vimeo.com/12700689/

If you want to know more about IMS Basic Learning Tools Interoperability, please see:

http://www.imsglobal.org/developers/BLTI/

I want to thank Simon, Michelle, Karen, Tanh, and many others for their kind hospitality while I was visiting.

I very much enjoyed staying at the Beech Cottage Bed and Breakfast in Milton Keynes. It was close to the central station and yet felt like I was spending my evenings in the countryside. I liked the Beech Cottage so well that I wrote a review for Google Maps.

NoteFlight as a IMS Basic LTI Producer – Cool Demonstration

I have been working with Joseph Berkovitz, the CEO of NoteFlight (www.noteflight.com) getting his software to support the IMS Basic LTI Producer specification. NoteFlight is a tool designed to teach music. Instructors can make assignments, perhaps giving them a partial composition and then students can compose and play music, handing in the assignment when done and then the teacher can again go back in and grade the student submissions.

For the impatient or those uninterested in the glorious philosophical and technical detail about how this was done, here is an awesome demo of NoteFlight in action running inside of Moodle using the BasicLTI4Moodle consumer for Moodle 1.9:

Quicktime: http://videos.noteflight.com/MoodleBasicLTI.mov

YouTube (lower quality): http://www.youtube.com/watch?v=kpPZ4osXJO0

Thanks to Joseph for sharing his demonstration with us.

noteflight-blackboard.jpgThis is the perfect example of a whole class of tools that are rather narrow when the entire teaching market is considered – but absolutely essential for teaching certain kinds of courses. Because of the narrow nature of the overall market for a tool such as NoteFlight, and the likely lack of financial clout for the teachers of those classes, it is not likely that a school will pay a large amount of money to integrate something like NoteFlight into their LMS system – so teachers and students would simply have to make new accounts on the NoteFlight site and keep track of separate passwords.

Of course, this is the kind of tool that we see IMS Basic LTI making possible. By reducing the cost of integrating into LMS systems to virtually zero and making it possible to place a tool in pretty much any LMS system with one integration, it allows tools like Noteflight to be made available to those courses that badly need the tool and keeps the costs of building NoteFlight low to allow NoteFlight to invest more in the tool itself rather than chasing after lots of LMS integrations just to get some business.

If you look at the demo, you will see an exciting implementation pattern in the NoteFlight support for IMS Basic LTI. It uses what we call “resource_link level configuration” where all instructor configuration is done on the NoteFlight servers (i.e. inside the frame). The use case is that the Instructor simply placed a generic “NoteFlight” tool as a Moodle Activity and then enters the tool and sets up the assignment. Under the covers, NoteFlight is detecting a new “placement” and keeps this new placement separate from all other placements. So the instructor can place many instances of NoteFlight in their course map and configure each separately.

noteflight-sakai-ctools.jpgWhat you don’t see is that if the instructor placed the activity and then did not configure it, and the student launched it, NoteFlight would say something to the effect of “not yet configured”. But since it is so natural for the instructor to place and then enter the tool, the configuration step just happens in the normal course of setup and the student simply never sees the tool in an unconfigured state.

It takes a while before folks used to writing deep integrations like a BlackBoard Building Block, Moodle Module, and Sakai Tool get the simple elegance of this approach. Most tool developers want to fight with the LMS until their particular and weird configuration needs are properly done in the LMS user interface. The problem is that then the end-user experience is under control of the LMS and they may change it or break it in some future release. Also, it really simplifies writing tool documentation. All of the configuration screens are the same for a tool like NoteFlight – regardless of which LMS it is running in, making documentation simpler. Tool writers kind of have been taught not to feel empowered when facing the daunting task of LMS integration. IMS Basic LTI gives tool writers far greater control over the user experience – which in my opinion is as it should be.

All in all, I want to thank Joseph for his excellent work and helping explore the capabilities in the IMS Basic LTI Specification (www.imsglobal.org).

Abstract: Impact Well-Beyond Market Share: Synergy Between Open Source and Standards

While there are a few very successful open source projects that achieve significant market share such as the Apache Web Server, Tomcat, Linux, and PHP, the vast majority of Open Source projects often achieve a relatively small fraction of market share. This is not surprising given the lack or a profit motive by open source projects. Individual participants in open source projects may have profit motives, but generally the project itself is focused on building the best quality software regardless of the ultimate market share. Even when an open source project has a relatively small market share, it can have a strong influence in the overall market by participating in standards activities as well as providing high-quality reference implementation of standards when those standards are approved. Open Source projects are often the best way to get a standard to the tipping point in terms of market adoption even if the open source software only represents a small fraction of the real market. This talk will discuss standards in general and in particular standards for teaching and learning produced by the IMS Global Learning Consortium. We will discuss the progression of the IMS Learning Tools Interoperability Standard and how open source involvement in the process has greatly affected the overall marketplace.

Video: The Art of Community Source Within Sakai

I have been doing some thinking about the right way to govern Community Source recently. Sakai has been “experimenting” with what it means to be Community Source since 2004. We wonder if Community Source is different than Open Source and if so, how it it different.

Several things have triggered me to think more deeply about this in the last few weeks:

o Approaching first six months of being on the Sakai Board of Directors

o The Review of the Sakai Product Council after one year of its existence

o Seeing the Jono Bacon talk about the “Art of Community”

o Thinking about the upcoming Sakai Conference in Denver and thinking about the kinds of conversations that will happen there

So I decided to make and record a presentation that I titled, “The Art of Community Source” – with full homage to Jono Bacon’s book and talk title :).

Abstract
I start out by reviewing Jono Bacon’s (Ubuntu Community Manager) book and presentation titled “The Art of Community” and describe some of the concepts that come from Jono’s work. I then apply Jono’s terminology to the Moodle, Blackboard, Python, Apache, and Kuali projects to develop a way to categorize open and community source efforts. I then look at Sakai’s changing view of ‘Community Source’ as we transitioned from one executive director (me) to another (Michael Korkuska). I review what I see as the strengths and weaknesses of community structure under both leaders and then suggest how we can improve our current structure – in particular – how we need to adjust our definition of the Sakai Product Council to remove some of the tension in our current structure.

My Slides:  http://www-personal.umich.edu/~csev/talks/2010/2010-05-08-art-of-community-source.pdf

Jono Bacon’s Talk: http://www.youtube.com/watch?v=zKOrWubmzAY
Jono Bacon’s Web Site: http://www.artofcommunityonline.org/

I continue down the path I lay out in this talk in more detail in my review and comments of the Sakai Product Council. I have some recommendations as to how to adjust the remit of the Product Council going forward at:

http://confluence.sakaiproject.org/display/MGT/Chuck+Product+Council+Review+Comments

As always – comments are welcome.

How Do I Replace The Headlight on 2006 Subaru Tribeca

If you owned a 2006 or 2007 Subaru B9 Tribeca, you would know why this post is important. The first year the Tribeca was introduced it had really cool headlights with flowing alien-bugeye styling. Later models have more conventional headlight design and are probably easier to replace. The 2006 Tribeca headlights (particularly the low beams) are a bit of a trick. Particularly the driver side.

Most of what you need to know is in this awesome entry in the FixYa.com forum:

FixYa.com: How do I replace headlight on 2006 subaru tribeca

Low-Beam Headlight Removal Subaru B9 Tribeca 2006 The only thing that is a little vague is how to get the dang clip off and back on. The rest is pretty easy once you can get to the back of the light.

Note: See those Phillips screws – do NOT remove them. I know that our first instinct is to unscrew things – the screws hold the clip in place and are a bear to get back in. Just do NOT under any circumstances remove the Phillips screws you see in these pictures.

First, getting the clip off… Here is a picture of the passenger side bulb facing forward (the left side of the picture is toward the center of the car).. You can see that the leads have been removed from the bulb and tucked down and away.

On the left side of the picture you see the D-shaped left end of the clip. You can just see the end of the clip peeking out from under the bit of metal that is held in place by the left Phillips screw. To remove the clip, push the D-shaped bit toward the front of the car and then down toward the garage floor. It will easily unclip and then pull away easily so you can remove the light.

06-05-10_211604_01.jpgWith the clip off and the light bulb removed, we see the detail of how the D-Shaped part of the clip is actually kind of an S-shape with the little bit that clips under the metal by the left Phillips screw.

We also see that the little alignment tab on the bulb faces downward. The replacement bulb is a Sylvania H7.

To reinstall, put the bulb in with the tab downward, get the clip so it rests on the flat bulb base, push the D-shaped bit of the clip slightly downward and toward the front of the car than let it come back toward you and and the clip will grab under the metal bit by the left Phillips screw and end up looking like the “before disassembly” picture.

Put the leads back on and reassemble the rest and Voila! You have a new low-beam on your 2009 Subaru Tribeca. And you saved $50.00 and several hours of frustration.

P.S. If you followed these instructions so far, imagine for a minute just what a pain it would have been if you took out those Phillips screws.

One more fun bit of information. This design is pretty hard to see. If you have a mirror, you can and should use it to get the lay of the land and figure our how things go together. But I did not have a mirror. All I had was my trusty iPhone. I stuffed a flashlight in to get some light and then put my iPhone in to take pictures that I could not see myself because the space was too small. So the only way I got to see these scenes was through my iPhone acting as a makeshift periscope! Yes – there is an app for that.

FixYa.com: How do I replace headlight on 2006 subaru tribeca

Again, I need to give props the the folks on the FixYa.com forum – they tell you all the hard stuff – especially how to get at the light on the driver’s side. All I added here was the detail and photos regarding working with the clip.