Friday, January 27, 2017

Exploring Akka-HTTP in Scala (1)

Several months ago, while playing with Scala, I've experimented with Spray. As new needs for a production system have recently come up, I am looking at the natural descendent of Spray: Akka-HTTP.
The Akka-HTTP modules implement a full server- and client-side HTTP stack on top of akka-actors and akka-streams. It's not a web-framework but rather a more general toolkit for providing and consuming HTTP-based services. While interaction with a browser is of course also in scope it is not the primary focus of Akka HTTP.
From: Akka-HTTP
The simple need for a HTTP-service provider brought me to explore more of the interesting Akka ecosystem. In fact, Akka-HTTP promotes an interesting way of providing and consuming HTTP-based services and it is built on top of akka-actors and akka-streams.



Akka-actor system

Akka-actor implements the Actor Model to provide a better platform to build scalable, resilient and responsive applications.
From: What is Akka
Check out the following slides and see also the Reactive Manifesto and the Reactive Manifesto 2.0.


Akka-streams

Akka-streams is an abstraction over the Actor system that simplify streams usage, for instance, by taking care of managing back-pressure.
From: Streams introduction
As Endre Varga put it in a very nice blog post (with simple and effective examples):
The primary goal of streams is to provide a simple way to:
  • build concurrent and memory bounded computations
  • that can safely interact with various forms of non-blocking IO interfaces
  • without involving blocking
  • while embracing multi-core concurrency,
  • and solving the typical pitfall of missing back-pressure: faster producers overwhelm slower consumers that run on a separate thread, resulting in OutOfMemoryExceptions.
From: Threading & Concurrency in Akka Streams Explained (part I)
In the same post, Endre summarizes the properties of streams as:

  • Streams do not run on the caller thread. Instead, they run on a different thread in the background, without blocking the caller. 
  • Stream stages usually share the same thread unless they are explicitly demarcated from each other by an asynchronous boundary (which can be added by calling .async between the stages we want to separate). 
  • Stages demarcated by asynchronous boundaries might run concurrently with each other. 
  • Stages do not run on a dedicated thread, but they borrow one from a common pool for a short period.
Here is another good Akka-streams 101 and a presentation:

Read about the more general initiative of Reactive Streams to provide a standard for asynchronous stream processing with non-blocking back pressure here. And see the following presentation:

Friday, January 15, 2016

NTS: JavaScript time and timezones... [1]

Coordinated Universal Time (UTC), is the primary time standard by which the world regulates clocks and time. It is, within about 1 second, mean solar time at 0° longitude;
UTC is one of several closely related successors to Greenwich Mean Time (GMT).
Greenwich Mean Time (GMT) is the mean solar time at the Royal Observatory in Greenwich, London.
UTC, while based on zero degrees longitude, which passes through the Greenwich Observatory, is based on atomic time and includes leap seconds as they are added to our clock every so often. UTC was used beginning in the mid-twentieth century but became the official standard of world time on January 1, 1972.

Although GMT and UTC share the same current time in practice, GMT is a time zone officially used in some European and African countries. UTC is not a time zone, but a time standard that is the basis for civil time and time zones worldwide. This means that no country or territory officially uses UTC as a local time.

Neither UTC nor GMT ever change for Daylight Saving Time (DST). However, some of the countries that use GMT switch to different time zones during their DST period.
The Eastern Time Zone (ET) is a time zone encompassing 17 U.S. states in the eastern part of the contiguous United States, parts of eastern Canada, the state of Quintana Roo in Mexico, Panama in Central America and the Caribbean Islands.
  • Eastern Standard Time (EST) corresponds to ET standard time (autumn/winter) and it is 5 hours behind Coordinated Universal Time (UTC−05:00).
  • Eastern Daylight Time (EDT), is used by some places when observing daylight saving time (spring/summer) is 4 hours behind Coordinated Universal Time (UTC−04:00).

Creating The Date object

There are four ways to create the Date object:

new Date()

We can create a JavaScript Date 'now' object as follows:
var d = new Date();
The Date is created with timezone set to the Local Time timezone (EST for me):
//  d -> Tue Jan 12 2016 23:34:03 GMT-0500 (EST)
It is then possible to compute the timezone difference between UTC and Local Time (EST):
var n = d.getTimezoneOffset();
//  n -> 300 (minutes, equivalent to 5 hours)

new Date(milliseconds)

JavaScript dates are calculated in milliseconds from 01 January, 1970 00:00:00 Universal Time (UTC).
var d = new Date(0); 
//  d -> Wed Dec 31 1969 19:00:00 GMT-0500 (EST) -> D1
One day contains 86,400,000 milliseconds.
var d = new Date(86400000); 
//  d -> Thu Jan 01 1970 19:00:00 GMT-0500 (EST)
By providing a negative amount of milliseconds we will refer to a date prior to 01 January, 1970 00:00:00 Universal Time (UTC).
var d = new Date(-86400000*365); 
//  d -> Tue Dec 31 1968 19:00:00 GMT-0500 (EST) -> One year prior to D1

new Date(dateString)

var d = new Date("October 12, 1973 11:13:00")); 
//  d -> Fri Oct 12 1973 11:13:00 GMT-0400 (EDT)

new Date(year, month, day, hours, minutes, seconds, milliseconds)

Note that the months are identified by 0-11 numbers. Where 0 is January.
var d = new Date(73,9,12,11,13,00,0);
//  d -> Fri Oct 12 1973 11:13:00 GMT-0400 (EDT)
Also note that when the year is specified with an integer between 0-99, that will be translated to a year between 1900 and 1999. In other words when the year is identified by the last or the last two digits (0 = 1900).
var d = new Date(0,9,12,11,13,00,0);
//  d -> Fri Oct 12 1900 11:13:00 GMT-0400 (EDT)
However, the year can be identified by four digits:
var d = new Date(1899,9,12,11,13,00,0);
//  d -> Thu Oct 12 1899 11:13:00 GMT-0400 (EDT)
So, in order to define a date with year between 0 and 99 we can use the method setFullYear():
var d = new Date(19,9,12,11,13,00,0);
d.setFullYear(19);
//  d -> Sat Oct 12 19 11:13:00 GMT-0400 (EDT)
//  d -> -61543010820000 (ms from 01 January, 1970 00:00:00 UTC)
Note that the method setYear() will behave exactly as the constructor:
var d = new Date(19,9,12,11,13,00,0);
d.setYear(19);
//  d -> Sun Oct 12 1919 11:13:00 GMT-0400 (EDT)
//  d -> -1584866820000 (ms from 01 January, 1970 00:00:00 UTC)
Read more on the Mozilla Developer Network.

