Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts

Sunday, July 18, 2010

Java LDAP SDK for SyncRepl replication showcase

I just published a post on my company blog about how to implement a SyncRepl client using two different Java LDAP SDK, Apache DS and UnboundID: 


http://blog.normation.com/2010/07/18/java-ldap-sdk-for-syncrepl-replication-showcase/

SyncRepl is a replication protocol for LDAP, normalized in RFC 4533.  

The demonstration is done with a showcase web application that display in real time modification done in an LDAP server. 
The application, named Syweno, was developed in Scala, thanks to Liftweb and it's amazing Comet. It looks like:



Of course, update are synchronized thank to SyncRepl, and are propagated to the web page in real time thanks to Comet updates. 

The code source is available on github here: http://github.com/fanf/syweno

Enjoy !

Thursday, July 1, 2010

Scala dreaded underscore @ PSUG

(orignal content from http://blog.normation.com/2010/07/01/scala-dreaded-underscore-psug  )

On the evening of June 30th 2010, the Paris Scala User Group organized its second event.
This time, there were two presentations:

  • in the first one, Alexis Agahi, our kind user group leader, made a feedback after one year of scala experience. It’s available here.
  • the second one was given by your servitor, and deals with each and every use case of underscores in the Scala language – I hope I didn’t miss any.
    It’s available here.
See you next time on PSUG!

Monday, April 19, 2010

Summary of my Scala Days 2010

A great reception...

I had the immense luck to go to the First ScalaDays event organized by EPFL in Lausanne on 15/16 of April 2010.

It was an immense luck, because the event was simply fabulous. And so, to begin, I really want to thanks the Scala team, and especially Antonio Cunei for their amazing work of organization: the welcome with the little kit with the little goodies and T-Shirt was a nice introduction, the food was really good, the boat trip and dinner on first day evening a really top-level dinner.
Safe for a volcanic eruption in Iceland which disrupted flights all around Europe and so impacted a lot of attendees, it could have been near perfection.

... with great talks ...

And that is just for the organization: presentations were at the same level. Most of them were really good, and the choice between two sessions not always easy. Fortunately, presentation were recorded, and so should soon become available in line (I listed presentation I went to at the end). One little reproach: some of them would have deserve more time than allowed here, but that is near to nothing.

Akka presentation was somehow special. Jonas Boner and the Akka team did an amazing work in no more than a year, from “just an other actor implementation” to a full feature actor framework à la Erlang OTP, with actor supervision and management, persistent data structures, distribution, Software Transactional Memory (STM) integration, and all of that under the common umbrella of actor paradigm. 
To me, Akka is more and more looking like the Killer App for Scala, a middle layer framework which will be more or less in all Scala applications in a near future, a little like Spring is for the Java world. It brings so much power with so little boilerplate... So, if you don't know Akka, just go looking for it right now.

... and a bright future in sight for Scala

All along the event, there was a felling of “taking part of the starting point of something great”, perhaps a little like what were firsts Java one. Perhaps it was partly du to the fact that meeting about 155 Scala enthusiasts from Europe, US, Japan, Australia and so on was a great moment - it was really good to finally put faces on mailing lists and IRC names (hello Miles, Josh, Timothy and all the others !).
But I believe that it was more than just that. Today, I'm pretty confident that Scala is here to stay and growth.

The most "symptomatic" announcement of that evolution of the language organization from the research sphere to a broader audience is the announcement that a Scala Foundation will be created to manage it. 


So, that was a really wonderful event, and long life to Scala !

Ho – and I get my “Programming in Scala” dedicated by Martin, it's the little thing that is making that event even more special to me :)


Presentations seen

So, that's the list of presentations I attended, with a (really) brief description of them. Video of talks should me made available in a near future.

April, 15

15 morning - opening talk
A cool Opening Talk by Martin Odersky, focused on all the goodness brought by Scala 2.8, how it evolves from "just a little refactoring of Collection API" to a "3.0 without the name". Great.


15, morning


PEGEX by Kota Mizushima
or how to have combinator parser which looks like regexp. Interesting project, but a I think a little young for now... Keep an eye on it.

Scala Parallel collections by Aleksander Prokopec
Presentation of parallel collections arriving in Scala 2.8.1... It seems that it will be really great stuff, with good integration in existing collection API.


Developing the Scala bindings to the Fly Object Space by Channing Walton, Nigel Warren, Simon Kent
I miss a part of the beginning, but for what I saw,  Fly Object Space seems to be a powerful framework for distributed computing. 


15, afternoon, part 1

CCSTM: A library based STM for Scala by Nathan Bronson, Hasaan Chafi, Kunle Olukotun
A talk about what  Software Transactional Memory (STM) implementation can be achieve with Scala from an ideal STM, really nice stuff – STM seems to be a hot topic, it is cool that what is one of the most interesting feature of Clojure is winning interest in Scala.

Lightweight language support for type-based, concurrent event processing by Phillip Hadler
Really nice technical presentation about how type information can leads to massive performance optimization in pattern matching.

Named and default argument in Scala by Luka Rytz
To me, this feature is one of the best of Scala 2.8. It was nice to see how the implementation was done.


15, afternoon, part 2

Specialization in Scala by Iulian Dragos
Specialization finally comes to Scala 2.8 ! For the first time, Scala has the opportunity to be able to do things faster than Java, namely automatically specializing method to native JVM type to remove unnecessary boxing/unboxing logic. Great stuff, even if it's just a beginning.

Leaky Monads – an experiment with automatic resources management by Josh Suereth
Or how to cleanly manage resources in Scala with a little bit of monad, but only when we need them.
Great presentation by Josh, with a lot of “déjà vu” feeling for me – most of the problem he talk about and the solution he found was alike whose I encountered when I did my monadic resource management of LDAP connections.

Type-safe SQL embedded in Scala by Christoph Wulfz
Cool stuff to make SQL a first class citizen in Scala, as XML is.

April, 16

The next day seems to have again raise the level of the event. For me, it was a fabulous set of presentations. All were really top level one, and all subjects were great - well, or at least, I was the perfect target for them :)

16, morning keynotes

A really interesting keynote by Kunle Olukotun, the man behind the heavily-multi-core Niagara processor. He shows how to deeply embed polymorphic DSL in Scala, and it was kind of amazing. The Parallel and concurrent future seems to be bright in Scala world.

16, morning

Scala @ Linkedin : distributed computed with Norbert by Chris Conrad
Really cool to see what Linkedin did with Scala, and their scaling and distribution problem are really nice ones (in the way a hard maths theorem is nice to prove ;).

Akka: Simpler scalabitity, fault-tolerance, concurrency & remoting throught actors by Jonas Boner, Victor Klang
As I already said, Akka is more and more looking like the killer app on Scala. Kudo to Jonas ans Akka team.

Scala IDE for Eclipse : retrospect and prospect for 2.8 by Miles Sabin
After years of purgatory (for users ;), Scala Eclipse IDE seems to finally be interesting again, thanks to Miles and all the hard work. A really bad point for Eclipse foundation and its autism regarding JDT evolution.

16, afternoon, part 1

sbt: design and implementation by Mark Harrah
SBT, the build system that will save all of us from Maven – thanks Mark, and congrats for the work

