Sunday, December 16, 2007

GroowyWS 0.2.0

It has been a long time since I talked about GroovyWS ... Groovy has been out for a week now and I have been working a bit on GroovyWS as well so I decided to push a new version. The changes brought by this new version are minor in term of workload but they should (hopefully) made GroovyWS more usuable in a production environment.
The first change deals with https support. Now you cab use the WSClient with a serving using secure http. This has been tested using Amazon S3 web services:

def proxy = new WSClient("https://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl",..)

You can now create buckets :-)

The other major change is the support for servers using basic authentication. So if your server requests to have an "Authorization: Basic bG9naW46cGFzc3dk" header in the request, you are able to set the correct properties using:

System.props["http.user"] = "login"
System.props["http.password"] = "passwd"

Do not forget that the token transmitted is just a base64 encoding of "login:passwd", so basically your are transmitting your credentials in clear text :-). You don't trust me ? Try this:

echo -n 'login:passwd' | openssl enc -a -e

or

echo 'bG9naW46cGFzc3dk' | openssl enc -a -d

Only use this over https !

The last minor change is to publish the SOAPAction property in the WSDL generated by the server. This makes odd commercial products work with WSServer !

What are the next steps ? I would like to add WS-Security support. This is something I already have partially, I am missing a public server to test it and would like to know how you would envisage its usage using groovy. So if you have any idea, do not hesitate to contact me ...

Sunday, August 26, 2007

GroovySOAP is now GroovyWS

It has been a long time without news. The fact is that I have been moving from France to Singapore and that keeps me busy with and away from the keyboard. Anyway I am back. You probably now that CXF has taken over XFire. Thanks to the work done by Dan & Al, the move has been pretty fast and we now have the best from XFire & Celtix.
I thought it was time to move also from GroovySOAP (relying on XFire) to GroovyWS (build on top of CXF). What are the difference so far ? If you choose GroovyWS you will have to use Java5 but you will gain an easiest way to build your clients (no worries about the complex types, they are automatically generated) and a proxy support.
In the future, I will probably start to work on basic authentication as this has been asked several times.
The build can be found here.

Friday, August 24, 2007

Songs of the sea

Hier, soir nous avons passé la soirée à Sentosa accompagné de Jean-Yves et David. On peut accèder à cette île (destinée uniquement aux loisirs) par différents moyens. Cette fois-ci, David avait choisi les oeufs (oui vous avez bien lu) afin de nous faire profiter de la vue sur la ville. Au programme: "Songs of the Sea" un spectacle réellement féérique fait de feux (follets) et de jeux de lumières et de lasers projetés sur des jets d'eaux. Le spectacle raconte l'histoire de Li - jeune homme doté d'une voix charmeuse. Li et ses amis découvrent l'existence de la princesse Ami sous l'emprise d'un village enchanté. Réussiront-ils à la délivrer avec l'aide des créatures de la mer ?

Bon allez, si vous voulez la réponse il vous faudra venir découvrir le spectacle ... Bon, au pire nous vous avons mis quelques photos ici.

Sunday, August 19, 2007

Visite au zoo

Première semaine à Singapour ! Après avoir tenté d'évaluer les différents moyens pour aller de notre nouveau domicile au boulot (1h15 ;-) ), le premier week-end nous a permis de souffler un peu. Samedi, ce fut direction le centre ville afin de rendre visite au Merlion (emblème de Singapour) situé en bord de mer, puis de faire du shopping chez Carrefour: nostalgie oblige. Dimanche, direction le zoo à une trentaine de minutes de chez nous (bus 138 !), on en a pris plein les yeux avec des animaux inconnus chez nous (par exemple les tragulidés - oui je sais ils ne sont pas particulièrement beaux !). Aux programmes: perroquets colorés, caméléon, singes en tout genre, lémuriens, éléphants et de nombreux autres que je vous invite à découvrir ici . Nous avons même pu découvrir quelques serpents fort peu recommendables qui trainent par ici.

A bientôt, pour de nouvelles aventures.
Posted by Picasa

Wednesday, May 9, 2007

Embedding Google Maps in your Groovy application

Google provides a wide variety of API for embedding their applications into your web pages. They are very convenient if your are developing web applications but I find it very painful to embed them into any Java application. Hopefully as far as GMaps is considered, the swingx-ws project is providing a JXMapViewer class in which you can configure a tile provider for using the Google map servers. Let's use Groovy to build a small apps using Google geocoding and putting some information on a map.

Central to our small application is the JXMapViewer. Each mapviewer is associated to a tile factory which delivers the image pieces. Once configured, the mapviewer will take care of the rest querying the map server when required depending on your location. Configuring the tile factory is the more tricky part of the snipplet, here are all the arguments of the constructor:

def tfi = new TileFactoryInfo(0, 20, 17, 256, true, true,"can't disclose", "x", "y", "zoom")

The first four numbers to the TileFactoryInfo constructor represent the minimum zoom, the maximum zoom, the total zoom levels, and the tile size (very often a tile is a 256 pixels square) . The two booleans are used to indicate if the x coordinates go left to right or right to left and if the y coordinate goes from top to bottom or out from the equator. The rest of the parameters are for the base url and the name of the http parameters in the get request to fetch tiles.

Let's continue by defining our Swing interface including the JXMapViewer. Here the code defining our panel which includes a textfield (in which you could type an address), the widget containing the map viewer and two buttons for zooming in and out.


import java.awt.*
import java.awt.BorderLayout as BL

