Thursday, November 12, 2009

Bootstrap GWT2 with maven, UiBinder and i18n

I'm setting up a boostrap project for GWT 2 witch would use maven 2, UiBinder and i18n.
The idea is to centralize resources about UiBinder and test GWT 2, the result being used as a template project for real GWT 2 projects.

I'm quite new to GWT (2 days old...), so it is also a learning project. If it could be of any use for you, don't hesitate to use it - or enhance it, or make comments :)

For now, it's based on GWT 2.0.0-ms2, and some configuration may be specific to my environment (Linux&Firefox 3.5).

It's available here: http://github.com/fanf/gwt2-mvn-bootstrap

Tuesday, November 10, 2009

Maven2 bootstrap pom.xml for SLF4J and no-commons-logging

Each time I start a new Java project with Maven 2, I need to write the same dependencies again and again: SLF4J and no commons-logging because it's evil (and SpringFramework seems to want to keep it), Joda Time by default, some properties, etc.

So, that's the template pom.xml I use for the bootstrap, if it may help anybody here (it uses logback for logging, as it's more efficient than Log4j with SLF4J, but feel free to use what you want):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.test</groupId>
  <artifactId>test</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <!-- UTF-8 for everyone -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <slf4j-version>1.5.8</slf4j-version>
    <logback-version>0.9.17</logback-version>
  </properties>

  <description>Template for project without Commons-logging</description>

  <repositories>
    <repository>
      <id>no-commons-logging</id>
      <name>No-commons-logging Maven Repository</name>
      <layout>default</layout>
      <url>http://no-commons-logging.zapto.org/mvn2</url>
      <snapshots><enabled>false</enabled></snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
  </pluginRepositories>

  <build>
    <plugins>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>1.6</version>
    </dependency>

    <!--  test -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>

    <!--
      All the following is related to our will to NOT use Commong-logging. Never. 
      And framework we depend on won't bring commons-loggin nether (I'm looking at
      you, stringframework).
    -->
    <!-- use no-commons-logging -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>99.0-does-not-exist</version>
    </dependency>
    <!-- no-commons-logging-api, if you need it -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging-api</artifactId>
      <version>99.0-does-not-exist</version>
    </dependency>
    <!-- slf4j commons-logging replacement -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>${slf4j-version}</version>
    </dependency>
    <!-- other slf4j jars -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j-version}</version>
    </dependency>
    <!-- using slf4j native backend -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>${logback-version}</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>${logback-version}</version>
    </dependency>
  </dependencies>
</project>

Saturday, October 24, 2009

Clone objects with arguments override in Scala 2.8: best practices ?

I'm actively looking for best practices and patterns about how to create clone objects in Scala, with the possibility to change some values of the cloned object along the way.

I have the usual concern of the Java world on that topic: I would like to avoid Java "clone", I want to be able to use the pattern in a class hierarchy, I want to have the minimum amount of code (or at least, the simplest possible) to write in domain class to support my cloning API.
And as I'm in Scala, I want to deal with both vars and vals, if possible in the same consistent way.

Actually, I want to provide to my libraries consumer an effective way to do things like that (where *Child* extends *Parent* class):



    val p = new Parent("some value")
    // simple cloning
    val p2 = p.copy
    //clone, and change a val and a var along the way
    val p3 = p.copy(p_val1 = "new value for val", p_var1 = "new value for var")

    //and same things apply for children of Parent:
    val c = new Child("some parent value", "some child value")
    //override child val/var and/or parent val/var in the same fashion
    val c1 = c.copy(p_val1 = "new value for val defined in Parent class",
                    c_val1 = "new value for val defined in Child class",
                    p_var1 = "new value for var defined in Parent class",
                    c_var1 = "new value for var defined in Child class" )


As Scala 2.8 is advertised with "default and named arguments", such things should possible (well, hopefully easy too ;). I came with this solution:



class A(val val_a:String)  {
    var var_a = ""
}

object A {
    def merge[T](t:T)
    (
        var_a : String
    ) : T = {
        t match {
            case x:A => x.var_a = var_a
            case _ => error("")
        }
        t
    }
    
    def copy(source:A)
    (
        val_a : String = source.val_a, 
        var_a : String = source.var_a
    ) : A = merge(new A(val_a))(var_a)
}

class B(override val val_a:String, val val_b : Int) extends A(val_a) {
    var var_b = 0
}

