Thursday 15 August 2013

Thread safe Java DateFormat

Not that the JDK documentation doesn't say it clearly: "Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally."
Nevertheless there are still programmers who seem to forget this fact when using date formats in their web applications, and you can count me among this sloppy bunch - so very expected from a Oracle Certified Java Professional!

It is common practice to declare utility objects as public class variables or even constants so that they can be used globally in our application, but we can't do that with Date formats if our application is multi-threaded, as most enterprise applications are. Only three options left:
  • Create an instance of DateFormat every time we need it, even if we know that instantiation is an expensive process.
  • Synchronize our calls to DateFormat methods.
  • Use ThreadLocal if your application server uses a thread pool.
There's a good experiment about these three methods in this article. It's worth reading.

But there's one more way of getting out of this trap: use FastDateFormat from apache commons-lang library. It is, as its name suggest, fast and - more important - thread safe, so we can use it just the way we want to use this kind of classes: instantiate it once and use it everywhere.
Well, Alfresco - my favorite playground - happens to include commons-lang.jar in its distribution, so I'm going to show an example of how to use FastDateFormat in Alfresco.

First we define a few date format java beans:
<bean id="dateFormat1" class="org.apache.commons.lang.time.FastDateFormat"
  factory-method="getInstance">
 <constructor-arg value="dd/MM/yyyy"/>
</bean>

<bean id="dateFormat2" class="org.apache.commons.lang.time.FastDateFormat"
  factory-method="getInstance">
 <constructor-arg value="dd/MM/yy"/>
</bean>
We take advantage of the static createInstance method and use it as bean factory method.

We could inject directly one of these date formats into any bean that requires it, or we can bundle them into a factory bean, as below:
<util:map id="dateFormats">
 <entry key="dd/MM/yyyy" value-ref="dateFormat1" />
 <entry key="dd/MM/yy" value-ref="dateFormat2" />
</util:map>

<bean id="dateFormatFactory"
  class="ie.paco.alfresco.util.impl.DateFormatFactory">
 <property name="formats" ref="dateFormats" />
</bean>
DateFormatFactory encapsulates a Map of DateFormats, any of which may be retrieved by invoking getFormat(String key):
package ie.paco.alfresco.util;
import java.text.Format;

public interface FormatFactory {
 public Format getFormat(String key);
}
package ie.paco.alfresco.util.impl;
import java.text.Format;
import java.util.Map;
import ie.paco.alfresco.util.FormatFactory;

public class DateFormatFactory implements FormatFactory {
 
 private Map formats;

 @Override
 public Format getFormat(String key) {
  return formats.get(key);
 }

 public Map getFormats() {
  return formats;
 }

 public void setFormats(Map formats) {
  this.formats = formats;
 }

}
And last, make some client code for our new date formats, for example a PropertyDecorator:
...
public class DatePropertyDecorator extends BasePropertyDecorator {
 
 private FormatFactory formatFactory;

 @SuppressWarnings("unchecked")
 @Override
 public JSONAware decorate(QName propertyName, NodeRef nodeRef, Serializable value) {
        JSONObject map = new JSONObject();
        Format dateFormat = formatFactory.getFormat("dd/MM/yy");
        String formatted = dateFormat.format(value);
        map.put("raw", value.toString());
        map.put("formatted", formatted);
  return map;
 }

 public FormatFactory getFormatFactory() {
  return formatFactory;
 }

 public void setFormatFactory(FormatFactory formatFactory) {
  this.formatFactory = formatFactory;
 }
}
This property decorator is meant to be used on date properties. It will output both the raw String value of the date and its formatted value. Its bean definition follows
<bean id="datePropertiesDecorator" parent="baseDecorator" class="ie.paco.alfresco.repo.jscript.app.DatePropertyDecorator">
 <property name="formatFactory" ref="dateFormatFactory"/>
 <property name="propertyNames">
  <set>
   <value>cm:created</value>
   <value>cm:modified</value>
   <value>cm:accessed</value>
  </set>
 </property>
</bean>

The decorator will modify the output of the properties cm:created, cm:modifed and cm:accessed. So when we go to the document library the doclist webscript will return something like this:


We just need a Share extention to exploit this decorator. But that will be the subject of another post.
And remember; when it comes to formatting dates, FastDateFormat is your man.

You can get the code of this tutorial from here.

The Free Verse

This section has nothing to do with technology.