Scala Modules: a Scala DSL to ease OSGi development by Heiko Seeberger
A “small” library to make OSGi use more user-friendly, and a lot of interest toward it. Sometime, syntax and cleanness IS important (subliminal message to all Java coders who don't see the problems with Java boilerplate)

Sneaking Scala into your organization by David Copeland
Even if I don't have that problem – in my company of four people, all the two developers are Scala experts ;), the talk was really interesting and well thought. Hope that a lot of people will follow these advices :)

16, afternoon, part 2


Their was no presentation in the last afternoon, but a workshop in which attendees were able to summarize their thought about Scala - what is missing, what has to be done, etc. Unfortunately, I had to leave before than the restitution was done, and missed it. So, for that, I'm like all of you: waiting for blog/video to know what happened !

And that's all, until next year (in U.S ?) !

Wednesday, March 17, 2010

Scala Unix file permissions DSL

Scala native DSL capabilities are astonishing. I just created some Scala object to mimic Unix file permission representation and "chmod" interaction, and I'm rather pleased of the result

Only user", "group" and "other" permission are managed - so no setuid, setgid or sticky bit.

Perm objects

They are simple immutable permission objects with a nice toString and an octal representation:
scala> val p:Perm = wx
scala> w.toString // "-wx"
scala> w.octal // 3
You can combine permission to obtain new permissions:
scala> w+r  // rw-
scala> rwx-w // r-w

FilePerms objects

They keep a group of three mutable permissions. You can create a new File permission object from octal values:
scala> val perms = FilePerms(777)

Or from Perm object:
scala> val perms = FilePerms(rw,rw,r)
Like Perm, they have nice string and octal representation:
scala> val perms = FilePerms(777)
scala> perms.toString //rwxrwxrwx
scala> perms.octal // 777

Missing values are initialized to "no permission":
scala> val perms = FilePerms(77) //rwxrwx---
scala> val perms = FilePerms(rw) //rw-------

And of course, you can change permissions:
scala> val perms = FilePerms(77) //rwxrwx---
scala> perms.g-wx  // rwxr----
scala> perms.ugo+x // rwxr-x--x
scala> perms.a-wx  // r--r-----
The binding of theses objects with Java IO with the goal to actually set file permissions is let as an exercise for the reader ;)
It's available on gist here: http://gist.github.com/335791. To test it, simply copy the file content, fire a Scala REPL, start an object declaration, past the content of the file, close you object, import its content, and play:
scala> object p { [enter]
  | [here, past the content of the file]
  .....
  | }
defined module p

scala> import p._
import p._

scala> FilePerms(644)
res0: Option[p.FilePerms] = Some(rw-r--r--)

Enjoy !


PS: if you have an idea about how to mimic chown, I would appreciate. For now, all I get is:
chmod( ug(_)+rw, filePerms)
Not really nice.

Wednesday, January 20, 2010

Scala and Spring 3 JavaConfig

Scala, Spring 3, Actor, REST, IoC configuration by code...
... and well, I should be able to put some other buzz words in that title, perhaps agile and Scrum ?

I wanted to test Spring 3 "configuration via code" new feature, and especially how well it works with Scala.

As a Tapestry 5 (former) user, I'm a great fan of IoC configuration done in Java (or Scala). From a developer point of view, it's so much more easy and robust (especially refactoring prone) to have access to a real, type safe language in place of an ersatz like XML... and most of the time, it's also much less verbose.

The application
I needed a pretext and decided to build a trivial web application that allows to upload files to some URL, and post-process them - a rather usual need in a web-application. That will allow to test Spring 3 new "REST" features, a bit of Expression Language, and put in a little Scala Actor to let the (long) processing be done asynchronously.
I also used maven, and Slf4j with NoCommonsLogging to be able to use Slf4j with Spring.

What exactly does the application:
- wait uploads on a REST endpoint URL;
- when an upload comes, save it into a temporary file;
- signal the file's availability to a "file processor". That processing may take a looooooong time to process (for example, it's a big XML report, with a lot of parsing, input validation, graphs generation, etc), and so, the processing should be done in a side process.

Results
Everything comes along really well, and the result is available on github.

To test it, you will need a JVM and Maven (if you haven't done it yet and are not limited by production constrains, just go download the last 1.6 JVM (1.6.0_18), the performances improvements with the last two releases are impressive)

% git clone git://github.com/fanf/scala-spring3-upload.git
% cd scala-spring3-upload
% mvn jetty:run
You should have a Jetty server up and running on localhost.
Now, you can upload a file to http://localhost:8080/upload, and see that the upload is processed and HTTP code returned, and then an asynchronous process is launched to process the file - well, actually it just waits 10 seconds and delete it.
On Linux, you can use Curl to post files:

% curl -F FileToUploadName=@/path/to/the/file/to/upload http://localhost:8080/upload/


Details about the project
Here comes the different files and their purpose:

src/main/webapp/WEB-INF/

It contains usual servlet configuration files, in XML :
- web.xml : standard Java servlet config file, nothing to see here. with a reference to the annotation based context loader and the AppConfig.scala file.

- upload-servlet.xml : Spring servlet config file. It's this one that is Spring default enter point, and it contains an entry point to the Scala file used for bean configuration, and to the prope


I just don't understand why this last file is needed. It's where you feel that JavaConfig was an afterthought in Spring... Couldn't have we a convention in place of that ? Something like "put your master configuration code in that package" ? All in all, it's small pain to have to write that file, but it also bring really little information. 


UPDATE: as Chris Beams shows me, I should have RTFM more carefully. It's now possible (I do believed it wasn't in first RCs), and I updated the sources to have a full ScalaBased configuration.

src/main/scala/org/test/upload

That package contains the code to receive file (UploadEndpoint.scala) and process them (FileProcessor.scala).
As you can see, there is very little code, and most of it is self-explanatory.

src/main/scala/org/test/upload/config

That last package only contains the AppConfig.scala file, the place where Spring IoC configuration is done.
I really like the cleaness of that file, compared to what may have been the equivalent XML one.
The default sleepTime value is especially cool, typically a things hard to do when you only have XML