object B {
    def merge[T](t:T)
    (
        var_a : String,
        var_b : Int
    ) : T = {
        A.merge(t)(var_a) match {
            case x:B => x.var_b = var_b
            case _ => error("")
        }
        t
    }
    
    def copy(source:B)
    (
        val_a : String = source.val_a,
        var_a : String = source.var_a,
        val_b : Int = source.val_b,
        var_b : Int = source.var_b
    ) : B = merge(new B(val_a,val_b))(var_a,var_b)
}


class C(override val val_a : String) extends A(val_a)

// ***************** 
// Example of use
// ***************** 

object TestCloning {
    
    def main(args:Array[String]) {
        val a1 = new A("la_init")
        a1.var_a = "ra_init"
            
        val b1 = new B("lb_init",1)
        b1.var_a = "rb_init"
        b1.var_b = 10

        //example with A

        val a2 = A.copy(a1)()
        assert(!(a1 eq a2))
        assert(a2.var_a == a1.var_a)
        assert(a2.val_a == a1.val_a)
        
        val a3 = A.copy(a1)(val_a = "la_mod")
        assert(a3.var_a == a1.var_a)
        assert(a3.val_a == "la_mod")
        
        val a4 = A.copy(a1)(val_a = "la_mod", var_a = "ra_mod")
        assert(a4.val_a == "la_mod")
        assert(a4.var_a == "ra_mod")

        val a5 = A.copy(new C("foo"))()
        assert(a5.var_a == "")
        assert(a5.val_a == "foo")

        val a6 = A.copy(b1)()
        assert(a6.val_a == "lb_init")
        assert(a6.var_a == "rb_init")
        
        //with B
            
        val b2 = B.copy(b1)()
        assert(b2.val_a == "lb_init")
        assert(b2.var_a == "rb_init")
        assert(b2.val_b == 1)
        assert(b2.var_b == 10)
            
        val b3 = B.copy(b1)(var_b = 5, val_a = "lb_mod")
        assert(b3.val_a == "lb_mod")
        assert(b3.var_a == "rb_init")
        assert(b3.val_b == 1)
        assert(b3.var_b == 5)
            
    }

That solution seems to work, and allows to do the kind of use case I wanted to build.
But it seems not satisfactory at all for (at least) these reasons:
1/ - the trailing "()" in real clone without override is mandatory and doesn't look right;
2/ - it seems to be a lot of tedious code to write in each class, and so seems to be really error prone;
3/ - I'm not at ease with the merge method, but I can't say why exactly;
4/ - I don't like to much the factory approach.

1/ could be easily addressed if in place of only a copy(source:X)(.....) we define a couple of method :
    def copyWith(source:A)( ... ) : A = merge(...)(...)
    def copy(source:A) = copyWith(source)()

3/ and 4/ are just feelings, and so could be shut up for now.

But 2/ is a real concern, and I would like to find a way to externalize more code in traits, so that domain classes have only simple, short code to write to provide a clone API.
 
So Scalazy, what are your best practices about the cloning topic in Scala ?

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.

Sunday, September 20, 2009

Faster log in in Ubuntu 9.10 "Karmic Koala" and e17

I'm a long time user of Enlightenment 17, or e17. I mean, a really long time user, since I used it since the end of 2004 or so. If I kept it for so a long time dispite of all its rough edges, it's because I love a lot of things in e17, like the default windows and mouse focusing behaviour, the possibility to have a lot of cool and usefull desktop effects with a real open source driver that doesn't support 3D acceleration.


But what I like above all the the speed of the the environement. In e17, everything seems to be quick and responsive - well almost everything, Firefox and OpenOffice are what they are ;)
For example, the login process in e17 takes a couple of second. I mean, really a couple: I validate my user/password in GDM, and hop, my desktop environement is fully-loaded and usable.

OK, so why I'm talking about that ? Lastly, I tried the new Ubuntu Karmic Koala Alpha 5. Before anything else, I do know what alpha means, and I'm not saying anything against Ubuntu, things are expected to enhance until end of october.
Among a loads of other things, Karmic Koala introduces a new transition screen when X is loading, in order to smoothen a little transitions : XSplash. The problem is that XSplash doesn't seem to be aware of the speed of e17, and when you login, it loops for quite a long time (perhaps 20 seconds ?) before letting the desktop be shown.

