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

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

Back to TOP