Conclusion
This little project could be a good starting-point if you want to use Spring 3 with Scala, or Slf4j with Spring.
I'm also rather impressed by how much little code is needed with Spring 3 to configured the REST endpoint.
And building little asynchronous services thanks to actor is just too simple (OK, here it's a toy, but if you want serious business with actor, look at AKKA).

Monday, October 12, 2009

ActiveLDAP in Scala : LDAP on the JVM, in a shell !

Update: typos only

Until a really recent time, LDAP in the JVM, trougth JNDI API, was a nightmare of usability. Just connecting to an LDAP directory with a simple login/pass was worth a dozen lines of really unatural code (and I'm almost not exagering)

Hopefully, the situation is evolving, and there is several projects willing to provide a better LDAP SDK on the JVM.

Among them, there is UnboundId's one. I started to play with it, and it's quite delighting to be able to use a good API to do your work !

So it gives me an idea : how this SDK could be pimped thanks to Scala to be used in command lines, in a ruby ActiveLDAP fashion ?

And things are coming along really well. It's just a start, but this is an example of a Scala REPL session with my version of Scala ActiveLDAP :


scala> import test.activeldap._
import test.activeldap._

scala> import LdapFilter._
import LdapFilter._

scala> val p = new SimpleAuthLCP(baseDn = "dc=example,dc=org",authDn = 
"cn=admin", authPw = "secret pass")
p: test.activeldap.SimpleAuthLCP = [cn=admin@localhost:389 (base: 
dc=example,dc=org) by password authentication]

scala> val users = new MetaActiveEntry(prefix = "ou=people",  
rdn = "uid" , classes = Set("top","person","organizationalPerson","inetOrgPerson"), 
provider = p )
users: test.activeldap.MetaActiveEntry = test.activeldap.MetaActiveEntry@c85a33

scala> val user = users.find()(0)
user: test.activeldap.ActiveEntry = uid=42,ou=people,dc=example,dc=org

scala> user.details
res28: java.lang.String = Entry(dn='uid=42,ou=people,dc=example,dc=org', 
attributes={Attribute(name=objectClass, values={'inetOrgPerson', 
'organizationalPerson', 'person', 'top'}), 
Attribute(name=sn, values={'Bar'}), Attribute(name=cn, values={'Foo'}), 
Attribute(name=mail, values={'foo@bar.com'}), Attribute(name=uid, values={'42'})})

scala> user("uid") = "43"

scala> user.save

scala> users.find()
res31: Seq[test.activeldap.ActiveEntry] = ArrayBuffer(uid=42,ou=people,dc=example,dc=org,
uid=43,ou=people,dc=example,dc=org)

scala> user("mail") = Seq("foo@bar.com","foo_bar@bar.com")

scala> user.save

scala> users.find(EQ("uid","43"))(0).details
res34: java.lang.String = Entry(dn='uid=43,ou=people,dc=example,dc=org', 
attributes={Attribute(name=objectClass, values={'inetOrgPerson', 
'organizationalPerson', 'person', 'top'}), Attribute(name=sn, values={'Bar'}),
Attribute(name=cn, values={'Foo'}), Attribute(name=mail, values={'foo@bar.com', 
'foo_bar@bar.com'}), Attribute(name=uid, values={'43'})})

scala> user.delete

scala> users.find(EQ("uid","43"))
res36: Seq[test.activeldap.ActiveEntry] = ArrayBuffer()


scala> 

There is a really nice feature brought by Scala 2.8 for this kind of API: named and default parameters. I  used it in the previous sessions to define the connection: host and port were not provided (default to localhost:389),  but you can specify them if you need :

 scala> val p = new SimpleAuthLCP(
        | authDn = "cn=manager",
        | authPw = "secret password",
        | host = "an.other.host.com",
        | port = "1389",
        | baseDn = "dc=company,dc=com"
        | )

It's just a begining, and there is a lot of other nice features from Ruby ActiveLDAP that could be added...

Thursday, October 1, 2009

Alternative languages for the JVM @ OpenWorldForum Paris

Today, a was kindly invited by Alexis Moussine - Pouchkine to be the Scala advocate in a roundtable about alternative languages on the JVM, during a session about the Futur of Java in Open World Forum meeting in Paris.

The sessions was brief (3 parts of about 30 minutes), and in my feeling a bit outside the main topic of OpenWorldForum which was more about open source at a strategic an politic level, but (surprisingly for me) our room was quite crowd, with interested people.

Alexis gave the first presentation about the state of Java and OpenJDK, and final presentation,  about forthcoming JavaEE 6. As always, I really liked to hear and see Alexis make the show, his presentations were really good, and he defenitly deserve his "JavaEE and Glashfish Evangelist" title.

The roundtable begun with a presentation from Stéphane Fermigier of the way accomplished by Java and the JVM as a platform for other language since it's first release back in 1996.
Afterwards, Guillaume Laforge (of course for Groovy) and I (for Scala) talked about our prefered language, the "welcomeness" of the JVM plateform, the always funny debate about dynamically and statically typed languages, and the fact that we seem to be going to a world of "polyglotism", where multiple languages would cooperate on top of a highly industrialized, robust and efficient VM, and be selected for their adequacy to the task to accomplish - all that things mixed up with attendees questions. 

And then, even if we went past the given 30 minutes (well, actually, even went past the 40 minutes...) it was already time to stop.

It was a really pleasant meeting, and I'm really happy to see that Groovy is now a first class citizen in the Java world, that Scala is beyond the status of new intriguing thing and becomes to be evaluated in different places, and that we can say "functional programming" elsewhere than in an University or some strange startup without being looked as a dangerous, non business compliant hacker.

Friday, August 14, 2009

Why simple XML processing is so painful in Java ?


Note: this article is of little interest to learn Scala XML apis, there is far better coverage of them elsewhere in the web, like here and in details here. It's more like a rant against Java, which makes things painful where it should shine...


Nowadays, XML is more or less everywhere, especially when there is data to dispatch between applications, protocols, program languages and other technologies - and no, Json is not (yet ?) as ubiquitous as XML for that.

And still nowadays, parsing simple XML documents in Java is a pain.

Well, actually, I don't speak about complex, normalized documents with defined, huge XSD schemas (perhaps in this situation, you can afford to invest time in Jaxb or Jibx to do it the right way), nor simpler scenario, but where you want to have a real XML/Object mapping - XStream is a kind here, and really does a good job.

I'm talking about kind of XML documents which are more like a database dump, that may be long and with rather deep tree structures, and where you just want to cherry pick some values - of course, in different parts of the tree. You know, when you just want to test ideas, and you have to implement a quick, working thing to see if the overall architecture works [1], and you really don't want to build a full POJO tree to change or erase it the next hour.

That's a kind of place where Java XPath API (jaxp) should shine. But it doesn't. I'm not saying that it's difficult, nor that it doesn't actually work, but that it's painful and you end up with lines and lines and lines of burden (cast, expression compilation, redefinition of higher function than the ones provided by API to do common things, etc) in code that should just expose your intention at first sight.

Well, lets take a super simple example.

Lets say that I have this kind of XML data :


<?xml version="1.0" ?>
<request>
<id>463516</id>
<timestamp>1250240149028</timestamp>
<information>
<person>
<id>463</id>
<firstname>Alex</firstname>
<lastname>Bar</lastname>
<age>34</age>
<gender>male</gender>
<address>
<street>136 W 9th St</street>
<city>Casper</city>
<country>United States</country>
</address>
</person>
</information>
</request>

And I only want to take the timestamp, add the city in a male or female list depending of the gender, and if age > 18, increment the count off adults.

I have a data container that looks like[2]:

public class Data {
public static final String MALE = "male";
public static final String FEMALE = "female";

private final Long timestamp;

private final Map<String, List<String>> stats;

private int adults;

public Data(Long timestamp) {
this.timestamp = timestamp;
this.stats = new HashMap<String, List<String>>();
this.stats.put(MALE, new ArrayList<String>());
this.stats.put(FEMALE, new ArrayList<String>());
}

public void addMale(String city) { this.stats.get(MALE).add(city); }
public void addFemale(String city) { this.stats.get(FEMALE).add(city); }
public Long getTimestamp() { return timestamp; }
public void incAdults() { this.adults = this.adults + 1; }

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("time: ").append(this.timestamp).append("\n");
sb.append("female: ");
for(String s : stats.get(FEMALE)) {
sb.append(s).append("; ");
}
sb.append("\n");
sb.append("male: ");
for(String s : stats.get(MALE)) {
sb.append(s).append("; ");
}
sb.append("\n");
sb.append("adults: ").append(adults);
return sb.toString();
}
}

OK, I now this the simplest Java class I came with to implements this logic:

/*
* So, you need a lots of imports,
* and you must have jaxp-api
* somewhere in you path
*/

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;


public class ParseData {

/*
* the "throws Exception" is here to try to remove a
* lot of burden, but of course, don't do that at home !
*/
public static void main(String[] args) throws Exception {

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("data.xml");
XPath xpath = XPathFactory.newInstance().newXPath();

// now, I start to actually do something interesting
Data data = new Data(Long.parseLong(
s(xpath, doc, "//request/timestamp/text()")));

XPathExpression xe = xpath.compile("//request/information/person");
NodeList nodes = (NodeList)xe.evaluate(doc,XPathConstants.NODESET);

for(int i = 0; i < nodes.getLength() ; i++) {
String gender = s(xpath, nodes.item(i), "//gender/text()");
String city = s(xpath, nodes.item(i), "//address/city/text()");

if(Data.MALE.equals(gender.toLowerCase())) {
data.addMale(city);
} else if (Data.FEMALE.equals(gender.toLowerCase())) {
data.addFemale(city);
}

if(Integer.parseInt(s(xpath, nodes.item(i), "//age/text()")) >= 18) {
data.incAdults();
}
}

System.out.println(data);

}

/*
* Why do I have to do that ? Even it it's two lines,
* I just let you imagine the look of the
* main loop without this function...
* But why the Xpath API doesn't have the four of five
* functions alike defined for each XPathConstants types ?
* Before actually begin to use the API, I have to redefine it...
*/
public static String s(XPath xpath, Object root, String expr) throws Exception {
XPathExpression xe = xpath.compile(expr);
return (String)xe.evaluate(root, XPathConstants.STRING);
}

}


As you can see, there is a lots of type cast, and I quickly loose what I'm looking for, even in a so simple class with so little cases and data to retrieve.

So, at the end, what did I do ? Just use the Scala XML library. Same logic, in a scala class:



import scala.xml.XML

object ScalaParseData {

def main(args:Array[String]) {

val doc = XML.load("data.xml")

val data = new Data((doc\\"request"\"timestamp" text).toLong)

for(person <- (doc\\"request"\"information"\"person")) {
val city = person\"address"\"city" text

(person\"gender" text).toLowerCase match {
case Data.MALE => data.addMale(city)
case Data.FEMALE => data.addFemale(city)
}

if((person\"age" text).toInt >= 18) data.incAdults
}

println(data)
}
}


In both case, the same output is printed in stdout:

time: 1250240149028
female:
male: Casper;
adults: 1


Even if you never look at Scala, you understand what is the global logic, what piece of data are looked for. Nothing to add :)


[1]: ok, the question here is: is Java the right language for that ? Well, it seems that the answer, for whose who still had doubts, is DEFINITLY NOT.

[2] OK, even the data container is complex, and Java really miss Tuples structure to prototype efficiently. In such a process, you just don't want to spend time writing POJOs and POJOs and POJOs that are only, meaningless container for two string lists and a long, even if you IDE does 90%of the job. If you are interested by more efficient data structure for Java, you should go and look for Functional Java, that's a really cool project - and at least, you will have tuples (named "products" here), function class (to not have to define again and again that Filter<E> { boolean filter(E element); } class)

Thursday, May 28, 2009

100 problems solved on Project Euler

Today, I just finished my 100th problem on Project Euleur, using Scala - of course.