So, the solution is simply to disable XSplash for the login, and let e17 loads within its 2 seconds:
in the file /etc/gdm/PreSession/Default comments the things related to XSplash, or if "Default" file only contains XSplash related things, disable it like that (of course, be aware that as Ubuntu is only in alpha phase, this file may be use for other things that Xsplash in the future, and you can break other things with that) :


mv /etc/gdm/PreSession/Default /etc/gdm/PreSession/Default.disabled


That's all ! Now, you can enjoy the lightning login speed of e17 on Ubuntu Karmic Koala.

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)

Sunday, June 7, 2009

A Tour Of Scala @ OSSGTP - Paris OSS user group

Thursday (4 june 2009), I gave a presentation about the Scala programming language to the OSSGTP group (Open Source Software - Get Together in Paris).

This presentation is available under Creative Common BY-NC-SA, so you are free to download the source, use it, enhanced it and redistribute it !





PS: let me know if you see any errors, or if you use it, it will make me happy
PPS: I took inspiration from "Programming in Scala" book by Martin Odersky, Lex Spoon and Bill Venners, "Pragmatic Real World Scala" by Jonas Boner, "A Scalable Language" by Martin Odersky and "The feel of Scala" by Bill Venners - thanks for their great presentations and books !

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...

Tuesday, April 21, 2009

So, Sun is no more - Oracle is one of the big three

At the beginning, I though I wouldn't write about it. After all, all the Internet is talking about it, and I'm just a little developer, with my little biased view of the world through my small experience. But the thing may be so impacting for my daily life, and well Sun was such an uncommon adventure of a company, I wanted to mark the day. The following is just my thoughts on that big thing, take them as no more than that.

So, yesterday Oracle announced to the world that they bought Sun for something like $7,4 Billions.
My first feeling was (is) "better being Oracle than IBM". All in all, it may even be good. But wow, what a concentration ! Now, the "business software solution" industry is shared among 3 bigs (MS/IBM/Oracle), and that's all. And Oracle owns the database market, both opensource and proprietary.

So, more in details, I thing that there is 3 domains of Sun that will be push foward by Oracle:
- MySQL ;
- the Java platform ;
- Hardware, Solaris and related knowledge.

Hardware and Solaris
The hardware and Solaris part are, I think, the domains with the clearer future : they will become the preferred platform for hight performance, highly tuned, very very expensive SGBD server and Business app server.
For me, that's the main point why Oracle is better than IBM : Oracle WANT these missing layers in their integrated stack, and IBM would have killed Sparc and Solaris, their old rivals. So, be prepared for Sparc/Solaris/Oracle SGBD killer servers, with Sun^W Oracle storage solutions, to make run your Sparc/Solaris/Weblogic business application servers.
Moreover, we could see some really cool and great things happen in the filesytem domain: just think that ZSF, btrfs and OCFS(2) fathers are now in the same company...

MySQL
I don't fear anything for MySQL. Oracle bought InnoDB not so long time ago, they already thought to buy them at the same moment Sun did. MySQL could become their "low level" offer, and all the big customer will be encourage to switch to Oracle DB with wors like "you know, we own both system, but clearly you, you need our most expensive one, the one that works best".


The Java language and the Java platform
Oracle have a lot of business application build on Java, and now they own the platform. They also have two JVMs.
Oh, and they make money with the techno, something Sun never succeeded to do.

So clearly, Java was a BIG motivation for the operation, and Oracle will want to promote at the maximum its platform against opponents. And a better platform whould lead to better softwares, no ? :)

The real question is about policies. What will happen to JCP ? In the current model, the guerilla beside Sun and IBM was famous, things could become even worst now... Will Oracle try to follow MS way in the management of its software platform evolution to avoid it ?

Less clear points
My real interrogation are around Sun existing application, and Oracle behavior toward OpenSource.

Netbeans may be a winner here, even if Oracle seem to have taken interests onto Eclipse. But what will happen to Glassfish ? The v3 is amazing, it's still a reference implementation of JEE, but there's Weblogic... So, Glassfish has the low level / test solution, and Weblo for "real things" ?

Even more frighting, what will happen to Sun's (really good) Identity and Access Management solution (OpenDS, OpenSSO, Identity Manager, etc) ? Oracle was a frontal concurrent here, I don't see them keep both offers...

And what will happen to the Sun clear move toward open source ? Oracle is not reluctant to OSS (I mean, at least not more than IBM), and they contributed some really nice stuff in the last years (btrfs for example). But they are not exactly an open source company, to say the least.