import javax.swing.*
import javax.swing.WindowConstants as WC
import javax.swing.JOptionPane as JOP
import javax.swing.BorderFactory as BF
import javax.swing.SwingUtilities as SU

import org.jdesktop.swingx.mapviewer.*
import org.jdesktop.swingx.JXMapViewer

import groovy.swing.SwingBuilder

def googleKey = "your google api key"

def mapViewer = new JXMapViewer()
def tfi = new TileFactoryInfo(...)

mapViewer.tileFactory = new DefaultTileFactory(tfi)
mapViewer.zoom = 5
mapViewer.centerPosition = [48.856558, 2.350966] // Paris

def swing = new SwingBuilder()
def frame = swing.frame(title: 'Groovy Maps',defaultCloseOperation:WC.DISPOSE_ON_CLOSE) {
panel(id: "mainPanel", layout: new BL()) {
panel(constraints: BL.NORTH, layout: new BL()) {
textField(id: "address", constraints: BL.CENTER, columns: 50,
border: BF.createTitledBorder("Address"), actionPerformed: {
def address = swing.address.text
// geocoding code here
}
widget(mapViewer)
panel(constraints: BL.SOUTH) {
button(text: "+", actionPerformed: { mapViewer.zoom -= 1 })
button(text: "-", actionPerformed: { mapViewer.zoom += 1 })
}
}
}
frame.pack()
frame.size = [800, 600]
frame.locationRelativeTo = null

frame.visible = true



Using the Google geocoder is pretty simple when using an http request to http://maps.google.com/maps/geo? with the following parameters in the URI:
# q, the address that you want to geocode,
# key, you API key,
# output , the format in which the output should be generated. In our example, we will use xml, the other options are kml, csv, or json.

In our case, the address will come from a texfield so the code looks like this:

textField(id: "address", constraints: BL.CENTER, columns: 50,
border: BF.createTitledBorder("Address"), actionPerformed: {
def address = swing.address.text

// geocoding
SU.invokeLater {
Thread.start {
def geocodingUrl = "http://maps.google.com/maps/geo?q=
{URLEncoder.encode(address)}&output=xml&key=${googleKey}".toURL()
def node = new XmlSlurper().parseText(geocodingUrl.text)
if (node.Response.Status.code == "200") {
def coord = node.Response.Placemark.Point.coordinates.text().
tokenize(',').collect{Float.parseFloat(it) }
mapViewer.centerPosition = coord[1..0]
}
}
}
})


Assemby all the pieces give you the global application ...

In conclusion, JXMapViewer is a powerful component that make it easy to embed maps in your groovy application. In a next stage, I will show you how to add more information in a different layer.

Wednesday, May 2, 2007

J-7 for JavaOne 07

Now that Groovy-1.1-BETA-1 and Grails-0.5 are out, it's time to focus on JavaOne. There will be an important presence for both projects since at least 8 sessions are mentioning Groovy. Apart from these sessions, two other events are worth to attend:
# On May 7, if you are in SF and are interested by dynamic languages - don't miss the RedMonk unconference track during the CommunityOne event,
# On May 8, join the Groovy and Grails community for the Groovy/Grails One Meet-up at the W Hotel from 6:30pm.

And probably many more to be announced !

Groovy is enterprise ready

It has been a long time since my last post. But important things are happening for enterprise scripting. Yes, Groovy-1.1-beta-1 was released yesterday. This release has new features that could speed up its adoption at the enterprise level. In this post, let's focus on annotations that is something brought by Java 5. Nowadays, annotations are everywhere from Spring Framework, Hibernate, TestNG to the newcomer Google-Guice lightweight dependency injection framework.
Let's see how Guice and Groovy can be used jointly.
All you need is a fresh Groovy 1.1-beta-1 install and guice-1.0.jar and aopalliance-1.0.jar from Google-Guice. As an example, I will use the stupid mathematic application I am using for the GroovySOAP tutorial.
Let say, you have an addition contract like this one:

import com.google.inject.*
interface Calculator {
def add(a,b)
}

Here is an obvious instanciation of that contract (this should be implemented as a singleton):

@Singleton
class CalculatorImpl implements Calculator {
def add(a, b) {a + b }
}

The next step is to write the client that will need that service to be injected. In Groovy, this is as simple as shown below. The @Inject annotation is used for that purpose.

class Client {
@Inject
Calculator calc

def executeCalc(a, b) { calc.add(a,b) }
}

What is not yet done is the wiring between our client and the implementation class. This can be done programmatically using the so called Modules in Guice. Here is what I am doing here:

class MyModule implements Module {
void configure(Binder binder) {
binder.bind(Calculator).to(CalculatorImpl)
}
}

At this point, we are done. Here is how you can use your client in Groovy:

def injector = Guice.createInjector(new MyModule())
def client = injector.getInstance(Client)
assert 3 == client.executeCalc(1,2)

If you want to learn more on this topic, here are further reading on Guicy by MrG and some early experiment on JPA and annotations in Groovy by Romain.

Monday, April 2, 2007

L'ainée est blonde

Le facteur apporte une lettre à une dame; il dit : "Vous avez trois filles, quel age ont-elles respectivement ?" La dame répond en souriant:"Le produit de leur age est 36, et leur somme est égale au numéro de la porte d'en face." Le facteur se retourne, hésite, puis dit: "Il me manque un renseignement."

La dame dit:"Oui, l'ainée est blonde."

Quel est l'age des trois filles ?