Thursday, January 07, 2016

NTS: JavaScript testing of null, undefined...

In JavaScript, there are a couple of ways to verify if a variable is not undefined.

Undefined

Undefined type is a built-in JavaScript type. undefined (immutable) value is a primitive and is the sole value of the Undefined type. Any property that has not been assigned a value, assumes the undefined value. A function without a return statement, or a function with an empty return statement returns undefined. The value of an unsupplied function argument is undefined. The undefined  global variable which is a reference to the value undefined. In ES3 this variable is mutable, while in ES5 it is immutable.

So the global undefined property represents the primitive value undefined.

Objects are aggregations of properties. A property can reference an object or a primitive. Primitives are values, they have no properties. In JavaScript there are 5 primitive types: undefined, null, boolean, string and number. Everything else is an object. The primitive types boolean, string and number can be wrapped by their object counterparts. These objects are instances of the Boolean, String and Number constructors respectively.

The latest ECMAScript standard defines seven data types (source Mozilla Contributors):
undefined is a a global variable or a property of the global object.

typeof undefined;  // "undefined"

var name = "Paolo Ciccarese";
name = undefined;
typeof name;       // "undefined"

From ES5 the property cannot be re-assigned, and an attempt will fail silently. By turning on the 'strict mode' attempting to assign a value to undefined will throw an error instead. In general, even when possible, re-assigning undefined is not a good idea.

The Global object is an intrinsic object whose purpose is to collect global functions and constants into one object. The global object itself can be accessed using the this operator in the global scope. The Global object cannot be created using the new operator. It is created when the scripting engine is initialized, thus making its functions and constants available immediately.

Undefined: Local or Declared Variables


if (name === undefined) ... // Works for local and/or declared variables

This approach (JSFiddle) works when the variable has been defined for instance in a function:
function myFunction(foo) {
    if (foo === undefined) {
        alert('sorry, that is undefined');
    }
}
myFunction();

However, if the variable has never been declared, that would trigger an exception (JSFiddle - see the console):
function myFunction() {
    if (foo === undefined) { // Triggers a ReferenceError exception
        alert('sorry, that is undefined');
    }
}
myFunction();

Therefore, this approach works well for local variables that we know have been declared. It is not a convenient approach for local variables that might have not been declared.

Avoid the following as it returns true also for null:
if (typeof foo == 'undefined') ... // Returns true also for null

Undefined: Global Variables


if(typeof name === "undefined") ... // Works for global and local variables

This approach works for both declared (JSFiddle):
function myFunction(foo) {
    if (typeof foo === 'undefined') {
        alert('sorry, that is undefined');
    }
}
myFunction();

and undeclared variables (JSFiddle):
function myFunction() {
    if (typeof foo === 'undefined') {
        alert('sorry, that is undefined');
    }
}
myFunction();

We might argue this last approach is safer in general.

Null

The Null (type) has exactly one value, called null (value). The value null is a JavaScript literal representing null or an "empty" value, i.e. no object value is present. It is one of JavaScript's primitive values and also - unlike undefined - a JavaScript keyword. Because of being a keyword, null is inherently unassignable, while ES5 had to add a special rule to cover the undefined global variable.

null is classified as a JavaScript Object:
typeof(null) // object
typeof(undefined) // undefined
The value null is a JavaScript literal representing null or an "empty" value, i.e. no object value is present. In other words we can assign null to a variable without a value:
var nv = null; // null
typeof nv      // object

Notice that:
null === undefined // false
null == undefined  // true*
null == false;     // false
null == '';        // false
null == 0;         // false
* see language specifications here


Testing for Null


So if we test with:
if (x == null) ... // Tests both null and undefined
We are actually testing for name to be null and undefined at the same time. But if we test with:
if (x === null) ... // Tests for null only

Testing for Undefined and Null

For testing both null and undefined (when a variable is declared) it is possible to do:
if (x != null)  ... // Tests both null and undefined

Ore more explicitly:
if (x !== undefined && x !== null)  ... // Tests both null and undefined

And to prevent ReferenceError for undeclared variables:
if (typeof x !== 'undefined' && x !== null)  ... // Tests null, undefined

Falsey values

In JavaScript we can also test with the following:
if (!x) ... // Tests for falsey values

Which will be evaluated true if name is: null, undefined, NaN, empty string ("" or ''), 0, -0, false. This checking has to be used carefully when the value of the data could be 0 or false or an empty string.

Friday, October 17, 2014

When SPARQL query length is an issue

While developing Annotopia I wrote some code to create dynamically SPARQL queries servicing a faceted search. According to the facets values, the queries can become extremely long... until I hit the limit:

Virtuoso 37000 Error SP031: SPARQL: Internal error: 
       The length of generated SQL text has exceeded 10000 lines of code
It seems that the SPARQL compiler stops because the SQL compiler, the successor in the processing pipeline, will fail to compile it in any reasonable time. After initial surprised reaction I started to dig deeper in the structure of my queries. Here is what I learned.

Use the FILTER + IN construct instead of multiple UNIONs


It might result simpler, when writing code, to dynamically compose a query with lists of UNIONs. Unfortunately that translates in much longer SQL queries. So this:

        
        { ?s oa:serializedBy <urn:application:domeo> }
        UNION
        { ?s oa:serializedBy <urn:application:utopia> }

for multiple items, should become:

        { ?s oa:serializedBy ?serializer .
            FILTER ( ?serializer IN 
               (<urn:application:domeo>, <urn:application:utopia>) )
        }

Friday, October 10, 2014

Annotopia 101 - Basic use for document/data annotation

This post explains how to get started in using Annotopia as a server for document/data annotation. It assumes Annotopia is already installed and running and that you have admin access to the instance.


Step 1. Register your system

After logging in (as admin) to Annotopia, you will see a welcome screen:
  • Click on 'Administration Dashboard' (top left of the screen)


  • Select 'Create System'

  • Fill out the form and 'Save system'

  • Take note of the 'API key' which is going to be used by your system to communicate with Annotopia when Annotopia is not set up to use a stronger Authentication mechanism.

 

Step 2. Create my first annotation (POST)

Assuming that the server address is http://myserver.example.com:8090 we are going to create our first POST. Normally your application will connect to the server through Ajax or a server call. For the sake of this tutorial we are going to use curl that is easy to use in command line.