Project Euler is a really good way to learn a language on small problems, to see its different sides and idiomatic constructs, and be confronted on performance/algorithm optimization choices - that teaches you to feel when something migth make you gain an order or two of execution time / memory consumption, and when you are working for peanuts.

OK, you won't see how the language solves big architectural design and maintenance problems, but you will learn if the language fits your mind, and if you are able to get things done with it. And definitly, Scala shines on such problems, and completly fits my mind.

So, it was a really good learning experience. Now, I need to test it on bigger problem, to see how it goes on the long run, and I have some ideas for that...

Wednesday, March 25, 2009

Tapestry 5 - Scala : view article in HTML, JSON or XML

We must have the REST in our blog, it will attract a lot of investors


The last time we saw how to make basic CRUD functionalities for the blog. That was quite a long time, because I started to encounter some rough edges that make Scala and T5 don't go together as smoothly as expected. Nevertheless, all problems were worked around.

This article is about how simply one can customized the output format of her URL in a RESTful way (see that for more details about REST, but whatever says this too academic article, we all well know that "REST" means "pretty shiny URLs" and "being 2.0, not like whose outdated web service" ;).

So, basically, what we will provide is two different ways of viewing an article:
  • A standard, HTML view with this kind of URLs: http://localhost:8080/blog/article/view/1


  • An XML or JSON output, with this kind of URLs: http://localhost:8080/blog/article/view:xml/1 or blog/article/view:json/1


    <article title="First article" id="1">
    <published>true</published>
    <content>Content for the first article</content>
    <creationDate>2009-03-24 16:16:31.865 CET</creationDate>
    </article>

    And:

    {"article": {
    "@published": "true",
    "@title": "First article",
    "@id": "1",
    "content": "Content for the first article",
    "creationDate": "2009-03-24 16:16:31.865 CET"
    }}

The "view article" page


The first step here is to build a page that will show an article based on it's id.
We want that an URL like: http://localhost:8080/blog/article/view/1
Return the page:


For that, we add a ViewArticle class and ViewArticle template in the package "org.example.blog.pages.article".

The template is trivial, we simply display meaningful information of a backed article object:
org.example.blog.pages.article.ViewArticle.tml
<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">

<h2>${article.title}</h2>
<h4>by ${authorname}, on ${article.creationDate}</h4>

<div>
${article.content}
</div>

</t:layout>


And that's all.

The Scala class is not much more complicated:
org.example.blog.pages.article.ViewArticle.scala
class ViewArticle {

@Inject
var articleDao : ReadDao[Article,String] = _

@Inject
var conf : BlogConfiguration = _

@Property
var article : Article = _

var id : String = _

def onActivate(id:String) { this.id = id }

def getAuthorName() = this.conf.getAuthor.getLogin

def setupRender {
this.article = this.get(id)
}

private def get(id:String) =
if(null == id ) NoneArticle
else this.articleDao.get(id).getOrElse(NoneArticle)
}


We see that I use two services, the Article DAO that allows to retrieve article from their store, and the blog's configuration that is used to display to author name: the article object it accessible from the template because of the @Property annotation (this T5 annotation is in fact the same as the Scala @BeanProperty one, it generates the pair of getter/setter for the attribute), getAuthorName() is called in the template by ${authorname}.