Just a reading recommendation. Two classics from the twentieth century:

Harper Lee. To Kill a Mockingbird

and

Friedrich Hayek. The Road to Serfdom

Saturday 9 February 2013

Portlets and JSF

This is the continuation of my previous post Portals, Portlets and Alfresco, but this time the focus is on the portlet itself and JSF.
You recall that our previous exercise simply calls an Alfresco webscript and retrieves the list of user groups registered in Alfresco.
Well, now we will extend the portlet to make it get and display the subgroups and users contained in any group, just by clicking on its name. So, we're going to trigger from the view an action on the backing bean which, as a result, will call again an Alfresco webscript.
But this post is not about Alfresco. While extendind the portlet we're going to refactor it to make it look like a well done application.
In particular we're going to
  • Make use of resource bundles. The base of Internationalisation.
  • Apply OO principles to the design of Java classes.
  • Exploit Dependency Injection in managed beans and managed properties.
  • Add unit testing.
Lots to do. So let's get on with it.
First, get the code here.

JSF and Resource Bundles

Properties files have been aroung for some time now, haven't they? And we all know how to load them from Java code.
In JSF we can expose resource bundles and make them available to the view, too. We simply need to declare it in our faces-config.xml file:

 
  alfresco
  bundle
 

This declaration means that we have a file named alfresco.properties right at the root of our application classpath, and it is available in EL Expressions under the name of bundle. So our view can read the properties as follows.
<h:outputText value="#{bundle['alfresco.allgroups.title']}" />
or, if the property requires parameters...
# A property expecting a parameter
alfresco.children.title=Content of Group {0}
...call and pass the parameter...
<h:outputFormat value="#{bundle['alfresco.children.title']}">
 
</h:outputFormat>
...and get the result...

OO Principles

By all means the most interesting feature of this second release of our exercise is the attempt, successful I think, to apply OO principles to the design of Java classes.
In the first release we had a single bean who cared about everything. Now we're going to separate different concerns of the application in different artefacts.
We have already started by moving labels and URL strings to the alfresco.properties file. Next step is to redesign GroupsBean.java to make it what it is supposed to be: a backing bean for the view, and nothing else.
The first version of the bean did everything. Not that it had much to do, just a single http request, but only this forces the bean to instatiate an http client, make a connection, and get the results.
Since we're going to need now one more http request it is all the more clear that it would be better to have a different object to deal with this.
And that's what we're going to build. Another class, Requestor, will take care of the http stuff. We even make use of another OO principle: "Program to interfaces"; so we make Requestor an interface and that's the only thing that our bean needs to know.
The analysis is quite simple:


The actual Requestor implementation is going to be injected by means of the JSF Inversion of Control mechanism, as explained in the next section. But first let's have a look at its design:



As you can see, we have factored out the creation of the GetMethod object in another class (represented by the interface FactoryService). It is always good practice to avoid calling constructors from your code; classes that instantiate objects in their methods are harder to unit-test. (More about this in the Unit Test section below).

Dependency Injection

Inversion of Control (IoC) is the final touch of Object Oriented Programming. It realises the dream of "Program to Interfaces and don't let your classes know about the concrete implementations of their collaborators".
Our bean GroupsBean requires a Requestor to perform the call to Alfresco, but we say nowhere in the java code which concrete class will do the job, we let the portlet container tell the bean which collaborator to use.
As you well know, or can guess, this dependency injection happens in faces-config.xml:


 factoryService
 ie.paco.alfresco_portlet.service.impl.FactoryServiceImpl
 application


 httpClient
 org.apache.commons.httpclient.HttpClient
 application


 requestor
 ie.paco.alfresco_portlet.http.impl.RequestorImpl
 application
 
  factoryService
  #{factoryService}
 
 
  client
  #{httpClient}
 

In the snippet avove, see how we tell the container to instantiate a FactoryServiceImpl and an HttpClient with application scope. Then we define also the RequestorImpl, and we inject in its properties 'requestor' and 'factoryService' the objects mentiones before. For this mechanism to work two things must be true:
  • The injected objects must be assignable to their corresponding properties.
  • The bean receiving the objects must have appropriate setter methods.
Finally we define our GroupsBean as follows:


 groupsBean
 ie.paco.alfresco_portlet.GroupsBean
 view
 
  requestor
  #{requestor}
 