The structure of the POST for an annotation item is very simple (API documentation here):

  curl -i -X POST http://myserver.example.com:8090/s/annotation \
       -H "Content-Type: application/json" \
       -d'{"apiKey":"{+SYSTEM_API_KEY}", "outCmd":"frame", "item":{+ANNOTATION}}
Where +SYSTEM_API_KEY is the API key of the previous section and +ANNOTATION is the actual annotation content. Notice also the parameter "outCmd":"frame", this is used to frame the JSON-LD result, which means that the result will always be returned with a precise hierarchical structure so that the clients don't have to deal with the variability of a graph-like representation.

A simple example of Annotation of type Highlight (conformant to the Open Annotation Model) would be:

{
 "@context": "https://raw2.github.com/Annotopia/AtSmartStorage/master/web-app/data/OAContext.json",
 "@id": "urn:temp:7",
 "@type": "oa:Annotation",
 "motivatedBy": "oa:highlighting",
 "annotatedBy": {
  "@id": "http://orcid.org/0000-0002-5156-2703",
  "@type": "foaf:Person",
  "foaf:name": "Paolo Ciccarese"
 },
 "annotatedAt": "2014-02-17T09:46:11EST",
 "serializedBy": "urn:application:utopia",
 "serializedAt": "2014-02-17T09:46:51EST",
 "hasTarget": {
  "@id": "urn:temp:8",
  "@type": "oa:SpecificResource",
  "hasSelector": {
   "@type": "oa:TextQuoteSelector",
   "exact": "senior scientist and software engineer",
   "prefix": "I am a",
   "suffix": ", working in the bio-medical informatics field since the year 2000"
  },
  "hasSource": {
   "@id": "http://paolociccarese.info",
   "@type": "dctypes:Text"
  }
 }
}


Note that:
  • the '@context' is necessary for the server to interpret the content
  • the '@id' fields contain a temporary value. In fact, when posting an annotation for the first time, the server will mint URIs for Annotation and Target and will return the updated content to the client as a response of the POST
  • the 'motivatedBy' property declares that the intent of the annotation is of highlighting.
  • the 'hasTarget' uses a quote of the annotated piece of content. 
  • the 'hasSource/@id' represents the URI of the annotated resource
  • the 'hasSelector' identifies a fragment of that resource.
  • the 'serializedBy' declares which system created the artifact. In the above case it is the Utopia for PDF application. Domeo would  be urn:application:domeo**.
** Note that this aspect is not fully implemented yet, therefore only specific systems are recognized by Annotopia and used for filtering. All others are managed but not exploited. In other words, currently only two values are fully manage 'urn:application:domeo' and 'urn:application:utopia'. Alternative values can be used and stored but they will not appear in the facets.  for search.

A simpler example of Annotation of type Comment of an entire resource:

{
    "@context": "https://raw2.github.com/Annotopia/AtSmartStorage/master/web-app/data/OAContext.json",
    "@id": "urn:temp:001",
    "@type": "http://www.w3.org/ns/oa#Annotation",
    "motivatedBy": "oa:commenting",
    "annotatedBy": {
        "@id": "http://orcid.org/0000-0002-5156-2703",
        "@type": "foaf:Person",
        "foaf:name": "Paolo Ciccarese"
    },
    "annotatedAt": "2014-02-17T09:46:11EST",
    "serializedBy": "urn:application:domeo",
    "serializedAt": "2014-02-17T09:46:51EST",
    "hasBody": {
        "@type": [
            "cnt:ContentAsText",
            "dctypes:Text"
        ],
        "cnt:chars": "This is an interesting document",
        "dc:format": "text/plain"
    },
    "hasTarget": "http://paolociccarese.info"
}
 
Note that:
  • the 'hasBody' shows how to encode textual content
  • the 'hasTarget' is just a URI**.
** Note that as the target is a URI, anything identifiable can be annotated. In the above case we are annotating a web page, but the URI could be the identifier for a Data point as well.

Once the POST is sent, if everything is correct, the server (if "outCmd":"frame" was specified) will return a result message that has the following structure:

{"status":"saved", "result": {"duration": "1764ms","graphs":"1","item":[{
  "@context" : {
    ...
  },
  "@graph" : [ {
    "@id" : "http://myserver.example.com:8090/s/annotation/597C3DE9-8657-4FA6-ABCA-895A74B448E9",
    "@type" : "oa:Annotation",
    "http://purl.org/pav/previousVersion" : "urn:temp:7",
    "annotatedAt" : "2014-02-17T09:46:11EST",
    "annotatedBy" : {
      "@id" : "http://orcid.org/0000-0002-5156-2703",
      "@type" : "foaf:Person",
      "name" : "Paolo Ciccarese"
    },
    "hasTarget" : {
      "@id" : "http://myserver.example.com:8090/s/resource/ED20AE10-4916-485C-903D-54D6F11DF682",
      "@type" : "oa:SpecificResource",
      "http://purl.org/pav/previousVersion" : "urn:temp:8",
      "hasSelector" : {
        "@id" : "_:b0",
        "@type" : "oa:TextQuoteSelector",
        "exact" : "senior scientist and software engineer",
        "prefix" : "I am a",
        "suffix" : ", working in the bio-medical informatics field since the year 2000"
      },
      "hasSource" : {
        "@id" : "http://paolociccarese.info",
        "@type" : "dctypes:Text"
      }
    },
    "motivatedBy" : "oa:highlighting",
    "serializedAt" : "2014-02-17T09:46:51EST",
    "serializedBy" : "urn:application:utopia"
  } ]
}]}}

Note that:
  • the updated message is stored in the "item" section in a '@graph'
  • the '@id' have been updated with resolvable URIs
  • the property "http://purl.org/pav/previousVersion" returns the original temporary '@id' for matching.

Step 3. How to include bibliographic metadata/identifiers

Annotopia can use identifiers (PubMed IDs, PubMed Central IDs, DOIs and PIIs) to resolve equivalent documents. For example a HTML version of the document vs a PDF version. Or multiple HTML versions of the same document.

To include bibliographic metadata identifiers in the annotation, is sufficient to add the data to the 'hasSource' section as follows:

"hasSource": {
 "@id": "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3102893/",
 "@type": "dctypes:Text",
 "format": "text/html",
 "http://purl.org/vocab/frbr/core#embodimentOf": {
                "http://purl.org/dc/terms/title":"An open annotation ontology for science on web 3.0",
                "http://prismstandard.org/namespaces/basic/2.0/doi": "10.1186/2041-1480-2-S2-S4",
  "http://purl.org/spar/fabio#hasPII": "2041-1480-2-S2-S4",
  "http://purl.org/spar/fabio#hasPubMedCentralId": "PMC3102893",
  "http://purl.org/spar/fabio#hasPubMedId": "21624159"
 }
}