So, what next for us ?
So, my best hope is that Oracle will free a lot of technical/low level stuff, like filesystem, a JVM, etc. That kind of stuff has little added value (in dollars) for them, and they might attracts a lot of geek / small companies to work on and make them better. On the other hand, Oracle keep their higher level, more business oriented, and far more profitable middlewares as incomes sources.

To conclude, there is one thing that I'm sure of: "It's tough making predictions, especially about the future", as would say Yogi Berra. Or Neils Bohr. Or Mark Twain. Or was it Robert Storm Petersen ? Well, at least, what is done is done, and let's see what will happen !

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...

Tuesday, March 3, 2009

Small UTF-8 URL

I just found this site thanks to reddit : http://www.reddit.com/r/programming/comments/81ld2/tinyarrows_what_do_you_think_site_we_made_to/

The goal is to build tiny URL from long ones, something as old as the Internet. The difference is that the URL can be build with UTF-8, what gives you funny opportunities :)

So now, you can access my blog with these URL :

http://➡.ws/φ
http://➡.ws/φ42

Ok, that's something a little useless, but it's cool and funny :)

Sunday, February 15, 2009

Personal thougth: Scala, Haskell, Coq and so little time !

There is a lot of really cool stuff going on the world in computer science and more precisely in formal proof, the last I found being: this article about "A Monadic, Functional Implementation of Real Numbers"

Haskell is continuously gaining attention, Scala and Clojure bring new dimensions to the JVM, this later (hopefully) evolving towards better support for functional paradigm and perhaps more verification support.

I'm lucky enough to have already worked in formal proof with the CompCert team when I graduated... but it was 5 years in the past.

In the meantime, I worked in the "real life business", and now I'm sure this don't feat to me. Well, at least I worked in the security domain, and discovered that their is some really hight level work done in this domain in France: two years ago, Gemalto proved a never reached level of certification for the JavaCard plateform:
http://www.gemalto.com/php/pr_view.php?id=239 . And they did it with Coq, what a coincidence :)

Well, I really want to spend a lot of more time in all these fields. So much things to do, so little time to spend in them...

EDIT: I forgot all the cool things around parallelism, Pi-Calculus, or actors (I believe there is something great that is on the way with Scala actors ;).

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 26, 2009

Ivy 2.0 released

The java library dependency management system Ivy finally reached the 2.0.0 released, and that's a great new.

The release note is here:
http://ant.apache.org/ivy/history/2.0.0/release-notes.html

(for the lazy clicker, here is the announcement part of the release note:)


Jan 20, 2009 - The Ivy project is pleased to announce its 2.0.0 release.
This is the first non-beta release of Ivy under Apache.

Ivy is a tool for managing (recording, tracking, resolving and
reporting) project dependencies, characterized by flexibility,
configurability, and tight integration with Apache Ant.

Key features of the 2.0.0 release are
* enhanced Maven2 compatibility, with several bug fixes and more
pom features covered
* improved cache management, including dynamic revision caching
with fine grain TTL
* improved concurrency support with cache locking and atomic publish
* namespace aware validation, allowing to use validation with
extra attributes
* new 'packager' resolver added
* better and more homogeneous relative paths handling
* better support for local builds
* numerous bug fixes as documented in Jira and in the release notes

We encourage all users of Ivy to update to this new version.

Issues should be reported to:
https://issues.apache.org/jira/browse/IVY

Download the 2.0.0 release at:
http://ant.apache.org/ivy/download.cgi

More information can be found on the Ivy website:
http://ant.apache.org/ivy/

Regards,
Maarten Coene


Note: I'm in now way implied in the Ivy dev-team, I just love their tool and wanted to thanks them for it.

Ivy seems to be loved by new "build system" make. Gradle, the Groovy buildr, is based on Ivy.
I will also signal the on-going work around an "maven-style build system with a stack of convention" build on top of Ivy and Ant, easy-ant (and there is an irc chan on freenode: #easyant). The project is work-in-progress, but a lot has already been done, and I believe it will be a great solution for all of us that are pissed-off by Maven, or just can't move from Ant but want to normalized (or "base on conventions") their build scripts, and integrate Ivy.

Note 2: I'm neither implied in easy-ant dev ;)

So, it seems that Maven is not the final winner in Java build system land, and that's good (no monopole, concurrency for the best...) !

Update: I simply forgot to link to Xavier Henin blog post about Ivy 2.0.0 release. Shame on me :/

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