Nice, isn't it?
You have probably seen in faces-config.xml and in the java code that I have also implemented a DummyRequestor, which comes handy if I want to test some feature of the application that doesn't require the HTTP call. Do you see how easy is it to switch from one requestor to the other? Just a little change in the config file.

Unit Test

Another benefit of applying OO Principles in our design is that we can easily develop unit tests for our classes, their methods being small and having one well-defined goal.
Dependencies are declared as interfaces, so we can mock them in our tests; we don't have to worry about the behaviour of the concrete implementations, their own unit tests will do that.
JUnit is the standard for Java unit testing. For mocking objects there are several libraries. Since I'm using at work EasyMock and PowerMock, I wanted to try in this exercise Mockito; and I tell you one thing: I like it!

The Free Verse

This section has nothing to do with technology.

The Iron Cross

It is always risky to tell a joke.
Before shooting one out you have to be certain that it's going to be a success, or people may end up laughing at you, or not laughing at all.
You evaluate your audience: are they close friends, family, colleagues? You evaluate the circumstances: you're in a pub, in the office kitchenette, at home; maybe someone has already started... You even evaluate what you're going to tell: is it funny, is it appropriate?
Appropriateness is the main issue. Jokes tend to twist serious matters into ridiculous positions and make them appear... well, ridiculous, unimportant; but people may not buy it. Most of the times the subject matter of the story is just too serious to be funny, or its characters or their deeds are just too bad, or the story is a mere display of bad taste. In any case, the first words of a joke should set clearly on which grounds it stands, as if they were saying "hey, listen to this silly story, but leave your analysis skills for your geek work, and please set your morals in Anglo-Irish-Bank mode."
So, one unfortunate night, I told this one
"This is Adolf Hitler knocking on heavens door..."
Well, that was a start, wasn't it?
After these eight words the story gets more involved, introduces more characters of the top kind, VIPs, if you know what I mean. Line after line the situation becomes ever more hilarious, until, at its climax, the story ends in a big roar of extreme irreverence. Fabulous.
And yet, it failed. I failed.
Why? Because my audience didn't know what the Iron Cross was.

Iron Cross 2nd Class. (www.marksmedals.com)

The most notorious German military award.
It is historically impressive, and its aesthetics makes it unique. So sober in design: a black cross on a silver plate. The ribbon doesn't sport any vivid colour; black and white, that's all. And the medal, almost as dull as the ribbon, stays away from flashiness, ostentation and the effeminate glow of gold. Simply beautiful.
Now you know.

Sunday 16 December 2012

Portals, Portlets and Alfresco


Portlets are self-contained web applications that are meant to be deployed in portals or, to be more precise, portlet containers.
All major application server vendors have extended their products with a portlet container, and the open-source world provides us with some implementations, too. To mention a few, we have Jetspeed, GateIn, Liferay...
In theory portlets should be able to deploy in any portlet container, but in practice we're developing portlets having in mind the concrete portal implementation we're working with. Often we need to add to our portlets some vendor-specific config files that make them integrate nicely in that particular portal and, as a side effect, make them useless for any other.
In this little example I have stuck to the portlet specification, kept the code portal-free and let the container inject whatever the portlet needs to run in it. And it works, at least in GateIn, my chosen portal. Later I will try to drop it in Liferay and see what happens; I'll let you know the results in another post.

Let's build a portlet that calls an Alfresco webscript to pull some data, and displays the results.

Alfresco

First we need an instance of Alfresco up and running. If you don't have it yet, download the latest community edition from here and install it. The default settings will almost do for our purposes, you don't even need to create a site for this example to work.
The only configuration items we need to change are the authentication settings since we need to ensure that Alfresco accepts remote calls. We achieve this by enabling external authentication. Edit alfresco-global.properties (in $ALFRESCO_HOME/tomcat/shared/classes) to include the following:

authentication.chain=external1:external,alfrescoNtlm1:alfrescoNtlm
external.authentication.enabled=true
external.authentication.proxyUserName=

If you have already an authentication.chain setup you only need to add external1:external to your current value. Note also that we have intentionally left empty the proxyUserName; this tells the external authentication subsystem that the user accessing Alfresco is the one specified in a header parameter in the remote request, as you will see when we develop the portlet. For more details about external authentication parameters see Alfresco docs.

Portlet