Step 4. Request for a specific annotation (GET {$id})

For requesting a specific annotation through its URI it is sufficient to execute (see API docs):

    curl -i -X GET +ANNOTATION_URI -H "Content-Type: application/json" \
       -d'{"apiKey":"+SYSTEM_API_KEY","outCmd":"frame"}'

Step 4. Request for annotations for a document (GET)

It is common to request the annotation for a particular document by URI (see API docs):

    curl -i -X GET http://myserver.example.com:8090/s/annotation \
      -H "Content-Type: application/json" \
      -d '{"apiKey":"+SYSTEM_API_KEY","tgtUrl":"http://www.jbiomedsem.com/content/2/S2/S4"}'


Or by bibliographic identifier:
    curl -i -X GET http://myserver.example.com:8090/s/annotation \
      -H "Content-Type: application/json" \
      -d '{"apiKey":"+SYSTEM_API_KEY","tgtIds":"{'pii':'2041-1480-2-S2-S4'}"}'

Tuesday, July 08, 2014

Adding bibliographic data to Open Annotation

One of the challenges for achieving interoperability between annotation clients that deal with different formats (for example PDF and HTML, see previous post Domeo and Utopia integration through Annotopia) is to be able to identify the annotated content.

For example, let's consider the paper about Annotation Ontology: Ciccarese P, Ocana M, Castro LJG, Das S, Clark, T. An open annotation ontology for science on web 3.0. J Biomed Semantics 2011, 2(Suppl 2):S4 (17 May 2011) [doi:10.1186/2041-1480-2-S2-S4]

Besides this PDF version (there might be others) of the article:
* PDF at Journal of Biomedical Semantics

The manuscript can be found in HTML format at least in these two locations (which exhibits different layouts):
* PubMed Central
* Journal of Biomedical Semantics

We know that the same content can be identified through identifiers:
* DOI (Digital Object Identifier) 10.1186/2041-1480-2-S2-S4
* PMID (PubMed ID) 21624159
* PMCID (PubMed Central ID) PMC3102893
* PII (Publisher Item Identifier) 2041-1480-2-S2-S4

In order to take into account all the available identifiers, it is possible to include in the annotation target the additional information. So if the client is annotating the PubMed Central version of the document (identified by the URL http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3102893/), the source of the target will be identified by:

 ...
    "hasSource": {
        "@id": "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3102893/",
        "@type": "dctypes:Text",
        "frbr:embodimentOf" : 
        { 
            "prism:doi": "10.1186/2041-1480-2-S2-S4",
            "fabio:hasPII":"2041-1480-2-S2-S4",
            "fabio:hasPubMedCentralId":"PMC3102893",
            "fabio:hasPubMedId":"21624159"
        }
        
    }
Where I made use of the FaBiO (FRBR aligned bibliographic Ontology) ontology which, in turns, reuse term from the FRBR ontology and the PRISM vocabulary. Kudos to Silvio Peroni for pointing out that the relationship between the Manifestation (HTML page) and the Expression should be frbr:embodimentOf and not fabio:manifestationOf. The latter would assume the identifiers are identifying the Work.

Domeo and Utopia integration through Annotopia

Here is a very recent demo of annotation created on a HTML document through Domeo and then seen on the correspondent PDF with the Utopia PDF viewer. All through Open Annotation and Annotopia.

Thanks to Steve Pettifer and Dave Thorne (for the Utopia plugin development); Thomas Wilkins for OAuth implementation in Annotopia. Annotopia is currently architected and developed by me.

Friday, April 25, 2014

Annotopia: Creation/updates with Open Annotation (?)

I am currently developing the Annotopia Open Annotation server [GitHub, Living Slides, Talk 'I Annotate 2014'] and there are a few topics related to the application of the Open Annotation Model that might need further discussion within the community. I will start with one

:: Date/agent of annotation creation and update ::

Even if we don't have the need to support versioning (this will be subject of a future post) and in the unlikely event that the annotation cannot be edited we often need to be able to keep track of who/when the annotation has been created and, eventually, updated. 


Open Annotation Provenance Model

The Open Annotation Model now supports the following provenance relationships/properties:


Vocabulary ItemTypeDescription
oa:annotatedByRelationship[subProperty of prov:wasAttributedTo] The object of the relationship is a resource that identifies the agent responsible for creating the Annotation. This may be either a human or software agent.
There SHOULD be exactly 1 oa:annotatedBy relationship per Annotation, but MAY be 0 or more than 1, as the Annotation may be anonymous, or multiple agents may have worked together on it.
oa:annotatedAtPropertyThe time at which the Annotation was created.
There SHOULD be exactly 1 oa:annotatedAt property per Annotation, and MUST NOT be more than 1. The datetime MUST be expressed in the xsd:dateTime format, and SHOULD have a timezone specified.
oa:serializedByRelationship[subProperty of prov:wasAttributedTo] The object of the relationship is the agent, likely software, responsible for generating the Annotation's serialization.
There MAY be 0 or more oa:serializedBy relationships per Annotation.
oa:serializedAtPropertyThe time at which the agent referenced by oa:serializedBy generated the first serialization of the Annotation, and any subsequent substantially different one. The annotation graph MUST have changed for this property to be updated, and as such represents the last modified datestamp for the Annotation. This might be used to determine if it should be re-imported into a triplestore when discovered.
There MAY be exactly 1 oa:serializedAt property per Annotation, and MUST NOT be more than 1. The datetime MUST be expressed in the xsd:dateTime format, and SHOULD have a timezone specified.

So we can encode when the annotation has been created and usually that coincides with the time when the user created the annotation on the user interface of the annotation client.

Then the annotation is sent to the server to be persisted.

Do nothing approach

One possible approach, that I would rather not advocate for, is to forget about the concepts of creation and update: 'every time a change is performed on an annotation, the old instance is swapped with the new one. The new one replaces entirely the previous annotation and shares the same URI.'. In this case, 'annotatedAt' is always referring to the latest annotation event (no matter if it was the original creation or following updates). 

Use a richer provenance model

