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.