Now let's make this portlet. I have already mentioned GateIn, but there are some more pieces in this little demo. Let me show you the techonology stack we're going to work on:
  • Eclipse IDE.
  • Maven. Let the experts do the build.
  • commons-httpclient. We're going to call an Alfresco webscript via HTTP, remember?
  • Jackson. The webscript returns JSON, and Jackson parses JSON like hell.
  • JSF. Why not? It's the technology I'm using at work right now.
  • GateIn. It comes bundled either with Tomcat or JBoss. Take JBoss, which can talk JSF without the need of any additional libraries.

GateIn installation

You only need to be careful with the ports if you are running Alfresco and GateIn on the same machine. If that's the case, edit the files standalone.xml (there are several) in $GATEIN_HOME/standalone/configuration to change the port numbers. Alternatively you can change Alfresco settings in $ALFRESCO_HOME/tomcat/conf/server.xml.
To launch GeteIn execute standalone.sh (or .bat if you're on Windows) from $GATEIN_HOME/bin.
When you have your portlet ready just drop the .war file into $GATEIN_HOME/standalone/deployments and it will autodeploy.

Maven

As always, it is easy to build a portlet project with Maven. We have a maven-archetype-portlet to get us started. It generates, along with the folder structure that we need, some Jetspeed-specific folders and files that you can simply remove since they're not needed in our example.
If you don't want to get involved in maven archetypes (shame on you), just grab my code from here.
Liferay provides some portlet archetypes, too. Even one for JSF!

Portlet construction

My portlet is very simple. It just calls an Alfresco webscript that returns the list of user groups in JSON format, and then the view displays the list. The webscript I'm calling is /alfresco/wcservice/api/groups.

Portlet descriptor

Let's say that a portlet is a portlet because it has a portlet.xml file.
The maven-archetype-portlet generates a sample descriptor for us; we just have to use it as a template to make the one we need. This is the important bit in mine:
javax.portlet.faces.GenericFacesPortlet

 javax.portlet.faces.defaultViewId.view
 /xhtml/groups.xhtml

There's no much to explain. The portlet class is not ours, the container provides it. On the other hand, the view is something we must implement, as you may expect.

Faces config

faces-config.xml is not generated by maven-archetype-portlet.
In my example, it only declares a managed bean: the backing bean for the view.

 groupsBean
 ie.paco.alfresco_portlet.GroupsBean
 view

Backing bean

GroupsBean.java is the bean linked to the view file groups.xhtml.
It doesn't do anything really especial. Just calls Alfresco webscript and transforms the JSON response into a Java Map, which is then stored in a field called groups.
private static final String ALFRESCO_GROUPS_URL = "http://192.168.145.166:8080/alfresco/wcservice/api/groups";

private Map<String, Object> groups = null;

public GroupsBean() {
 HttpClient client = new HttpClient();
 GetMethod method = new GetMethod(ALFRESCO_GROUPS_URL);
 method.addRequestHeader("X-Alfresco-Remote-User", "admin");
 try {
  // Execute the method.
  int statusCode = client.executeMethod(method);

  if (statusCode != HttpStatus.SC_OK) {
    LOGGER.error("Method failed: " + method.getStatusLine());
  }

  // Read the response body.
  String response = method.getResponseBodyAsString();

  // Deal with the response.
  LOGGER.debug(response);
  ObjectMapper mapper = new ObjectMapper();
  groups = mapper.readValue(response, new TypeReference<Map<String, Object>>(){});

   } catch (HttpException e) {
  LOGGER.error("Fatal protocol violation:", e);
   } catch (IOException e) {
  LOGGER.error("Fatal transport error:", e);
   } finally {
  // Release the connection.
  method.releaseConnection();
   }  
}

Note that the webscript URL is hard-coded in a constant. You need to edit that to make it work in your environment.
Note also how the user is passed in the request header. You may need to edit that line, too, if your Alfresco username is different.
The JSON response from the webscript is going to be something like this:
{
 "data": [
  {
     "authorityType": "GROUP",
     "shortName": "ALFRESCO_ADMINISTRATORS",
     "fullName": "GROUP_ALFRESCO_ADMINISTRATORS",
     "displayName": "ALFRESCO_ADMINISTRATORS",
     "url": "/api/groups/ALFRESCO_ADMINISTRATORS"
  },
  {
     "authorityType": "GROUP",
     "shortName": "EMAIL_CONTRIBUTORS",
     "fullName": "GROUP_EMAIL_CONTRIBUTORS",
     "displayName": "EMAIL_CONTRIBUTORS",
     "url": "/api/groups/EMAIL_CONTRIBUTORS"
  }
 ]
}
So the groups Map in the backing been is going to end up with a single entry with key "data" and a list of group objects as value. The group objects are going to be also Maps.

The view

You can't get it any simpler:

 

Alfresco User Groups

It iterates over the list of groups in the backing bean and outputs their property "shortName".
This is what my portlet looks like in a GateIn page:

Source code

You can get the source code from here.

 What's next?

Well, this one has been sooooo simple, hasn't it? I'm sure you're missing some action.
So now that we're not scared of portals, portlets and Alfresco, let's enable some clicking on this portlet and make things happen. I will share my work in the next post.

The blank verse

Remember that this section has nothing to do whith technology or consulting. Anyway, this conversation may be of interest:

"It's hard to find a decent room in Castleknock, Fergal. It seems that everybody wants to live there. Offers last just minutes; everytime I call, the room is gone. Browsing the ads in daft.ie is a hard work, and sometimes the unexpectedness strikes you."

"the unexpectedness! Your English, Pepe."

"Yeah, I know. My English...
"Listen to this one I found yesterday, for example: '... single female in her thirties offers a room to let in... blah blah blah Castleknock. More than a lodger I'm looking for someone who wants to relax and feel at home... blah blah blah...'
"...Intriguing".

"Is that room gone, too?"

"I don't know, but that room is out of question. It seems to me that just by answering this ad I would commit myself to no less than... being happy. That's big deal. An exhausting task."

"I think you're reading the message the wrong way, Pepe"

"I've read and re-read 'the message', as you say, several times and thought about it for hours trying to find different interpretations."

"Don't tell me you always arrive to the same conclusion."

"Not the same, but alike. They range from 'nightmare' to 'hell'".

Fergal chuckles. "How's that?"

"Listen, it's very simple." Pepe takes his lecture tone "That room is not my room. That house is not my house. That's not my home. I don't want to feel at home, I don't want to feel comfortable, I don't want to be nice, and I'm ready to pay for not having to."

"So you finally admit it. You are antisocial."

"What's wrong with being antisocial?"

"Well, that question is wrong, too."

"Anyway, that's not all. Listen to this: 'I'm clean and tidy but not over the top.'"

"That's the same lady?"

"That's her. Same lady, same ad.
"What the heck does she mean?"

"What do you think she means, Pepe?"

"I don't know what she means, I'm asking you. But I do know what those words mean: 'she - is - dirty.'"

"For God's sake, Pepe. She's not saying that. She's clean although not to the highest degree."

"Highest degree? There's only one degree of cleanness and many degrees of dirtiness, everybody knows that."

"That's a sophism."

"No, it's true. Listen, Fergal, what would you think of me if I said 'I'm honest but not over the top.'?"

"That's different."

"Because you say so."

Wednesday 23 May 2012

ECMAScript

ECMAScript

From time to time I find some JavaScript code that is not completely correct. “Not completely” in the sense that you can tell what the program is intended to do and you can see that it's doing it right, but only under certain conditions, having the programmer left the door open for malfunction to happen.

The main reason – if not the only – of such mistakes is the fact that the programmer has written the code thinking in another language, namely Java. The unfortunate choice of name for JavaScript has led many to the erroneous belief that the two languages are closely related and, as a consequence, Java programmers have been “automatically” considered JavaScript programmers. This misconception won recruiters first and it spread so successfully that soon Java developers started to believe it themselves. Then many Java developers got frustrated with their poor performance in JavaScript (so many things just didn’t work the way they expected) and the line “I hate JavaScript” became a commonplace among us.

This is only half the story. The other half, the good one, is that JavaScript is a dialect of ECMAScript, a full-fledged scripting language with some powerful features, like prototypes and weak typing, not to be found in Java, and some others common to both languages but different in syntax and/or semantics. We must accept this: ECMAScritps is a different language; and where do we turn to when we face a different language? Its specification!

A quick look at the spec index should suffice to convince you that we’re dealing with something original and separate from other languages. There are many features that demonstrate this originality, but in this post I’m going to focus on the equality operator (==), the most popular false friend to Java programmers.


== vs ===

ECMAScript defines two equality operators. The Strict Equals Operator (===) works much as the Java ==. The non-strict operator (==), on the contrary, performs some basic transformation on operands of different types before evaluating the comparison, so it may yield surprising results if you’re not familiar with those transformations.

The full description of this operator can be found in chapter 11.9.3 of the spec, The Abstract Equality Comparison Algorithm, but the interesting points can be summarized as follows:
  • undefined == null yields true.
var a;
var b = null;
console.log('type of a: ' + typeof(a));
console.log('type of b: ' + typeof(b));
console.log('a == b >>> ' + (a == b));

/*
Output:
type of a: undefined
type of b: object
a == b >>> true
*/
  • If one operand is a number and the other one is a string, the string is coerced into a number before comparison is made.
var a = "2";
var b = "3";
var c = 3;
console.log('type of a: ' + typeof(a));
console.log('type of b: ' + typeof(b));
console.log('type of c: ' + typeof(c));
console.log('a == c >>> ' + (a == c));
console.log('b == c >>> ' + (b == c));


Output:
type of a: string
type of b: string
type of c: number
a == c >>> false
b == c >>> true

  • If one operand is a Boolean and the other is not, the Boolean is converted to number before == is applied.
var a = "1";
var b = "3";
var c = false;
var d = true;
console.log('type of a: ' + typeof(a));
console.log('type of b: ' + typeof(b));
console.log('type of c: ' + typeof(c));
console.log('type of d: ' + typeof(d));
console.log('a == c >>> ' + (a == c));
console.log('b == c >>> ' + (b == c));
console.log('a == d >>> ' + (a == d));
console.log('b == d >>> ' + (b == d));


Output:
type of a: string
type of b: string
type of c: boolean
type of d: boolean
a == c >>> false
b == c >>> false
a == d >>> true
b == d >>> false

  • If one operand is an object and the other one is a string or a number, the object is converted to primitive and then the comparison takes place. The conversion object-to-primitive is object-dependent and it relies on one of the methods toString() and valueOf(); the details are explained here, but my advice is don’t evaluate objectA == aString nor objectA == aNumber.

The if statement

if (expression) statement
This is closely related to the equality operator, but there’s something more. expression can be anything and it will be evaluated to a Boolean according to the rules that you can find in the specification, chapters 12.5 The if Statement and 9.2 ToBoolean.
It is very common to write code like
if(document.getElementById(“foo”)) {...}
to check whether a DOM element exists in an HTML document. This is fine because we know that getElementById() will return either an object or null. In the first case the expression evaluates to true and in the other case to false.
But we need to be very careful with the if statement if we’re applying it to objects other than HTML documents. The results can be surprizing:

var a =
{
    prop1: 0,
    prop2: "0",
    prop3: {k: 0}
};
console.log('type of a: ' + typeof(a));
if (a.prop1) {
    console.log('a.prop1 evaluates to true')
} else {
    console.log('a.prop1 evaluates to false')
}
if (a.prop2) {
    console.log('a.prop2 evaluates to true')
} else {
    console.log('a.prop2 evaluates to false')
}
if (a.prop3) {
    console.log('a.prop3 evaluates to true')
} else {
    console.log('a.prop3 evaluates to false')
}

Output:
type of a: object
a.prop1 evaluates to false
a.prop2 evaluates to true
a.prop3 evaluates to true

The bottom line

Traditionally JavaScript has been used almost exclusively for scripting web pages so some of its particularities (like the two discussed above) have been under control thanks to the nature of the objects it manipulates (the DOM). But today it is becoming more and more a general-purpose scripting language driven by
  • the development of powerful JavaScript APIs (YUI, JQuery) that exploit the full potential of the language.
  • The advent of Rhino, a Java implementation of ECMAScript that has pushed the language into the server side.
Now it is essential to be aware of the language peculiarities – refer always to its specification – especially when coding server-side JavaScript, when it is just too easy to think that JavaScript is kind of Java.

The blank verse

Now chaps, this section has nothing to do with the subject of this post. I will drop here anything coming to my mind that I want to share. Sometimes it will be something completely off the wall, but not today.

In this first post I want to recommend a reading: Vargas Llosa’s The Dream of the Celt.
Vargas Llosa won 2010 Nobel Prize of Literature and, at the same time, he published this novel. This happened just a few weeks after my coming to Ireland and it was a nice coincidence that one of my favourite writers delivered a book with such sharp Irish tones among so many colours.
A less concise, more factual review can be found here. Enjoy.