To be a little more exhaustive, in Annotopia, as I was doing in Domeo and Annotation Ontology, I could use a series of properties of PAV (Provenance, Authoring and Versioning) ontology [paper]: pav:createdOn (when it has been created), pav:createdBy (who created it), pav:lastUpdateOn (when it has been last updated), pav:lastUpdateBy (who last updated the annotation).

So I could say:

Option A: Add lastUpdateOn

In this scenario we use annotatedAt/annotatedBy for the annotation creation and lastUpdateOn/lastUpdateBy for the last update.

{
    "@id" : "http://host/s/annotation/830ED7EE-BF7B-4A18-8AE1-A9AF96AC135B",
    "@type" : "oa:Annotation",
    "annotatedAt" : "2014-02-17T09:46:11EST",
    "annotatedBy" : {
      "@id" : "http://orcid.org/0000-0002-5156-2703",
      "@type" : "foaf:Person",
      "name" : "Paolo Ciccarese"
    },
    "pav:lastUpdateOn" : "2014-03-11T11:46:11EST",
    "pav:lastUpdateBy" : {
      "@id" : "http://example.org/johndoe",
      "@type" : "foaf:Person",
      "name" : "John Doe"
    }
...
}

In this case, both events would refer to when the act has been performed on the user interface (?).

Option B: Add createdOn and lastUpdateOn

Here we make use of annotatedAt/annotatedBy, createdOn/createdBy and  lastUpdateOn/lastUpdateBy

{
    "@id" : "http://host/s/annotation/830ED7EE-BF7B-4A18-8AE1-A9AF96AC135B",
    "@type" : "oa:Annotation",
    "pav:previousVersion" : "urn:temp:001",
    "annotatedAt" : "2014-02-17T09:46:11EST",
    "annotatedBy" : {
      "@id" : "http://orcid.org/0000-0002-5156-2703",
      "@type" : "foaf:Person",
      "name" : "Paolo Ciccarese"
    },
    "pav:createdOn" : "2014-02-17T09:48:11EST",
    "pav:createdBy" : {
      "@id" : "http://orcid.org/0000-0002-5156-2703",
      "@type" : "foaf:Person",
      "name" : "Paolo Ciccarese"
    },
    "pav:lastUpdateOn" : "2014-03-11T11:46:11EST",
    "pav:lastUpdateBy" : {
      "@id" : "http://example.org/johndoe",
      "@type" : "foaf:Person",
      "name" : "John Doe"
    }
...
}

In this case it is necessary to agree on the semantics of all those properties. I could use:
(i) 'createdOn/createdBy' for the original creation on the (Annotopia) server
(ii) 'lastUpdateOn/lastUpdateBy' for the last update on the (Annotopia)  server
(iii) and what is  'annotatedAt' going to indicate? The original creation or the latest update? And how do I keep track of the agents involved?

Saturday, February 08, 2014

A W3C Workshop on Annotations (April 2) and the I Annotate 2014 Conference (April 3-5)

The beginning of April is going to be a very exiting period for Annotation.
A W3C Workshop on Annotations
On April 2nd W3C is organizing a full day workshop in San Francisco on Annotation http://www.w3.org/2014/04/annotation/ Those who are members of the Open Annotation Community Group already know that there is a concrete possibility for a W3C Working Group focused on Annotation. A first draft of the charter has been shared: http://www.w3.org/2014/01/Ann-charter.html and comments/thoughts on that can be shared on the mailing list public-annotation@w3.org

I Annotate 2014
Hypothes.is just advertised the 2014 edition of the I Annotate conference for April 3-4 followed by two days of hacking 4-5.  Registration is now open.

Both events will be held at the FORT MASON CENTER - SAN FRANCISCO, CA.

Here are some links to videos of "I Annotate 213" presentations, more here.




From CATCH to HarvardX to Annotopia

On October 18, 2012, Philip Desenne (at the time Senior Product Manager, Academic Technology Services at Harvard), Martin Schreiner (Head of Maps, Media, Data and Government Information, Harvard College Library) and I got awarded a small grant from Harvard Library Labs called CATCH: Common Annotation, Tagging, and Citation at Harvard.

The idea was to create a federated network of server for storing annotations created for pedagogical purposes. As we knew there are many applications at Harvard creating annotation we wanted to provide a common back-end for all these to store, retrieve and search for annotation. The CATCH was meant to produce also some services for translating annotation into Open Annotation format so that we could store all the annotation coming from different tools in a uniform way that would have made search a lot easier.

Obviously, as I've spent the last two years developing the Domeo Annotation Tool, the idea was also to have Domeo using the same technology for storing/retrieving/searching annotation.



However, the original grant has been broken down in two phases and only the first phase has been funded so far. As result of the first phase I produced with the help of Justin Miranda, a back end for persisting annotation produced by an annotator client based on annotator.js technology.

Three weeks ago,  both client (thanks to the work by Daniel Cebrian Robles and Phil Desenne) and the CATCH server (developed by Justin Miranda and I) entered production in HarvardX for one class that counts about 14.000 students.

As the result of phase I was supposed to be just a prototype and not a production quality server, this has been a stressful and at the same time exciting transition.
In a few days, the CATCH counts already 21.000 annotation produced by more than 800 students and the number of annotations is increasing steadily.
The future of CATCH is named Annotopia
The original plan for CATCH has not been fully realized and the streaming of funding ended. So in agreement with Tim Clark (Director of MIND Informatics and PI of the Domeo project) we decided to create a new project called Annotopia that will consist in developing the full potential of the original CATCH idea. Annotopia will also provide additional services: text mining, terms search and support for semantic annotation. These features were already available in Domeo but they will be generalized and made available through APIs for third party annotation clients. 

The CATCH codebase will merge with the new platform and, at least for now, we will still refer to the name CATCH for indicating the instance for HavardX of the Annotopia annotation back-end.

The first release of Annotopia is scheduled by the end of March.

Monday, January 27, 2014

JSON-LD, Jena, Virtuoso and Named Graphs

After working for a couple of years on the Domeo Annotation Tool I am now working on a couple of projects that focus on the creation of a back-end for saving/searching annotation. I am planning to use the Open Annotation model and some other ontologies such as: PAV (Provenance, Authoring and Versioning) ontology and maybe CO (Collections Ontology).

Named Graphs and JSON-LD