The logic of the page is almost inexistent: when the page is activated (what means an HTTP request is handled by that page), we store the "id" parameter (in our example, it's "1") for when the page is rendered. There is more about Tapestry 5 page activation and parameters here.
When the page is rendered, we ask the article DAO to retrieve the article with the given ID. If none is found, or if the given id was null (no parameter was found in the URL), we used a special "NoneArticle" object for the rendering. This object is a placeholder that stands for "null" for article type, and is defined as follow:

org.example.blog.data.Article.scala
object NoneArticle extends Article(None) {
creationDate = new Date(0L);
title = "No such article"
}


And with that, the HTML view is over.

Marshalling article


Here we deal with the transformation of article object into XML or Json, and how we make a service for that task available in our blog.

XStream, the swiss-knife of serialization



Well, in fact I will confess something: I did almost nothing to make the other two output renderings works, it's basically only the mapping of an XStream output to some Tapestry 5 event handlers.

If you don't already know XStream, stop reading here, and just go and look for its 2 minutes tutorial - it's actually a two minutes thing to read and shows how powerful Xstream is.

For the lazy clicker, there's a summary: XStream is an amazing XML and JSON marshalling and unmarshalling library for Java. It's fast, it's powerful, it's broadly used with all the good that that carries, and its learning curve is counted in seconds.

Basically, without any configuration, you can use it like that:

Person joe = new Person("Joe", "Walnes");
XStream xstream = new XStream();
String xml = xstream.toXML(joe);


And it will output something like that:
<org.foo.domain.person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
</org.foo.domain.person>


With one more config line for the Xstream object:
xstream.alias("person", Person.class);


You get a prettier output:
<person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
</person>


Doesn't it look simple? And if I say that it also works for JSON output, and also in the reverse way (from JSON/XML to Object), that output customization is almost infinite, you're likely to fall in love with this little, cute library.

Marshalling services for our blog



In the pages, we only need a simple service that transform object to a String representation. As always, we define an interface for that service:

org.example.blog.services.Marshaller.scala
trait Marshaller { 
def to(o:Any) : String
}


Next, we are going to build two implementation for that service, one for XML output and one other for the JSON output. The two of them will extend a common Xstream based Marshaller:

org.example.blog.services.impl.XstreamMarshaller.scala
class XstreamMarshaller(val xstream:XStream) extends Marshaller  {
override def to(o : Any) = this.xstream.toXML(o)
}

class XmlXstreamMarshaller() extends XstreamMarshaller(new XStream(new DomDriver()))

class JsonXstreamMarshaller() extends XstreamMarshaller(new XStream(new JsonHierarchicalStreamDriver()))


There is only one step remaining to enable the service in our blog: binding interface and implementation in the Tapestry module definition:
org.example.blog.services.AppModule.scala
object AppModule {
//bind is a conventionnal method name for binding interface and implementation when no special configuration is needed
def bind(binder : ServiceBinder) {
binder.bind[Marshaller](classOf[Marshaller],classOf[impl.XmlXstreamMarshaller]) withId "xmlMarshaller"
binder.bind[Marshaller](classOf[Marshaller],classOf[impl.JsonXstreamMarshaller]) withId "jsonMarshaller"
}


Note that we assign a name (an Id) to each marshaller. That's because we now have two implementations for a given interface declared in the IoC registry. Tapestry 5 will not be able to know automatically what we really want to use when we will require a service injection for that interface, and so we will have to precise the name of the actual service we really want.

An now, let's use these marshallers to render JSONinfied and XMLified articles.

Binding URL to marshaller output


This second part aims to produce the correct output based on the URL.

T5 event handling system


Again, I did nothing special to bind URL and XML/JSON output since I used the standard Tapestry 5 event system: Url with ":" after a component or page name are interpreted as "component:eventname/eventparams".

For example, http://localhost:8080/blog/article/view:xml/1 means: throws the "xml" event on page "article", with the "1" parameter.

For our use case, the only thing to do is to handle "Xml" and "Json" events in the Scala back end of the "Article/View" page. Like most of the time in Tapestry 5, these event handlers are based on convention, and here the convention is to use "onEVENT" for the method name, where "EVENT" is the name of the event to handle.

The modified ViewArticle class looks like:

org.example.blog.pages.article.ViewArticle.scala
class ViewArticle {

@Inject
var articleDao : ReadDao[Article,String] = _

@Inject
var conf : BlogConfiguration = _

@Inject @Service("xmlMarshaller")
var xmlMarshaller : Marshaller = _

@Inject @Service("jsonMarshaller")
var jsonMarshaller : Marshaller = _

@Property
var article : Article = _

var id : String = _

def onActivate(id:String) { this.id = id }

def getAuthorName() = this.conf.getAuthor.getLogin

def setupRender {
this.article = this.get(id)
}

def onXml = new TextStreamResponse("text/xml",this.xmlMarshaller.to(NoneArticle))
def onJson = new TextStreamResponse("text/plain",this.jsonMarshaller.to(NoneArticle))

def onXml(id:String) = {
new TextStreamResponse("text/xml",this.xmlMarshaller.to(this.get(id)))
}

def onJson(id:String) = {
new TextStreamResponse("text/plain",this.jsonMarshaller.to(this.get(id)))
}

private def get(id:String) =
if(null == id ) NoneArticle
else this.articleDao.get(id).getOrElse(NoneArticle)
}


Compared to the first version, we just injected two marshallers and used them in event handlers. I set-up specific handlers for the case when no parameter is given in the URL.

Note that we solved the injection ambiguity problem on "Marshaller" injection by naming the service we really want to be injected thanks to the "@Service("name")" annotation after the @Inject one.

The only other remarkable thing is the TextStreamResponse object, that allows to return arbitrary text output for rendering. It's an implementation of the StreamResponse interface, that allows to return arbitrary content - yes, returning a PDF for a given URL is a matter of returning the correct StreamResponse in a handler method. Simple, no ?

With that, we have a first promising result.

http://localhost:8080/blog/article/view:xml/1 leads to:

<org.example.blog.data.Article>
<published>true</published>
<comments class="scala.Nil$"/>
<content>Content for the first article</content>
<title>First article</title>
<creationDate>2009-03-25 14:19:41.940 CET</creationDate>
<id class="scala.Some">
<x class="string">1</x>
</id>
</org.example.blog.data.Article>


And http://localhost:8080/blog/article/view:json/1 leads to:

{"org.example.blog.data.Article": {
"published": true,
"comments": {
"@class": "scala.Nil$"
},
"content": "Content for the first article",
"title": "First article",
"creationDate": "2009-03-25 14:19:41.940 CET",
"id": {
"@class": "scala.Some",
"x": {
"@class": "string",
"$": "1"
}
}
}}


And non existing article or no parameter, like in http://localhost:8080/blog/article/view:xml/foobar leads to:

<org.example.blog.data.NoneArticle_->
<published>false</published>
<comments class="scala.Nil$"/>
<content/>
<title>No such article</title>
<creationDate>1970-01-01 01:00:00.0 CET</creationDate>
<id class="scala.None$"/>
</org.example.blog.data.NoneArticle_->


That's not too bad for a couple of line of code, but output should be nicer.

Configuring output


Actually, we don't want to show the qualified class name in the output, nor we need the comments here, and it will be cool to have "id" and "title" as attributes of the "article" node.

For that, we will customized Xstream marshaller.

The first step is to change the marshaller implementation registration in AppModule to a more configurable one:

org.example.blog.services.AppModule.scala
  def bind(binder : ServiceBinder) {
//remove marshaller from here
}

def buildXmlMarshaller(): Marshaller = {
val m = new XmlXstreamMarshaller
ConfigureArticle4Xstream.configure(m.xstream)
m
}

def buildJsonMarshaller(): Marshaller = {
val m = new JsonXstreamMarshaller
ConfigureArticle4Xstream.configure(m.xstream)
m
}


These new definition also build two marshallers, named "XmlMarshaller" and "JsonMarshaller", but with that way we are able to configure the Xstream instance of each implementation.
Since our case is really simple, the two configurations are the same, and look like that:

org.example.blog.services.impl.XstreamMarshaller.scala
object ConfigureArticle4Xstream {
def configure(x:XStream) {
import org.example.blog.data.{Article,NoneArticle}
//output "article" in place of org.example.blog.data.Article
x.alias("article",classOf[Article])

//title and id will be output as attributes of article...
x.useAttributeFor(classOf[Article],"title")
x.useAttributeFor(classOf[Article],"id")

//...and since Id is not a simple string, we have to provide a converter to make it works
x.registerLocalConverter(classOf[Article],"id",new ArticleIdConverter())

//we don't want to display comments
x.omitField(classOf[Article],"comments")

//special config for NoneArticle
x.alias("article",NoneArticle.getClass)
}
}


Each line provides the commented explanation.
The id converter simply output the id if available, or "none":
org.example.blog.services.impl.XstreamMarshaller.scala
class ArticleIdConverter extends SingleValueConverter {
def fromString(s:String) = if("none" == s) None else Some(s)
def toString(a:Object) = a match {
case None => "none"
case Some(x) => x.toString
case _ => error("Not supported type: " + a.getClass.getName)
}
def canConvert(c:Class[_]) = {
if(c == classOf[scala.Option[_]]) true
else false
}
}


With this configuration, outputs are much nicer:

http://localhost:8080/blog/article/view:xml/1 leads to:

<article title="First article" id="1">
<published>true</published>
<content>Content for the first article</content>
<creationDate>2009-03-25 15:09:20.476 CET</creationDate>
</article>


And http://localhost:8080/blog/article/view:json/1 leads to:

{"article": {
"@title": "First article",
"@id": "1",
"published": true,
"content": "Content for the first article",
"creationDate": "2009-03-25 15:09:20.476 CET"
}}


And non existing article or no parameter, like in http://localhost:8080/blog/article/view:xml/foobar leads to:

{"article": {
"@title": "No such article",
"@id": "none",
"published": false,
"content": "",
"creationDate": "1970-01-01 01:00:00.0 CET"
}}


Now, we can say too our chief that he can go and look for investor, our blog has the REST (well, almost ;).
And that's all for today !

Next time


We reach a rather satisfying result with really few lines of code, but I have to say that our implementation is bad.

The main reason for that is that there is a bunch of coupling and code duplication at the moment:
- from the page designer point of vue, it's crappy to have to inject several marshallers, and choose the correct one for each event;
- moreover, addind a new output (for example, plain text) would mean modifying *all* pages that use marshallers;
- with the actual configuration, each time that we want to customize an output for a given object, we have to actually modify the code of XstreamMarshaller core implementation, or in the core module definition !

So the next time, we will see how we can improve these points. And again, it will be easy, thanks to Tapestry IoC provided features.

As always, the real full code is available at Github at this tag :
http://github.com/fanf/scala-t5-blog/tree/article4_20090325

Monday, March 16, 2009

Java annotation, scala object and javassist don't get along well

[Update: in the next paragraph, "showstopper" is clearly too strong - put it in my bad english level. The title is perhaps better, I wanted to say that things didn't came along as well as I hoped initially. In no case I wanted to sound over-pessimistic. Actually, the workaround is rather simple : I can use a direct call to the look-up service of T5 IOC each time I need a named service in place of the direct injection of that service.]

In my quest of using Tapestry 5 with a Scala back-end, I believe I fall on a showstopper. I seems that Javassist doesn't see annotation on method parameter in Scala object, although the annotation (being marked with Runtime retention) is seen with the Java reflexion API.

I tested with both Scala 2.7.3 and 2.8.0-nigtly, and both Javassist 3.9.0.GA and 3.10 - the behaviour is consistent in all combinations.

In fact, what seems to happens is that when one defines a Scala object "Foo.scala", scalac generates two classes : "Foo.class" that is a kind of singleton facade and initializer, and "Foo$.class" that is the actual class.

When the java reflexion API is used, I think that scala delegates the call in the rigth way. The problem seems to be that Javassist directly read the bytecode of "Foo.class", and doesn't see the annotation - it seems to be only on the method in "Foo$.class".

You can you see this behaviour like that:

Make a simple Java annotation, and compile it, something like @InjectService in Tapestry5-annotation package:


@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
@Documented
public @interface InjectService
{
String value();
}



Create a scala class that make use of that annotation and test it visibility thanks to Java reflexion API and Javassist :



import org.apache.tapestry5.ioc.annotations.InjectService
import javassist._
import javassist.runtime._


object ObjectTestAnnotation {
def methodWithParamAnnot(@InjectService("service id") s:String) = s
}

class ClassTestAnnotation {
def methodWithParamAnnot(@InjectService("service id") s:String) = s
}

object Main {

def main(args: Array[String]) {
/*
* Using Java reflexion API
*/
val methodWithParamAnnot = ObjectTestAnnotation.
getClass.getMethod("methodWithParamAnnot", classOf[String])
val annotations = methodWithParamAnnot.getParameterAnnotations
println("* with java reflexion API, on ObjectTestAnnotation")
annotations.foreach(_.foreach( x => println(x)))
// print:
// * with java reflexion API, on ObjectTestAnnotation
// @org.apache.tapestry5.ioc.annotations.InjectService(value=service id)

val methodWithParamAnnot1 = classOf[ClassTestAnnotation].
getMethod("methodWithParamAnnot", classOf[String])
val annotations1 = methodWithParamAnnot1.getParameterAnnotations
println("* with java reflexion API, on ClassTestAnnotation")
annotations1.foreach(_.foreach( x => println(x)))
// print:
// * with java reflexion API, on ClassTestAnnotation
// @org.apache.tapestry5.ioc.annotations.InjectService(value=service id)

/*
* Using Javassist
*/
val cp = ClassPool.getDefault()
val ctString = cp.get("java.lang.String")
val methodWithParamAnnot2 = cp.get("test.ObjectTestAnnotation")
.getDeclaredMethod("methodWithParamAnnot",Array(ctString))
val annotations2 = methodWithParamAnnot2.getParameterAnnotations
println("* with javassist, on ObjectTestAnnotation")
annotations2.foreach(_.foreach( x => println(x)))

// print (AND THAT'S BAD, the annotation is not seen !)

// * with javassist, on ObjectTestAnnotation

val methodWithParamAnnot2_bis = cp.get("test.ObjectTestAnnotation$")
.getDeclaredMethod("methodWithParamAnnot",Array(ctString))
val annotations2_bis = methodWithParamAnnot2_bis.getParameterAnnotations
println("* with javassist, on ObjectTestAnnotation$")
annotations2_bis.foreach(_.foreach( x => println(x)))
// print:
// * with javassist, on ObjectTestAnnotation$
// @org.apache.tapestry5.ioc.annotations.InjectService(value="service id")


val methodWithParamAnnot3 = cp.get("test.ClassTestAnnotation")
.getDeclaredMethod("methodWithParamAnnot",Array(ctString))
val annotations3 = methodWithParamAnnot3.getParameterAnnotations
println("* with javassist, on ClassTestAnnotation")
annotations3.foreach(_.foreach( x => println(x)))
// print:
// * with javassist, on ClassTestAnnotation
// @org.apache.tapestry5.ioc.annotations.InjectService(value="service id")

println("done")


}

}



Cry ! Because, of course, Tapestry 5 uses these annotations in such a way that a bug here make the whole thing unusable - the core of T5-IOC container relies on them.
I would have to see if I can use a class in place of the object...

Thursday, February 12, 2009

Tapestry 5 - Scala : start of delusion

I didn't write anything for a long time on my Tapestry 5 / Scala experiment. Things are starting to go wrong.

From one part, I found what may have been a bug in Scala ( https://lampsvn.epfl.ch/trac/scala/ticket/1695 ) and that delayed me lot in the use of T5 IoC binder.

For the other part, T5 IoC does not seems to support parameterized types at more than one level, and so I can't use parameterized class in contributions.

For example, I can't contribute Tuple, or (and that's quite a big limitation) class because in Scala, you can't use the unparameterized "Class" argument, it must be "Class[Something]", and here lies the hell of generics...

So for now, I'm beginning to thing that T5 and Scala don't feet so well together, or at least that I have some nuts to scratch and some "best practices" to find before going further in the test.


EDIT: as proposed by Ricky Clarkson, for the class problem, just use Class[_]

Monday, January 19, 2009

Tapestry 5 - Scala : a layout and basic CRUD for the blog

After setting up a hello world application in Scala and Tapestry, and testing how Tapestry IoC / property access works in this environment, it's time to actually do something.

So, this article will explain how I set up the basic fonctionnalities for our blog:

  • build a "Layout" component, so that the development will hurt our eyes a little less;
  • add an Article object, and the standards pages to use it:
    • the "home page" page will show all the published articles;
    • a "create" page will allow to add new article;
    • a "view" page will show only one article and its comments
    • a "manage" page will allows to view a list of all the article with some actions, like publish, delete, edit.




Setting up a layout


Using "layout" is a common pattern to apply the same design for all the site. In tapestry, no need to use an external template engine like sitemesh, you can simply build a "layout component" that you will use on all page that have to be decorated.

This pattern is so common that Tapestry 5 has a documentation page on how to do it with T5, so you just have to follow it : the harder part is to design the layout, or if, like me, you are a dumb in design, find a cool CSS/HTML template on internet (thank you Free CSS Templates for the one I chose.

As it's the first time that we will build a Tapestry 5 component, I will details a little what we need. In Tapestry 5, component are simple POJOs. They go under the ${t5-root}/components package, and are coupled with a Template (.tml) file.

  • create the ${root}/components/Layout.tml and ${root}/components/Layout.java couple of files for our component;
  • add the needed CSS/images in the webapp directory.


The code for the layout is here:

@IncludeStylesheet(Array("context:css/red/style.css"))
class Layout {

@Inject @Property
var conf : BlogConfiguration = _

}


The interesting part is the @IncludeStyleSheet annotation, that say to T5 ti add it the given CSS into the header of the pages where this component is used, what is handy for a layout component.

We can see that in Scala, we can't simply use the
@IncludeStylesheet({"context:css/red/style.css"})
notation, and have to explicitly build a new array - hopefully, it's trivial in Scala.

The template part of the component is bigger, since it's there that goes all the common HTML declaration.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
<title>${conf.blogTitle}</title>
<meta http-equiv="Content-Language" content="English" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>

<div id="wrap">

<div id="header">
<h1><a t:type="pagelink" t:page="index">${conf.blogTitle}</a></h1>
<h2>${conf.blogDescription}</h2>
</div>

<div id="menu">
<ul>
<li><a t:type="pagelink" t:page="index">Home</a></li>
[...]
</ul>
</div>

<div id="content">
<div class="left">

<t:body />

</div>

<div class="right">

<h2>Archives</h2>
<ul>
[... here will go the archives ...]
</ul>

<h2>Tags :</h2>
<ul>
[... here will go tags link ...]
</ul>

</div>

<div style="clear: both;"> </div>

</div>

<div id="bottom"> </div>
<div id="footer">
Designed by <a href="http://www.free-css-templates.com/">Free CSS Templates</a>
</div>
</div>
</body>
</html>


The important part it the <t:body /> tag, that says "here will go what will be find between the <t:layout> and </t:layout> tags. So, in the page where we want to use this layout, we will use template code like:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<h2>New article</h2>
[....]

</t:layout>


And now, our blog is prettier:




Note: I equally use <htmlTag t:type="T5_component"...> and <t:="T5_component"> notation to include T5 component in templates. The first one is better for designer, as template preview is correct, the second one is a little shorter. They are equivalent, and I should homogeneously use one or the other...


Article's CRUD


All this blog application is a pretext for that very part, so let's take a look at it. Reminder: "CRUD" stands for "Create, Retrieve, Update, Delete", and is a well know acronym that is used for simple application, with very little domain logic, and which are almost a front-end for datas, persisted in some layer (MySQL comes to mind, but CouchDB is a better buzz word today ;)

To sum-up, we have Article objects, a DAO to persist them, and a couple of pages to enable human I/O.

The "Article" domain object


An article is an object with an id, a title, a content, a list of comments and a creation date.

The "id" is unique identifier for an article among all the blog's article. Most of the time, it will be used to identity a particular article in the persistence layer or in URL.
I take the choice to let the persistance layer assigned the id, because we really are in a CRUD application, and no business logic can provide a realiable unique identifier. That means that a not yet persisted article has no id. In the same time, I want to enforce the fact that Id are imutable datas, that given a Article object, the id won't ever change.

In java, this kind of requirement can't easily be done in an other way than usgin "null". In Scala as in many other language, we have an Option type that has two kind of value:
  • the "None" value, which means "there is no data here";
  • the "Some[TypeOfData]" value, which means "there is a data here, and that is it's value".

I use this type for the article "Id", and the "Id" is a constructor param value of article, so that:
  • article id is immutable: an living object can't have it's id change;
  • an article with "None" id has never been saved ;

  • the persistence layer will assign IDs and return article with there definitive ID


Given that, that's the code for the Article object:

org.example.blog.data.Article.scala

class Article(val id:Option[String]) {
/*
* "none" is not allowed for article ID
*/
assert( id.forall( (s:String)=> !(s.toLowerCase == "none" )))

@BeanProperty var creationDate = new Date()

@BeanProperty var title = ""

@BeanProperty var content = ""

@BeanProperty var comments = List[Comment]()


@BeanProperty var published = false

def getId = id

/*
* String translation of the ID. Of course, it
* requires that id can't be the "None" String,
* and that's why we add the "assert" requirement
*/
def getDisplayId = this.id.getOrElse("None")
}

object Article {

/*
* Create a copy Article from a source one,
* setting the ID to a new value.
*/
def apply(id:String, source:Article) : Article = {
val a = new Article(Some(id))
a.title = source.title
a.content = source.content
a.comments = source.comments
a.creationDate = source.creationDate
a.published = source.published
a
}
}


Apart from the Article constructor and "Id" type explained before, there is three other notable things in this class:
  • A getDisplayId that is a simple method to give the article Id to other layer, especially the presentation layer. I chose to map "Some(id)" to the given id string, and the "None" type to the "None" string, what implies that I should never accept the "None" id;
  • since I can't accept "None" string as id, I added a requirement through an assertion (and no, performances don't matter, it's a tool blog application ;)
  • finally, there is a strange "object" definition after my class with the same name as it, that needs its own paragraph


"objects" are the Scala way to define static methods and contents, and it's why I used the "object" key word in the AppModule.
When paired with a class, it is called a companion object for the class. They have some special rights, in particular regarding visibilyity, that goes beyond this article.

I used this one to create a "copy" method that allows to create an article with a given id, different from the source - remember, I want to have immutable ids for an Article for all is life in memory.

The question is "why do I called this method apply, what is a name that carry almost zero information ?". Simply because it's a Scala magic word, that can be zapped when used ! Just writing "Article(id, article)" will call Article.apply(...). If you remember the "Array" in the @IncludeStyleSheet for the layout... That was the same principle. Array is the companion object of the Array class, and "Array("...","...")" secretly call the "apply" method of Array that take a list of String as parameter.

And we are done with Articles.

DAO



A DAOs ("Data Access Objects") are objects responsible for accessing and persisting (or delegate persistence of) other objects. They are the heart of CRUD application.

The first paragraph explain our generic DAO API, the second will show a naive, in memory implementation of the generic DAO for article, and a third one will explain how to use it with Tapestry IoC.

Generic DAO API


We will define DAO by their API, the set of method exposed by these service objects. In Java, API means "Interfaces", in Scala they means "Traits". In our example, they are the same things. We will define a real implementation


org.example.blog.services.DAO.scala

/**
* A read-only dao
* @param T is the type of entities handled by this DAO
* @param K is the type of the key that is used to identify entities.
*/
trait ReadDao[T, K <: Serializable] {

/*
* Retrieve an entity from its key. If no
* entities are known for the given key, None is returned.
* @param K the unique id of the entity to fetch
* @return None if no entity match that key,
* Some[entity] else
*/
def get(id:K) : Option[T]

/**
* Retrieve all the entities known by that DAO.
* Be carefull, that may be a huge number.
* @return the list of all entities for that DAO
*/
def getAll() : List[T]

/**
* Find all the entities that match the given requirement
* @param T => Boolean : the function to apply to find if
* an entity should be included in the returned list.
* (on a "true" return) or excluded (on a "false" return)
* @return the list of enetities matching the filter.
*/
def find(filter: T => Boolean) : List[T]
}

/**
* A write-only dao
* @param T is the type of entities handled by this DAO
* @param K is the type of the key that is used to identify entities.
*/
trait WriteDao[T, K <: Serializable] {

/**
* Persist the given entity: create a new one if
* the entity wasn't know in that DAO (entity
* key was None), or update an existing entity
* (it's key was Some[K]).
* @param T the entity to persist
* @return the key of the persisted entity if the process
* succeded, or None the the peristence failed.
*/
def save(entity:T) : Option[K]

/**
* Delete the article matching this id.
* If no article match this id, does nothing.
* Return true is the deletion is successful
*/
def delete(id:K) : Boolean

}

/**
* A read-write DAO, that combine read and write DAO traits.
*/
trait ReadWriteDao[T, K <: Serializable] extends ReadDao[T,K] with WriteDao[T,K]


Comments speak for themselves here, and "Option" is well-known now.
The only surprises are the "<:" which means that the K type has to be Serializable, and more notably for a Java guy, the "find" method: it takes a method as parameter !
The signature of the filter method is "I take an entity of type T as parameter, and return a Boolean".

For example, if we take an Article DAO, we may use this to find all the article whose title begin with "The" like that:


val articles = dao.find( (a:Article) => a.title.startsWith("The") == true )


That's all. It means "the method find takes as parameter a method that take an article as parameter, and return the result of the evaluation of "a.title.startsWith("The") == true".

It can even be simpler, because Scala allows to use "_" as a place-holder for parameter when there is no ambiguities, like here (in our case, find can't take anything but a method which has the "Article => Boolean" signature):


val articles = dao.find( _.title.startsWith("The") == true )


If you don't see why "closure" are so useful, look how simple that declaration is compared to the burden to declare a filter interface and used it, even with anonymous class in place of real instances...

In memory Article DAO



Now that we have our generic DAO API, we are ready to implement a version for Articles. This first DAO will be a really simple one, where articles are persisted in memory (in a Map).

org.example.blog.services.impl.dao.InmemoryDao.scala

import org.example.blog.data.Article
import scala.collection.mutable

import org.example.blog.services.ReadWriteDao

/**
* A simple, naive implementation of the Article DAO.
* In particular, this implementation is
* NOT AT ALL THREADSAFE
*/
class InmemoryArticleDao extends ReadWriteDao[Article, String] {

private val memory : mutable.Map[String, Article] = new mutable.HashMap()
private var id = 0
private def newId = { id = id + 1 ; id }

def get(id:String) = this.memory.get(id)

def getAll() = this.memory.values.toList

def find(filter: Article => Boolean) =
(for {
a <- this.memory.values
if(filter(a))
} yield a).toList

def save(article:Article) = {
val a = article.id match {
case None =>
val i = this.newId
Article(i.toString,article)
case Some(id) => article
}
assert(a.id.isDefined)
this.memory.put(a.id.get,a)
//check if article is in map for the id, return id if OK
this.memory.get(a.id.get).map( _.id.get)
}

def delete(id:String) = !( (this.memory - id).isDefinedAt(id) )
}


We can see that the "extends ReadWriteDao[Article, String]" is really like Java with generics.

The implementation is a basic mapping between our DAO API and the Map used as a back-end. Article Ids are generated by an incrementing number, but there's no lock against thread concurrency. Say that for now, it's really a tool example, and all in all, our blog can have only one author (reminds the configuration object of the previous post).

The save method is the most complex, because we have to process the update and the create case, based on the fact that id is None or Some(value).
We also see the use of the Article companion object "apply", that allows to copy the given article to a new one, but with it's freshly created id.

The filter method the Scala for comprehension loop that automatically concatenates yielded elements, but it could have been done with an even more imperative "for" loop too:

def find(filter: Article => Boolean) = {
var articles = List[Article]()
for(a <- this.memory.values) {
if(filter(a)) articles = a :: articles
}
articles
}


I believe that the first method is better, because the two are almost as inefficient, and the latter use a mutable variable.

That's all for the implementation of our DAO !

Enable Article DAO service thanks to T5 IoC



Now that we have a DAO API, and a DAO implementation for Article, we want to let our application know that when we use a DAO on articles, what we really want is to use the "In Memory Article DAO".

As for the Configuration service on the previous post, we just have to add a "build" method into the AppModule object to bind the ReadWrite[String,Article] DAO to its implementation:


def buildArticleDao = new InmemoryArticleDao()


Hum. Yeah, there is nothing to do but that, but as we are Professional, we can't let our bosses think that our job is so simple, so let's add some boilerplate to make the code seems harder, more complex:


def buildArticleDao = {
val a1 = new Article(None)
a1.title = "First article"
a1.content = "Content for the first article"
a1.published = true

val a2 = new Article(None)
a2.title = "Second article"
a2.content = "Content for the second article"

val m = new InmemoryArticleDao()
m.save(a1)
m.save(a2)
m
}


OK, that's better ! Actually, I just initialized the DAO with two articles (one published, not the other one), but it's far more impressive like that ;)

Putting the parts together : the presentation layer



Now that we (finally !) have all the services to create and retrieve articles set-up, we can switch to the only part in which customers have some interests, the presentation layer (that's because code screenshots look bad on powerpoint).

The Index page


The first page that will use our new services is the home page. On this page, we just want to display all published articles.

For that, we will use the Loop component:

org.example.blog.pages.Index.tml

<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">

<div t:type="loop" t:source="articles" t:value="article" class="article">
<h2><a t:type="pagelink" t:page="article/view" t:context="article.displayid">
${article.title}
</a></h2>

<div>${article.content}</div>
</div>

</t:layout>


We see in this template that we link to the "article/view" page, in which we will display the article with its comments. But as it's for an other day, for now we just create a org.example.blog.page.article.ViewArticle.{scala,tml} couple so that Tapestry 5 don't stop on a broken link (it validate that all lins are correct at start time), and we will take care of them the next time.

We also see that we need a "source" from where articles are taken, and a "value" to hold the current article of the loop. Of course, these objects are provided by the Scala part of the couple:

org.example.blog.pages.Index.scala

class Index {

@Inject
var readArticleDao : ReadDao[Article, String] = _

@Cached
def getArticles = readArticleDao.find( _.published == true ).toArray

@Property
var article : Article = _

}


The code stands for itself : we inject a read-only DAO for article - we don't need more, and even if actually we get the in memory read write implementation, this code only care for the read part ; we have a "getArticles" method that retrieve all publish articles from the DAO (remember: closures are great), and we have an Article "@Property" annotated to receive the current article from the loop.

As we have initialized the DAO with two articles (one published among them), as soon as we start the application, we can see the first, published article on the home page:



Isn't that great ?

Create new articles



Now that we can see our article, we may want to add some new ones - well, it's aim to be a blog, and what the point if I can't talk about how cute is my ickle hamster ?

For that, let's build the "create article" page.
Let's begin with the template. In this first version, I won't rely on the magc BeanEditForm, and we need to be able to set a title, a content, and choose to publish or not the article:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<h2>Create a new article</h2>

<t:form t:id="NewArticleForm" class="new-article">

<p>
<t:label for="publish" />&nbsp;<t:checkbox t:id="publish" t:value="article.published" />
</p>

<p>
<t:label for="title"/><br/>
<t:textfield class="large" t:id="title" value="article.title" validate="required"/>
</p>

<p>
<t:label for="content" /><br/>
<t:textarea class="large" t:id="content" value="article.content" />
</p>
<t:submit />
</t:form>
</t:layout>


This template is a little boring, but it's the first time we see a constructed form and it's different input. The title is required, and the form will be refused as long as it is no provided. There is other predifined validator, like min/man, regexp... And... well, there's nothing more to say : all input has a value parameter that is the link to the server-side java^W Scala object that will handle it, and there is a submit button. And that's all.

That looks like that:



Ok, so how do we handle that on the server side ?

org.example.blog.page.article.CreateArticle.scala

import org.apache.tapestry5.annotations.{Property,Persist,InjectPage}
import org.apache.tapestry5.ioc.annotations.Inject

import org.example.blog.data.Article
import org.example.blog.services.WriteDao

import java.text.DateFormat

class CreateArticle {

@Inject
var articleDao : WriteDao[Article,String] = _

@Persist @Property
var article : Article = _


@InjectPage
var redirectPage : ManageArticle = _

def setupRender {
if(null == this.article) {
this.article = new Article(None)
}
}

def onSuccessFromNewArticleForm = {
articleDao.save(article) match {
case None => error("Dao error ! Please retry.")
case _ => this.article = null ; redirectPage
}
}
}


This time we need the "Write" part of the DAO (and a again, no need for the other, so I injected the minimal aspect), and an Article that will back the the new article.

The article is annotated @Persist, so that it will be stored in session. We need that because the form has to be validated, and perhaps show again: we don't want to loose what was written in this case.

The setupRender method is a conventional name that matches a component rendering phase. We will take advantage of this method to initialized a new Article, if needed.

The onSuccessFromNewArticleForm is again a conventional method name to handle a component event. On that case, the event is "success", and we await it from the "articleForm" component... which is our form's "t:id". So, you get it, when the form succeed, we go into that method, in which we try to save the Article. If the DAO failed in its job, we raise an error, and else we redirect into the ManageArticle page. There is a lot of way to redirect to a page in T5: you can use URL, page class, the string page name, or the InjectPage annotated page. This method is handy when you need to init some value in the page before redirecting to it. Well, here it's just because it's cool ;).

And now, we are redirected to the "manate" page.

Manage all articles



The goal of this page is to give the author the possibility to view the list of all existing articles. Moreover, we want to be able to go there detail page, to publish or unpublish, edit and delete them.

In this case, the perfect component is the grid component.

This component allows to display a list of beans, one column by property, and allows to add, remove, reorder columns.

The template looks like that:


<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">

<h2>List, modify, publish article</h2>

<t:grid source="articles" row="article"
reorder="title" exclude="content" add="comments,publish,edit,delete">

<t:parameter name="titleCell">
<t:pagelink t:page="article/view" t:context="article.displayid">
${article.title}
</t:pagelink>
</t:parameter>

<t:parameter name="publishCell">
<t:actionlink t:id="changePublication" t:context="article.displayid">
${changePublication}
</t:actionlink>
</t:parameter>

<t:parameter name="commentsCell">
${article.comments.size()}
</t:parameter>

<t:parameter name="editCell">
<t:pagelink t:page="article/edit" t:context="article.displayid">
edit
</t:pagelink>
</t:parameter>

<t:parameter name="deleteCell">
<t:actionlink t:id="delete" t:context="article.displayid">
delete
</t:actionlink>
</t:parameter>

</t:grid>
</t:layout>


What looks in real like:



There is some interesting things in this template:
  • we have a source of bean, and the current Article is handle in the "row" parameter;
  • the "t:parameter" is special invocation that allows to bind a block of template code to component parameter. In our case, each t:parameter is used to replace the content of a column cell;
  • the pagelink component has already been seen several times, but here can see how easy it is to map page to URL: it's simply the list of directories from the "pages" package to the page object. We also see how we can pass a some context (variable) into the targeted page;
  • lastly, the "t:actionlink" is a component that allows to fire an event on the server side;


So, how we handle all that on the server side ?

org.example.blog.pages.article.ManageArticle.scala

class ManageArticle {

@Inject
var rwDao : ReadWriteDao[Article, String] = _

@Property
var article : Article = _

def getArticles = this.rwDao.getAll.sort( _.creationDate.getTime > _.creationDate.getTime ).toArray

def getChangePublication = if(article.published) "Un-published" else "Published"

def onActionFromChangePublication(id:String) {
val a = this.rwDao.get(id).getOrElse(error("No such article, id: " + id) )
a.published = !a.published
this.rwDao.save(a)
}

def onActionFromDelete(id:String) {
if(!this.rwDao.delete(id)) {
error("Can not delete this article")
}
}
}


The code is fairly simple and clear:

  • we need the ReadWriteDao, so we inject it;
  • we need an article to keep the current row, so we add an @Property annotated Article;
  • the source of all bean is provided by the "getArticles()" method, that simply retrieve all the articles from DAO (and sort them by date);
  • the "getChangePublication()" return the good text given the status of the article;
  • the "onActionFromChangePublication" method handle the event from the actionLink with "t:id" changePublication. The method await a parameter which is given by the context of action link (and is the article id). We react at this event by changing the status of the matching article, and save it back into the DAO;
  • finally, the "onActionFromDelete" handle the event from the "delete" link, and react to it by deleting the article from the DAO.


Note that all event handler that does not return anything redirect to the calling page.

Final words


Conclusion



And that's done ! The goal perimeter is reached, we can see, add, manage articles in a not too ugly blog.

Now, a lot of things remained:
  • Articles are not really persisted, and are lost on server shutdown. What abot saving them into a database, or even better into a more "text oriented" storage, has XML files, or something like a Java Content Repository (or a CouchDB ?)
  • Where are the comments ?
  • And the article details ? And all the formating of articles is lost in rendering ! That's awful ! Perhaps we need a smarter rendering component... and so we may used it at several place around the site (Index, article details...)
  • And what about a better text editor, that allows some kind of rich UI ? Personally, I really like showdown editor
  • And tags, hu ? We are building the tomorrow blog plateform for web 3.0 and don't even have tags ? That can't be serious !
  • oups, somebody just pointed that for now, there is no way to protect the manager area from the simple user... No authentication, no authorizations...
  • I also said that I will attempt to use easy-ant as build tool, in place of maven
  • and the list is almost infinite !


So, there is still some room to a little more experiment with T5 and Scala !

Source code



As always, the source code is available on the GitHub repository of the project.

To download and test the code for that articles, simply executes these commands:

% git clone git://github.com/fanf/scala-t5-blog.git
% cd scala-t5-blog
% git checkout -b test article3_20090119
% mvn jetty:run


Enjoy, and see you next time !

  © Blogger template 'Minimalist G' by Ourblogtemplates.com 2008

Back to TOP