Most importantly I am going to make large use of Named Graphs and their serialization in JSON-LD format, which is the recommended format for Open Annotation. JSON-LD became very recently a W3C Recommendation.
A Named Graph is a collections of Statements that is identified by a URI.
JSON-LD is a lightweight Linked Data format. It is easy for humans to read and write. It is based on the already successful JSON format and provides a way to help JSON data interoperate at Web-scale.
JSON-LD provides a very slick way of representing Named Graphs. Here is an example of Named Graph used for representing a very basic annotation (with Open Annotation):
  
  {
     "@context": {
        ...
     },
     "@id": "http://example.org/graphs/1",
     "@graph":
     [
        {
          "@id": "http://www.example.org/ann/1",
          "@type": "oa:Annotation",
          "hasBody": "http://www.example.org/body/1",
          "hasTarget": "http://www.example.org/target/1"
        }
     ]
  }

  Figure 1 - JSON-LD representation of a Named Graph and Open Annotation data.
  You can find the full @context in the Open Annotation specifications.

Loading JSON-LD in memory with Jena API 

I would like to store the above Named Graph for instance in the triple store Virtuoso Open-Source Edition. For this task I chose the Apache Jena API that makes use of the JSON-LD implementation for Java

I will start by loading in memory the above JSON-LD code (figure 1) that is currently in a JSON file:
  
  JenaJSONLD.init(); // Only needed once
  
  Dataset dataset = DatasetFactory.createMem();
  InputStream inputStream = new FileInputStream(annotationFile);
  if(inputStream == null) {
    throw new IllegalArgumentException("File: " + annotationFile + " not found");
  }
  RDFDataMgr.read(dataset, inputStream, "http://example.com/", JenaJSONLD.JSONLD);

  Figure 2 - Jena API code for loading the JSON-LD file in an in-memory Dataset.
The reason why I used a Dataset rather than a Model is because the
Dataset is a collection of named graphs and a background graph (also called the default graph or unnamed graph)
And that fits exactly the needs we have with the code in Figure 1. And the needs of much more complex use cases related to Domeo. Also, this approach works for both the JSON-LD making and not making use of graphs. If the JSON-LD does not contain any graph, the Statements will belong to the default graph.

Note: When I tired to use the Model and not the Dataset for loading the JSON-LD files, I realized that only the files with no @graph declarations were loaded correctly. The ones with the @graph declaration were not generating any statement.

Persist the Named Graphs in Virtuoso 

And these are the few lines of code I use to store the in-memory graphs in the Virtuoso store (I am sure there is a better way of doing this and combining the above step with these lines of code, however, this seems to work the way I want):
  // Default graph
  if(dataset.getDefaultModel()!=null && dataset.getDefaultModel().size()>0) {
    VirtGraph virtGraph = new VirtGraph (
      "jdbc:virtuoso://localhost:1111", "dba", "dba");
    VirtModel virtModel = new VirtModel(virtGraph);
    virtModel.add(dataset.getDefaultModel());
    // Print the triples
    println "graph: *"
    RDFDataMgr.write(System.out, dataset.getDefaultModel(), JenaJSONLD.JSONLD);
  }

  // Named graphs
  Iterator names = dataset.listNames()
  while(names.hasNext()) {
    String name = names.next();
    Model model = dataset.getNamedModel(name)
    VirtGraph virtGraph = new VirtGraph (name, 
      "jdbc:virtuoso://localhost:1111", "dba", "dba");
    VirtModel virtModel = new VirtModel(virtGraph);
    virtModel.add(model);

    // Print the triples
    println "graph: " + name
    RDFDataMgr.write(System.out, model, JenaJSONLD.JSONLD);
  }

  Figure 3 - Saving default and named graphs in Virtuoso

Software versions used in the example above

For the above examples I've used the following libraries/versions:
  • jena-core v. 2.11.0
  • jena-arq v. 2.11.0
  • jsonld-java-jena v. 0.2.99
  • virtjdbc4.jar
  • virt_jena2.jar

Wednesday, August 21, 2013

JSON parsing in JavaScript

Recently I've has some blocking issues with some code I wrote a while ago. A colleague tried to re-use that code with a different back-end and he kept experiencing the exception:
JSON.parse: unexpected character
Using Firebug, I promptly inspected the JSON content that was retrieved from the new service and by copying and pasting it into http://jsonlint.com/ it seemed to be valid JSON. However, the exception was still there and clearly indicated an issue with the format of the incoming content. I therefore inspected the code of both client and server and it turns out that (1) the old JavaScript snippet was using the eval function and (2) the new back-end, mimicking what my old testing code was doing, was generating through a servlet some testing JSON just by concatenating some strings and serializing the results as JSON.

The serialization of the service was including some '\n' (new lines) that, in the old ecosystem, improved the visualization of the JSON content apparently without disrupting the activity of the eval function. The serialized content included also some dates in the format 'MM/dd/yyyy HH:mm:ss Z'.
The eval function invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure (read more on json.org).
Strangely the same code that was working fine in my configuration, was failing in the configuration used by my colleague that seemed failing while interpreting the format of the dates.

As I had a similar problem months ago, I've decided therefore to move away from the eval function:
    In the old GWT code, making use of JNI:

    public static native JavaScriptObject parseJson(String jsonStr) /*-{
        return eval('(' + jsonStr + ')');
    }

    The equivalent in pure JavaScript would be (remember the parenthesis 
    as they turn the code into an expression that returns, rather than 
    just code to run):

    function parseJson(jsonStr) {
         return eval('(' + jsonStr + ')');
    }
to use the more recent JSON.parse which provides validation of the JSON content unlike eval that is faster but allows the string being parsed to contain absolutely anything including function calls.
Native JSON support is included in newer browsers and in the newest ECMAScript (JavaScript) standard. Similar features were already available with some JS libraries such as JQuery (http://api.jquery.com/jQuery.parseJSON/).
See http://www.w3schools.com/json/json_eval.asp for browser and software support.
When using the JSON.parse it is however necessary to escape the control characters.
According to section 2.5 of the JSON spec at ietf.org/rfc/rfc4627.txt: "All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)."
In that specific testing case the newline character could have been present in both the JSON values and in between JSON elements.
    // 1) Example of JSON with newline in the value
    [{"name":"Paolo Ciccarese \n"}]

    // 2) Example of JSON with newline between elements
    [\n{"name":"Paolo Ciccarese"}]
The above case 1) can be addressed by escaping the content (for instance replacing '\n' with '\\n'. The case 2) is illegal in JSON and would work only if using the eval function.
In my case the servlets were generating the '\n' because of the use of out.println instead of the harmless out.print
So in my case the parseJSON function became:
    In the old GWT code, making use of JNI:

    public static native JavaScriptObject parseJson(String jsonStr) /*-{
        try {
            var jsonStr = jsonStr      
                .replace(/[\\]/g, '\\\\')
                .replace(/[\/]/g, '\\/')
                .replace(/[\b]/g, '\\b')
                .replace(/[\f]/g, '\\f')
                .replace(/[\n]/g, '\\n')
                .replace(/[\r]/g, '\\r')
                .replace(/[\t]/g, '\\t')
                .replace(/\\'/g, "\\'");
            return JSON.parse(jsonStr);
        } catch (e) {
            alert("Error while parsing the JSON message: " + e);
        }
    }-*/;

    In pure JavaScript would be:

    function parseJson(jsonStr) {
        try {
            var jsonStr = jsonStr      
                .replace(/[\\]/g, '\\\\')
                .replace(/[\/]/g, '\\/')
                .replace(/[\b]/g, '\\b')
                .replace(/[\f]/g, '\\f')
                .replace(/[\n]/g, '\\n')
                .replace(/[\r]/g, '\\r')
                .replace(/[\t]/g, '\\t')
                .replace(/\\'/g, "\\'");
            return JSON.parse(jsonStr);
        } catch (e) {
            alert("Error while parsing the JSON message: " + e);
        }
    }
  
Therefore in the case:
    [{"name":"Paolo Ciccarese \n"}]
the newline is not interpreted as a newline in the JSON source anymore but as a newline in the JSON data, which is perfectly fine.

In conclusion, I am still not sure why the dates interpretation was failing with the eval method. But with the JSON.parse approach the problem is gone.

I also found this: 'A fast and secure JSON parser in JavaScript'. I did not have time to check out yet but it is promising: ' does not attempt to validate the JSON, so may return a surprising result given a syntactically invalid input, but it does not use eval so is deterministic and is guaranteed not to modify any object other than its return value'.

Saturday, July 20, 2013

Domeo, Annotation Framework, Catch Annotation Hub and Grails Plugins architecture

I found organizing big projects in components always a reassuring idea.
Component Oriented Programming? I let you decide if that is what I mean. I’ve read several discussion on the topic Component Oriented Programming vs. Object Oriented Programming and I am personally one of those who believes the two strategies are complementary and not in competition. As I am not interested in debating the theoretical differences, I would stick to what I normally do and not what I think.
That is one of the reasons I’ve always liked - and I still like - OSGi and that is also one of the reasons I’ve been always attracted by the Grails Plugins architecture.
The components oriented approach did not always pay off. Occasionally I just gave up when I found myself fighting with the technology of the moment, which was getting a little on the way. I am sure most of my problems were related to my limited knowledge of that particular technology... still, deadlines are deadlines and I needed to get things done.
I am certainly not the first nor the last developer celebrating the Grails Plugin Oriented Architecture. Here is a blog post that shows how a domain class defined in a plugin can be reused by other components of the architecture.

However, I have been thinking about the OSGi-based Eclipse architecture for a long time and I even tried to develop a lighter Java framework for developing applications along the same lines. Naturally, since I've been using Grails, I’ve been thinking on how to reproduce the same behavior in web applications by using Grails plugins. Basically I am talking about conveniently leveraging plugins to benefit from all the perks of the Grails platform: domain classes, services, controllers and views. I will defer to future posts some of the technical details. Meanwhile I wish to provide a little context.

I am thinking of leveraging the plugin architecture for a project called CATCH that I’ve been working on for a tiny grant awarded by Harvard Library Labs. As the Domeo Annotation Tool already provided some of the features I need for CATCH I've decided to refactor and spin off some of its components. I've  created a new GitHub project called Annotation Framework which will collect all the new improved modules that will be later used by both Domeo and CATCH


CATCH Annotation Hub

The goal of CATCH is to provide a hub for collecting/searching and sharing annotation produced by several clients. These includes the Domeo annotation client, HighBrow - an annotation client developed at Harvard by Reinhard Engels - and annotator.js an open-source JavaScript library and tool - developed by Nick Stenning  - that can be added to any webpage to make it annotatable.

Both CATCH and the older sister project Domeo are meant to be installed in several instances that should be able to communicate with each other in a federated architecture. You can think this as a series of Annotation Framework Nodes that are distributed and connected so that when a user performs a search on one of the nodes, it can also find results that have been created and stored in other authorized/linked nodes. All with access control...


Friday, October 12, 2012

It seems all a matter of size

After the new iPhone 5 sporting a bigger screen and a thinner body*, comes the Samsung SIII mini and probably a new smaller iPad mini. Then I see the new Vaio Tap 20 that it is really a new kind of PC. Watching movies on a home-portable bigger screen, playing social games... but still having a full PC available for editing two documents at the same time by typing with a real old-style classic keyboard.

 New Vaio Tap 20 - source Sony

I don't really like the idea of 'touching' the screen of a laptop, which seems way too delicate and wobbly but I kind of like the idea of a bigger home-tablet. I am just wondering what happens when this big screen falls on the ground... because that is going to happen.

* I would have honestly gave that up for a better battery

Thursday, October 11, 2012

Here's To The Crazy Ones, Again

Years ago I cam across the famous Apple Computers most inspiring piece of advertisement - at least for me:
"Here's To The Crazy Ones. The misfits. The rebels. The trouble-makers. The round pegs in the square holes. The ones who see things differently. They're not fond of rules, and they have no respect for the status-quo. You can quote them, disagree with them, glorify, or vilify them. About the only thing you can't do is ignore them. Because they change things. They push the human race forward. And while some may see them as the crazy ones, we see genius. Because the people who are crazy enough to think they can change the world - are the ones who DO !" - Apple Computers
Naturally, I believe many people mentally associated this piece to one person Steve Jobs. At the end, the good times of Apple seem always been happening during Steve's lead - and I believe that is one of the reasons why everything that is going on with iOS6 and iPhone 5 is carefully monitored and inspected by the entire world. Personally, I just liked what the piece conveys. 

Anyhow, after days of reading about the new iPhone 5 problems, and in particular about the fact that the aluminum scratches really easily, I read this: These Laser-Engraved iPhone 5s Look Really Cool (via Gizmodo). 

I like the fact that a problem - Apple inefficiency - has been translated into an opportunity. As the iPhone 5 max customization you can get is the choice between two colors, the engraving would make your phone really unique and different. I remember I ordered my first iPod Nano with the engraving
Dreams change the world - Paolo Ciccarese
That made my iPod Nano unique until it has been recalled by Apple some years later and exchanged for a new anonymous Nano that I basically never used. I feel the iPhone 5 engraving potential is going to make a difference in the 'think different' iWorld.


Friday, September 28, 2012

New Apple maps and Cook's iSorry

It is well known that maps are one of the most useful features of smartphones. I still see a very good amount of unexploited potential in maps. And I believe this is also the reason why Apple decided to develop a version of their own.

But I am surprised to see Apple delivering the new products with such poor and buggy maps. I not surprised to read Cook's official apologies. I am a little surprised by Cook recommending, in the same letter, to use competitors product. I would have expected a link to a different page listing alternatives.

I am sure Apple had very good reasons to deliver the phone in September even if map were clearly not ready. As I am assuming they knew the new maps were not classic Apple-quality, I cannot stop wondering if this would have happened with Jobs in charge.

Anyhow, customers are always lining up for iPhones and I am sure Apple will fix and work on the maps to make them amazing. Still, I find what happened very Apple-unusual… and I guess Cook felt it too if he delivered the official Apple iSorry.

Meanwhile - maybe also because of the new potential competitor? - Google keeps improving Google Maps:
- Google Maps, Now With More High-Res Satellite And 45° Aerial Imagery
- Google Maps Goes Diving, Provides “Seaview” Of Great Barrier Reef, Hawaii and Philippines
- Google Brings Its Indoor Maps To France

Wednesday, May 09, 2012

Running GWT 2.4.0 with STS 2.9.1 and Grails 2.0.3

Alright, if you followed all the steps of the previous post, you should be able to see the results of the GWT code execution at the address:
http://localhost:8080/{projectname}/hello.gsp 
As you might have noticed, I previously asked the plugin to compile the GWT code (compile-gwt-modules). That operation takes some seconds as the entire artifact is recompiled (when the application will grow, the compilation can last minutes).  Luckily there is an alternative, the hosted mode. When an application is running in hosted mode, the Java Virtual Machine (JVM) is actually executing the application code as compiled Java bytecode, using GWT plumbing to automate an embedded browser window. This means (1) we don't need to recompile the code as STS is producing the Java bytecode for us incrementally (2) the debugging facilities of your IDE are available to debug both your client-side GWT code and any server-side Java code as well.

First we start the grails application (run-app), second, in the command prompt we type:
run-gwt-client
This last command starts the hosted mode and you should see appearing a window like the one depicted in figure 1. 

Figure 1: hosted mode window.

Now we can 'copy to clipboard' and open that link in a web browser:
http://localhost:8080/GwtTest/hello.gsp?gwt.codesvr=127.0.0.1:9997
The page should appear in the window and the alert 'hello' should display. Now you can verify the usefulness of the hosted mode by updating the alert - in the class HelloApp.java from 'hello' to 'hello me' - and reloading the page. The alert will display the new string without you having to trigger the GWT code compilation manually. And this will result in a huge save of time. (Read more)

Note. Remember that the manual compilation is still necessary prior to deployment as the deployed version of the page will run the compiled JavaScript.


Friday, May 04, 2012

Setting up STS 2.9.1, Grails 2.0.3 and GWT 2.4.0

If you need to integrate Grails and Google Web Toolkit (GWT) here is a list of tips. If you are interested in Grails you might want to consider the SpringSource Tool Suite or briefly STS. I usually install the STS package in a directory which name includes the version of the STS software to make sure multiple versions of the tool can beautifully coexist on the same machine. The tool is currently in version 2.9.1 and, as the previous versions of STS, it offers a good set of features for integrating with Grails. After the installation is completed I suggest to open the Dashboard and select the tab "Extensions". If you have just installed the tool, it should look more or less like in figure 1.

Figure 1: STS 2.9.1 Dashboard right after installation.

As you can easily verify in figure1, I would suggest to pick two extensions in particular: Grails Support and Google Plugin for Eclipse - which now comes with GWT 2.4.0. Select those and proceed with the installation. I don't usually pick the "Grails (current production release)" as I usually download and install Grails separately. The current release version of Grails is 2.0.3 and you should download it and unzip it in a convenient location.

Figure 2: Setting up Grails in STS.

Once the installation is terminated, it is time to configure the plugins. The Grails Support plugin needs to know where the Grails installation is (figure 2). We can now create a new Grails project that I am going to name GwtTest.

Figure 3: Creating a new Grails project in STS 

The creation process should ask you if you want to change the perspective into the Grails perspective offered by STS. Once the project is created it is time to install the GWT Plugin for Grails.

Figure 4: Opening the Grails command prompt

You can perform this operation through the Grails command prompt offered by STS (figure 4) by typing
install-plugin gwt
And the process should complete displaying the details in the console:

Figure 5: Console after installation of the GWT plugin (0.6.1) for Grails
 
Note: Remember also to set up the GWT_HOME that is used for compilation.

We are now ready to create our first GWT module (learn about GWT modules here). Using once again the Grails command prompt offered by STS, we type:
create-gwt-module org.example.HelloApp
Once the process is completed, if you refresh the project, you will be able to notice that a new directory 'src' has appeared in the project explorer.

Figure 6: Project explorer and Console after the creation of the HelloApp GWT module

In order to declare this folder as a source code folder we can right click on the project and select 'Build Path'>'Configure Build Path' dialog. In the tab 'source' we select 'add folder' and we pick the newly created 'src/gwt' folder.

Figure 7: Declaring the GWT folder as a source code folder

We can now create the page hosting the GWT script by typing in the command prompt:
  create-gwt-page hello.gsp org.example.HelloApp
The new page will include the line of code that is performing the actual import of the GWT artifact:
<script src="${resource(dir:'gwt/org.example.HelloApp',
 file:'org.example.HelloApp.nocache.js')}" type="text/javascript">
</script>

We are now going to modify the HelloApp.java file adding Window.alert("hello"); within the method onModuleLoad() so that when the script is loading the alert 'hello' will fire.

We then compile the GWT code by typing in the command prompt:
compile-gwt-modules
And we are potentially ready to go. After running the Grails project - a simple run-app is good enough - and opening the page:
http://localhost:8080/{projectname}/hello.gsp
you will notice that nothing happens. As a matter of fact, if you check out what happens with Firebugs, you will notice that a resource has not been found. Unfortunately, it seems the Grails Resources Plugin, which is installed by default in the project, is not compatible with the Grails GWT Plugin. As suggested in this post we can modify the Config.groovy file to include:
grails.resources.adhoc.excludes = ['**/gwt/**']
When restarting the server, the hello.gsp page should now work and fire the 'hello' alert.