Archief voor categorie Uncategorized
Meld je nu aan voor de AgileMDD kennissessie op 30 maart
Geplaatst door Richard van der Laan in Uncategorized op maart 10, 2010
![]()
Luminis Software Development en ArchitecIT nodigen je graag uit voor een kennissessie over model-driven development.
We laten deze avond graag zien waarom modellen steeds belangrijker worden en hoe je er succesvol mee kunt zijn. De hele kennissessie zal in het teken staan van praktijkervaringen.
Aan de hand van vijf verschillende thema’s delen sprekers van diverse organisaties hun ervaringen met MDD in de praktijk: Thales Hengelo, Ministerie van Defensie, ArchitecIT, Delphino Consultancy en luminis.
In onze visie is het noodzakelijk om de ontwikkelkracht slimmer in te zetten, niet in de laatste plaats door de enorme toename van complexiteit in softwareintensieve systemen. In de praktijk zijn is er nog veel communicatie (overdrachtsmomenten) en bestaan de meeste ontwikkeltaken uit veel handwerk. Op basis van een pragmatische en doelgerichte aanpak kunnen ontwikkeltaken snel worden geautomatiseerd en kan de onderlinge communicatie worden verbeterd.
Datum: dinsdag 30 maart van 16:45 tot 20:00 uur
Locatie: IJsselburcht 3, 6825 BS, Arnhem
Voor wie: Architecten, ICT Managers en belangstellenden
Aanmelden: U kunt zich aanmelden per email door contact op te nemen met Inge Dokter
Het programma:
16:45 Opening in de grote zaal
17:00 Agile MDD: huidige trends en ontwikkelingen (Tony Sloos, Richard van der Laan)
17:30 MDA in realtime heterogene systemen (Rene van Hees, Alexander Broekhuis)
18:00 Lopend buffet
18:30 Microsoft DSL Toolkit in de praktijk (Gerrit Jan Timmermans, Erik Sanders)
19:00 MDD en software architectuur (Angelo Hulshout)
19:30 MDD kansen en risico’s (Andriy Levytskyy)
20:00 Afsluiting met borrel
Graag ontvangen we je aanmelding zo snel mogelijk, maar in iedergeval voor 12 maart. Aan deelname zijn geen kosten verbonden.
Je kan je aanmelding sturen naar Inge Dokter (inge.dokter@luminis.nl)
We hopen je te zien op dinsdag 30 maart!
Online video: Beyond OSGi software architecture
Geplaatst door Richard van der Laan in Uncategorized op januari 22, 2010
Op 11 november 2009 gaf Marcel Offermans samen met Jeroen van Grondelle (Be Informed) een duo presentatie over “Beyond OSGi software architecture”. De video van deze presentatie is inmiddels online beschikbaar. De gehele presentatie van 50 minuten kan je hier downloaden. Maar de eerste tien minuten zijn hieronder gelijk online te bekijken.
OSGi is niet meer weg te denken uit het Enterprise Java domein. Dit lightweight framework krijgt al een aantal jaren flinke aandacht en is met name bekend om z’n modulaire applicaties op basis van bundles. Minder bekend is het services model, waarbij applicaties worden ontwikkeld op basis van service interfaces en van elkaar ontkoppelde implementaties (POJO’s) van die interfaces. Krachtige eigenschappen van dit model zijn:
- complexiteitsreductie door stricte scheiding van services;
- declaratieve services en dependency management (IoC);
- aspect oriëntatie op basis van stub services;
- security model.
Lean software is een nieuwe manier om enterprise applicaties te bouwen op basis van OSGi, die ook goed aansluit bij Agile methoden, waarbij non-functional requirements ingevuld kunnen worden in een compact gebleven framework. In die context kijken we naar:
- applicaties deployen op allerlei platformen en omgevingen;
- applicaties automatisch installeren en updaten;
- applicaties voorzien van management interfaces;
- product software uitbreidbaar maken middels een SDK;
- product software verkopen als combinatie van standaard onderdelen en optionele uitbreidingen;
- modulaire User Interfaces.
De slides van de presentatie zijn te vinden op de NLJUG website.
Swing & OSGi — please play nice!
Geplaatst door Angelo van der Sijpt in Uncategorized, java op november 18, 2009
In a recent blog by Peter Karich, he showed how to create a pluggable Swing application using OSGi. While this works fine for smaller examples, you might run into more serious issues once you application starts to grow.
Plugging Swing: it leaks?
Let’s start with an application not unlike the one from aforementioned blog; it uses a window as host, and has a pluggable menu, and a pluggable table.
You can find the code we used at the end of this entry (or, for the impatient, here).
Using this pluggable system, we could end up with several curious situations. For instance, you might have a mixed look and feel in you application.
Or worse, you might end up with a UI that (sometimes) fails to start, and spits a stacktrace your way.
It leaks, but why?
Our host, and all components have been stored in separate bundles, meaning we don’t have full control about the order in which actions are performed (more about that later). However, we do know there are orders of execution that are less than ideal; let’s force one of those.
The project contains an Ant script to make things easier. From the root of the extracted project, run
$ > ant run1This starts the framework, installing the necessary bundles, but does not start them (note that this step uses Pax Runner, and therefore needs internet access). We can now start our bundles in the order we like.
A tale of two look-and-feels
After starting the framework, wait for the “Welcome to Felix” message, and run
[java] Welcome to Felix [java] ================ [java] start 2 start 1
The situation arises because the look and feel is a static concept in Swing. The menu bundle creates its JMenu before (see Menu.java, ln 30) the host sets its look and feel (Host.java, ln 51), and keep that look and feel, even when the host bundle changes it later.
Tables, ScrollPanes and NPEs
The NullPointerException above is a different story, but it goes back to the same staticness of Swing too. To force this situation, start only bundle 4.
[java] Welcome to Felix [java] ================ [java] start 4 [java] Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException [java] at net.luminis.swingosgi.part1.scrolltable.impl.TableComponent$1.run(TableComponent.java:31) [java] at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) [java] at java.awt.EventQueue.dispatchEvent(EventQueue.java:633) [java] at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) [java] at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) [java] at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) [java] at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) [java] at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) [java] at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Let’s take a look at the line where this NPE happens:
JScrollPane scrollPane = new JScrollPane(table); scrollPane.getColumnHeader().setBackground(Color.blue); m_panel.add(scrollPane);
We know that the ColumnHeader is null. This is because its JTable’s responsibility to create the header, but this is only done once the table knows it is part of an AWT hierarchy. The following lines come from the 1.5 JDK on a Mac; configureEnclosingScrollPane() creates the column header. This addNotify method comes from Component, and notifies of, exactly, the event of being added to an AWT container.
public void addNotify() { super.addNotify(); configureEnclosingScrollPane(); }
Order, order!
So, the static nature of Swing and the dynamic nature of OSGi seem to hurt each other seriously here.
One way to get the application right is by fixing the order in which Swing components can be created. By starting bundle 1 first in our application, we at least fix the look and feel. Getting the scrolling table to run correctly is an entirely different story.
Regarding order, a few possible solutions spring to mind immediately,
- Put all UI stuff in one bundle
- Use OSGi bundle start levels
Sure, all UI in a single bundle will give you the control necessary, but it also defeats the purpose. OSGi start levels can at least solve the ordering issues, but will not get you out of the NullPointerException and might have more impact than you desire.
What order?
As we have seen, absolute order does not solve our problem. How about separating creation and initialization? Still, we need to impose some order, or at least some hierarchy.

We represent each Swing component by an OSGi service, and leverage the OSGi service dependency resolution to build up our hierarchy; this way, we know the host service will be started last.
- Resolve services Once the host bundle starts, we know all components are locked and loaded; the host can now start setting up Swing’s static elements like the look and feel.
- Create components Component creation ripples downward: the host gets its direct children, adding them to its container, and in the process triggering the children to get their child components.
- Initialize components Once the component creation is done, the host instructs each component to initialize; we can now be certain that all components are part of the AWT hierarchy.
To reach this situation, we introduce a new OSGi service that wraps the component.

All components are handled by a service implementing ComponentProvider; notice how methods are required to be called on the EventDispatchThread, making sure that all components are created on the EDT, while retaining the order necessary.
public interface ComponentProvider { /** * Constant to identify ComponentProvider services. */ public static final String COMPONENT_ID_KEY = "component.id"; /** * This function should always be called from the EDT. The implementor * may assume that this function is called once and before {@link #addedToContainer()} * * @return the implementors (Swing) component which it provides. */ public JComponent getComponent(); /** * Triggered when the component is added to a container. The implementation * can validate some stuff. This function must be called on the EDT. * Implementors may assume this function is called after {@link #getComponent()}. */ public void addedToContainer(); }
The getComponent function is analogous to the create step above; the addedToContainer triggers the initialize.
Let’s try that out!
To check that this actually works OK, run
$ > ant run2from the root of the project, and start the bundles in any order you like. The UI will only show up once all required components are available; notice that the Table and the ScrollPane component can be used interchangeably.
Is it all good?
For the most part, yes. You do give up some flexibility: the UI is assembled at runtime, but it is no longer possible to (easily) plug components into a running system without special provisions. Then again, how often do you deploy new Swing-based functionality to a running application?
In the example application, we use ServiceTrackers to keep track of the components needed by the host. In a real system, you should consider using some dependency management mechanism; we have used the Apache Felix Dependency Manager in the past.
The project and the story
The project mentioned above is available as a zipped Eclipse project. You can directly import this into Eclipse, or just unzip it and run the Ant build file.
To run the examples, you will need Apache Ant. Also, since we use Pax Runner, you will need an internet connection.
The presentation we gave about this at Devoxx 09 is at SlideShare.
Oredev 2009
Geplaatst door Angelo van der Sijpt in Uncategorized op november 6, 2009
This past week (4 – 6 November), I went to Øredev, probably the largest developer conference in Scandinavia. I had been invited as a speaker, thanks for having me!
Great food, nice ambiance
The first thing that strikes me about this conference is how well it has been prepared. The food is great, there is a good evening program, and overall both your inner geek and inner person are well looked after.
Highlights
Interactive Visualizations from Microsoft research – Eric Stollnitz (User Experience track)
One of the rare talks I actually did not like. Having not read the session description properly, I had totally wrong expectations; the session demoed visual tools like Photosynth, which are cool, but not something we haven’t seen before. And besides, running Vista on a Mac, and having to kill Internet Explorer…?
Open source Java: ten things you didn’t know you could do – Terrence Barr (Java track)
Early in the talk it felt like a plug for the greatness of Sun, making Java open source. Later, however, it mentions some seriously cool technology that has become possible now! Some honorable mentions,
- The Maxine guest VM is an effort to run a Java VM directly on a HyperVisor, skipping the entire OS!
- IKVM.NET is a project aiming to run Java code on a .NET VM. Somehow, it turns out that Java bytecode and .NET assembly language are so similar, that an effort has been started to create automatic translation tools between compiled Java and compiled .NET (and vice versa). I would like to add that this is allows not only Java to run on a .NET VM, but likely any language that runs on the Java VM! Interesting…
- Zero writes a Java VM in plain C without using assembler code, making it easier to port it to new platforms.
The Manager’s Guide to Agile Adoption – Mike Cottmeyer (PM In Practice track)
A great talk showing the issues that might hamper agile adoption, especially in larger organizations. Some snippets,
- “Agile adoption at the team level is not the issue, it’s adopting agile across teams.”
- Don’t speak of features of a system, speak of capabilities (think about that one!)
- Depending on the amount of dependencies between teams, we could use a Scrum of Scrums (resource dependency), Product Owner team (requirements dependency), or a Product Owner team with Architects (technical dependencies). Whatever method is used, this higher level should build a normalized backlog, intended to create some alignment along the teams. The team’s backlogs are based on this normalized backlog.
- Feature teams will break down at some level; at a certain system size, it’s no longer possible to create a top-to-bottom slice of the system which is small enough for a single team to manage.
In short, I really enjoyed this talk, and I feel there might be some applications for these ideas somewhere near me…
How Exactly Can Developers Create a Compelling User Experience? – Ben Galbraith (User Experience track)
Exactly the way I would expect a user experience talk to look (and feel!) like: polished imagery, a well-oiled story line, and lots of inspiration. Besides, I have two new books to add to my reading list: About Face by Alan Cooper, which seems to be the standard volume on interaction design, and The humane interface by Jeff Raskin.
Reconsidering cherished design dogmas – Johannes Brodwall & Finn-Robert Kristensen (Architecture track)
I actually had a beer with these guys a few days earlier, and they told me about their ideas. In short, there are a number of dogmas in software design we came to hold true, but are they actually true? For instance, is generic code really more reusable than specific code?
It’s a shame the talk didn’t really come across, and I could not put my finger on the problem; it might have something to do with the over-abstracted example they chose.
Dynamic Deployment with OSGi – Angelo van der Sijpt (Java track)
Well, let the crowds decide on this one. Have you visited my talk, and have an opinion about it? Let me know in the comments?
Modeling in the Age of Agility – Kevlin Henney (Agile Architecture track)
“Working software over comprehensive documentation” sounds good, but how about modeling? Are all models potential waste? Of course not, but when applying modeling because it is modeling, is sure to create models no one will ever look at, and the few good ones in there are buried. Some snippets,
- “Agile is all about doing.” Actually, I did not know the word ‘Agile’ comes from the Latin verb for ‘to do’.
- “The most important aspect of modeling is the -ing.”
So?
Like I said, a great conference, and I’m sorry I missed the test track. I will leave you with a quote I picked up on Twitter (I don’t know which session it’s from),
“Don’t build frameworks, extract them”
Nieuwe iPhone applicatie gelanceerd: Quote eetgids
Geplaatst door Arjan Schaaf in Uncategorized op oktober 2, 2009
Op 1 oktober was het zover, de Quote eetgids staat in de Apple Appstore! Met de Quote eetgids kan je op eenvoudige wijze restaurants in de buurt vinden en beoordelen. Dit op basis van je huidige lokatie die met behulp van GPS wordt vastgesteld. Heb je andere voorkeuren? Alleen met gelegenheden met michelinster? Of na een heerlijke dag varen, aanleggen bij de steiger met zicht op je blinkende jacht van een voortreffelijk menu genieten? Check de Quote eetgids!
![]() |
Ontwerp: luminis live Technische realisatie: luminis software development |
NHibernate Lambda Extensions – an open-source adventure
Geplaatst door Richard de Zwart in Uncategorized op juli 10, 2009
For our client Gerechtsdeurwaarderskantoor De Jong we built a .NET application that uses NHibernate in the data-layer to talk to the Informix database. To abstract away from the specific knowledge about the database / ORM I created the below structure:

The DomainConnector is a class that implements lots of business rules to load/save domain-objects and gets its IStorage from our IoC-container (which is Castle Windsor). The InformixConnector implements the IStorage interface, but the DomainConnector doesn’t know that. Just as it doesn’t know that the InformixConnector uses NHibernate to do the actual work.
Well, until recently that was not entirely the case. The DomainConnector needs queries to specify which objects it wants in a list (for example). Those queries were in strings and were actually HQL queries.
Mmmmmmmh, so the DomainConnector did not know what database was in the back-end (thanks to NHibernate), but did know in some way about the fact that NHibernate was used. Use invalid HQL in your query and you’re doomed.
Some times you can live with less-than-perfect code. But a couple of days ago I ran into a problem I felt I had had before. I got this message from NHibernate that it could not map some property. So what do you do? You check your mapping file and the class that it maps to and conclude that everything is perfect. So you Google. Nothing interesting.
And then (a frustrating hour later) a memory bubbles up: it is not talking about the mapping itself, it’s talking about trying to map names in a query! Yep, that was the problem. The cause? I changed the name of a property. The real cause? This property was referenced in a string and the compiler could -of course- not warn me I had to change the query-string.
I had e feeling that Lambda-expressions must be the solution to this problem (as they are currently to a lot of my problems). And Google (as a .NET afficionado should I be bing-ing?) told me there was already an open-source project that did just what I wanted:
nhlambdaextensions.
This project contains a few extension classes that allow you to use lambdas to specify your ICriteria. As they say on their homepage:
.Add(Expression.Eq("Name", "Smith"))
becomes
.Add(p => p.Name == "Smith")
Now you can have Intellisense and compile-time checking. No way you inadvertently type LastName in stead of Name!
So I downloaded the binaries, tried to compile, noticed that I needed a newer version of NHibernate, downloaded that and it compiled. Changed one of the DomainConnectors and ran a unit test: bingo!!! This was going to work. I was so happy, I changed all the DomainConnectors before running an intergration test. I mean: I changed all the code before actually running it against NHibernate. *** UGLY WORDS *** when I did that eventually. For some obscure reason the SessionFactory could no longer be created, so no database access…
Reverting to the previous version of NHibernate solved this (I love version-control), but then I could not compile my lambdas anymore. So what should I do now: try to solve the SessionFactory problem or revert to the queries-in-a-string version of my DomainConnector. Tough descision.
And then I had my epiphany: this is open-source code. I can download the code, add it to my project, compile it against my working version of NHibernate and have lambda-based queries. Have your cake and eat it too!
It took no more than 10 minutes to achieve this. That’s the beauty of open-source, take control. But it also gave me more responsibility than I might actually want. Now this code was sort-of my code. Would I do that for larger open-source project like NHibernate itself? No way, my client’s business depends on the use of NHibernate. I want to be sure I have a stable, correctly compiled version of it. But for this 6 classes, 500 lines of code project I feel ok.
I even solved a bug that I might contribute to the project. Did not do that yet, though. Small steps….
Using GWT to create an OSGi-aware web application
Geplaatst door Angelo van der Sijpt in Uncategorized op juli 9, 2009
Update 2010-02-20 Both Pax Runner 1.3.0 and GWT 2.0 have caused quite some changes to this post. I have tried to stay up to date as well as I could (the zipped project now uses GWT 2.0), but you might find some inconsistencies when following the tutorial.
Google Web Toolkit is cool, and so is OSGi. However, when building a web UI for Apache ACE, I found out that creating a web application that can use OSGi services is not that easy. By the end of this tutorial, you will have created a GWT project that delivers a usable jar. If you’re impatient, skip to the end for the downloadable Eclipse project.
Step 1: Create a GWT project
Create a regular GWT project using the regular webAppCreator; this will give you a project that includes an Ant buildfile, we will need that later on.
angelos:workspace angelos$ ./gwt-mac-1.6.4/webAppCreator -out GwtDemo net.luminis.gwt.gwtdemo Created directory GwtDemo/src Created directory GwtDemo/war Created directory GwtDemo/war/WEB-INF Created directory GwtDemo/war/WEB-INF/lib Created directory GwtDemo/src/net/luminis/gwt Created directory GwtDemo/src/net/luminis/gwt/client Created directory GwtDemo/src/net/luminis/gwt/server Created file GwtDemo/src/net/luminis/gwt/gwtdemo.gwt.xml Created file GwtDemo/war/gwtdemo.html Created file GwtDemo/war/gwtdemo.css Created file GwtDemo/war/WEB-INF/web.xml Created file GwtDemo/src/net/luminis/gwt/client/gwtdemo.java Created file GwtDemo/src/net/luminis/gwt/client/GreetingService.java Created file GwtDemo/src/net/luminis/gwt/client/GreetingServiceAsync.java Created file GwtDemo/src/net/luminis/gwt/server/GreetingServiceImpl.java Created file GwtDemo/build.xml Created file GwtDemo/README.txt Created file GwtDemo/.project Created file GwtDemo/.classpath Created file GwtDemo/gwtdemo.launch Created file GwtDemo/war/WEB-INF/lib/gwt-servlet.jar
If you want to, you can import this project directly into your Eclipse. If you check the mark “use Google Web Toolkit” in the project properties, you can use all the same goodies that creating the project in Eclipse would have given you. Remember to replace the buildpath entries for gwt-user.jar and gwt-dev-*.jar by a Library import for GWT.
Step 2: Include the necessary OSGi references
Create an ‘ext’ directory, and add org.osgi.core.jar to that. In Eclipse, add this jar to your build path.
Step 3: Use OSGi services from your web applicaiton
We will first add a simple Activator on the server side.
package net.luminis.gwt.server; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { private static BundleContext m_context; public static BundleContext getContext() { return m_context; } public void start(BundleContext context) throws Exception { m_context = context; } public void stop(BundleContext context) throws Exception { } }
Then, we up the GreetingServiceImpl to actually use this BundleContext (note that we use it directly here, but you could use it to get other services, create a ServiceTracker, etc.)
public String greetServer(String input) { String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); return "Hello, " + input + "! I am running " + serverInfo + ". It looks like you are using:" + userAgent + "The framework we run from has " + Activator.getContext().getBundles().length + " bundles in it."; }
Step 4: Add OSGi dependencies for the compiler
Add our OSGi dependencies to the classpath, so the compiler can find all of it.
<!-- Add any additional non-server libs (such as JUnit) -->Right, let’s give it a try!
angelos:GwtDemo angelos$ ant war Buildfile: build.xml ...some output removed... war: [zip] Building zip: /Users/angelos/workspace/workspace/GwtDemo/gwtdemo.war BUILD SUCCESSFUL Total time: 36 seconds
You will find a war in your project directory now. There still is one ingredient we need. We need to make this into a proper bundle. We can use bnd to help us with that.
Step 5: use bnd to create a proper war
Download bnd, and put into a lib directory, and add it to your buildfile.
We create a new target that transforms our war into a jar.
<target name="jar">
<copy file="gwtdemo.war" tofile="gwtdemo.jar"/>
<echo file="gwtdemo.bnd">Import-Package: junit.framework;resolution:=optional, com.google.gwt.*;resolution:=optional, org.w3c.*;resolution:=optional, sun.misc;resolution:=optional, javax.imageio;resolution:=optional, javax.servlet.*;resolution:=optional, *
Bundle-Name: GWT Demo
Bundle-ClassPath: WEB-INF/classes, WEB-INF/lib/gwt-servlet.jar
Bundle-SymbolicName: net.luminis.gwt.gwtdemo
Webapp-Context: gwtdemo
Bundle-Activator: net.luminis.gwt.server.Activator
</echo>
<bndwrap jars="gwtdemo.jar" output="gwtdemo.jar"/>
<jar file="gwtdemo.jar" update="true">
<manifest>
<attribute name="Bundle-ClassPath" value="WEB-INF/classes, WEB-INF/lib/gwt-servlet.jar, ."/>
</manifest>
</jar>
<delete file="gwtdemo.bnd"/>
</target>What’s happening here?
- we copy our war to the same file, but with a jar extension,
- we create a file for bnd to use, stating that we
- want optional imports for junit and the gwt benchmarks, and non-optional imports for everything else (that what the * is for),
- have some classes that we want bnd to scan for finding dependencies,
- want to use a given Webapp-Context (this is a Pax war extender specific entry),
- let bnd do its magic,
- update our manifest: we put the . back on the classpath. This is important for the web application to find all resources, but if we would tell bnd to do it like this, it would treat . as the root of the classpath.
- Finally, we delete that temporary bnd file.
What does that give us?
angelos:GwtDemo angelos$ ant jar Buildfile: build.xml ...some output removed... jar: [copy] Copying 1 file to /Users/angelos/workspace/workspace/GwtDemo [bndwrap] gwtdemo 41 910305 [bndwrap] Warnings [bndwrap] Superfluous export-package instructions: [WEB-INF.classes.net, gwtdemo.gwt.standard.images, WEB-INF, gwtdemo, WEB-INF.classes.net.luminis.gwt, gwtdemo.gwt.standard, WEB-INF.classes.net.luminis, WEB-INF.lib, WEB-INF.classes, gwtdemo.gwt.standard.images.ie6, WEB-INF.classes.net.luminis.gwt.client, WEB-INF.classes.net.luminis.gwt.server, gwtdemo.gwt] [jar] Updating jar: /Users/angelos/workspace/workspace/GwtDemo/gwtdemo.jar [delete] Deleting: /Users/angelos/workspace/workspace/GwtDemo/gwtdemo.bnd BUILD SUCCESSFUL Total time: 23 seconds
That’s it! You can now deploy this jar into a framework that uses the pax web tools. Right, let’s give that a try.
Download pax-runner, and unzip that somewhere. Copy in your new jar, an try the following command
angelos:pax-runner angelos$ sh bin/pax-run.sh --profiles=war,compendium gwtdemo.jar
Now visit http://localhost:8080/gwtdemo:

Summary
So, what did we need?
- A fairly regular GWT project, create with an Ant file,
- some code that tries to use OSGi services,
- some bnd magic to make the war into a jar,
- Pax tools to get it all running quickly.
If you don’t want to use pax runner, you can need to deploy pax-web-extender-war(jar, snapshot 23 June) and an http server, preferably pax-web-service(jar), into your framework.
You can download the gwtdemo Eclipse project to play around with it. I have not provided the GWT runtime in this download; you should edit line 4 of the build.xml to point to your installation of GWT.
Google Wave – Ze doen het weer….
Geplaatst door Richard de Zwart in Uncategorized op juni 28, 2009
Google presenteerde recentelijk een van de nieuwe ontwikkelingen waarmee ze bezig zijn: Waves. Volgens de documentatie op de Google Wave API website is een wave:
“A wave is a threaded conversation, consisting of one or more participants (which may include both human participants and robots). The wave is a dynamic entity which contains state and stores historical information. A wave is a living thing, with participants communicating and modifying the wave in real time.”
Google Wave draait in je browser. Het is een Javascript applicatie die je browser omtovert tot een collaboration-tool die de concurrentie met een heleboel duurbetaalde tools probleemloos aankan. En het is gratis. De gehele code-base wordt ge-opensourced zodat iedereen heel snel en makkelijk met zijn eigen Wave implementatie aan de slag kan
Is het mooi?
Ja, wat je ziet op de demo die ze gaven op de Google IO conference is absoluut spectaculair. Het duurt even voordat het tot je doordringt (thick skull, sorry), maar dan zie je (als techneut in ieder geval) dat het heel knap is wat ze daar aanbieden. Of je het wilt hebben, of dat het de wereld gaat veranderen of de hoeveelheid CO2 in de atmosfeer gaat verminderen? Geen idee, maar hieronder licht ik even de punten toe die mij erg aanspraken.
Real-time
Alles wat je in een Wave intikt, is onmiddellijk zichtbaar bij alle andere mensen die jouw Wave open hebben staan. Dit biedt dus in ieder geval Instant Messaging, maar dan zonder het wachten op “Mr.X is typing a message”. Er is een open protocol ontwikkelt dat deze communicatie regelt. Even ter herinnering: dit is in je browser. Dus real-time communicatie tussen 2 of meer browsers.
Concurrent
Je werkt met alle betrokkenen tegelijk aan een Wave. Iedereen kan reply-en binnen een Wave, maar kan ook
corrigeren wat een ander nog aan het intikken is. In dat proces wordt bijgehouden wie wat heeft gedaan.
Multi-media
Letterlijk. Het maakt niet uit welk type medium je wilt gebruiken: tekst, beeld, film, geluid. Je kunt het allemaal drag-n-droppen in een wave. Als je een serie plaatjes in een Wave gooit, krijgen alle deelnemers onmiddellijk thumbnails te zien.
Playback
Alle wijzigingen op de Wave staan op een time-line die je kunt terugspelen. Als je met een groep mensen aan een stuk tekst werkt kun je de hele conversatie terughalen, wat noodzakelijk kan zijn omdat iedereen alle tekst kan wijzigen en je alleen het uiteindelijke resultaat ziet. Er is een demo van een schaak-applicatie die in een Wave draait. Behalve dat iedereen op de Wave onmiddellijk de gedane zetten ziet, kun je het hele spel opnieuw afspelen door de time-line te manipuleren. Als ontwikkelaar van een dergelijke app hoef je niets te doen voor de real-time en play-back functionaliteit. Die zit in de Wave en krijg je er gratis bij!
Robots
Er is al een grote hoeveelheid robots geschreven die deelnemen aan een conversatie zoals mensen dat kunnen doen. Deze robots werken voor je als een soort tool of plug-in. Er is bijvoorbeeld een spelling-checker robot die jouw Wave edit terwijl je ermee bezig bent. En zelfs een vertaal-robot die jouw tekst bij jouw Franse collega in het Frans vertaald laat zien. Maar ook robots die tekst herkennen als links en ze meteen clikable maken, of robots die een link naar video herkennen en je meteen de optie geven om een player te embedden.
APIs
Er is een uitgebreide API beschikbaar om zelf robots te maken of om een Wave in je eigen (web)applicatie te embedden. Je vindt er meer over op: http://code.google.com/apis/wave.
Conclusie
Het is eigenlijk nog te vroeg om conclusies te trekken. De developers wereld is er al flink opgesprongen en heeft een veelheid aan robots en gadgets geproduceerd. Dat zegt niet alles. Zoals uit mijn enthousiasme al blijkt is het voor techneuten echt een heel interessant platform. Of het een killer-app is weet ik niet. Het zou heel goed de manier van communicatie kunnen veranderen, omdat je mail, chat en IM in één en dezelfde vormt giet. Ik denk dat het net zo gaat als met de iPhone. Op zichzelf niet briljant, maar doorr de juiste onderliggende technologie maakt het applicaties mogelijk die echt briljant zijn en het product tot grotere hoogte tillen.
Behaviour Driven Development (BDD)
Geplaatst door Richard de Zwart in Uncategorized op juni 24, 2009
Ik las recentelijk in een blog-entry van Rob Conery over BDD. Rob Conery ontwikkelt voor Microsoft een op ASP.NET gebaseerde StoreFront. Een soort starters-pakket voor mensen die een web-winkel willen maken. In het proces van het ontwikkelen van deze applicatie (die inmiddels ook op Codeplex is geopensourced onder de werktitel Kona heeft hij meerdere ontwikkel-processen en ontwikkel-methodes uitgeprobeerd. En in dat hele proces was hij er niet vies van om de hele zaak op zijn kop te gooien of zelfs helemaal opnieuw te beginnen. Alleen daarom al is hij een held. O, ja, en ook omdat ie op Hawaii woont…
Zo kwamen de afgelopen maanden Test-Driven-Development, Domain-Driven-Development en -als meest recente- Behaviour Driven Development langs. BDD is min of meer uitgevonden door Dan North (http://dannorth.net/introducing-bdd) en lost voor mij (en ook voor Rob Conery) een probleem op dat ik altijd met TDD heb gehad: hoe begin je met je tests?
Natuurlijk ga je eerst je test maken en dan pas de code die zorgt voor het vervullen van je test. We kennen het allemaal: red-green-refactor. Maar met welke test begin je, en hoe heet die test?
BDD doet iets heel simpels: denk niet meer in de term “test” maar in termen als “gedrag” en “specificaties”. Dus: “welk gedrag wil ik implementeren” en niet “welke test wil ik schrijven”. Je komt dan heel makkelijk op iets als “EmptyShoppingCartShouldReturnCountOfOneWhenProductAdded”. Dat kan ik vertalen naar een test en ik kan ook de code schrijven die de test vervult!
De volgende stap is dat je al de requirements/specs/behaviours die je kent op een dergelijke manier in je code zet. Gewoon lege methods met aan Assert.Fail erin. Dat geeft je een hele lijst van test-methodes die natuurlijk initieel allemaal falen. Maar het is dan wel zonneklaar wat je moet gaan doen om de hele zaak groen te krijgen.
Dit lijkt niet revolutionair, maar ik heb het vandaag in de praktijk uitgeprobeerd en het leverde me een zeer tevreden gevoel op. Ten eerste wist ik wat ik moest gaan coderen, ten tweede wist ik dat ik een test had voor alle code die ik zou gaan maken en ten derde wist ik -eenmaal aan het einde van de rit, alles groen- dat ik niet meer code had gemaakt dan ik nodig had.
Ik zou ook dolgraag de volgende stap maken: het inzetten van MSpec (). Albert Oudenampsen had mij al eens RSpec laten zien: in feite een Ruby-programmaatje dat het mogelijk maakte om je specificaties in bijna-menselijke-taal te schrijven en te executeren. Maar zoals wel vaker duurt het bij mij enige maanden tot jaren voordat ik zie wat Albert ziet. MSpec is op de ideeen van RSpec gebaseerd, maar is specifiek voor het .NET platform.
MSpec biedt een library die je meelinkt in je test-project en die je de taal-elementen geeft waarmee je je tests (sorry, je behaviours) schrijft en biedt je een MSpec-runner die de behaviours runt en over de resultaten rapporteert. Je neemt dus je requirements-document, schrijft in MSpec-syntax je tests en runt het hele zaakje met de MSpec-runner. Vervolgens ga je zorgen dat de specs/behaviours groen worden door net als bij TDD te gaan implementeren. Even een stukje code om er een gevoel bij te krijgen:
1. [Description]
2. public class Transferring_between_from_account_and_to_account
3. {
4. static Account fromAccount;
5. static Account toAccount;
6.
7. Context before_each =()=>
8. {
9. fromAccount = new Account {Balance = 1m};
10. toAccount = new Account {Balance = 1m};
11. };
12.
13. When the_transfer_is_made =()=>
14. {
15. fromAccount.Transfer(1m, toAccount);
16. };
17.
18. It should_debit_the_from_account_by_the_amount_transferred =()=>
19. {
20. fromAccount.Balance.ShouldEqual(0m);
21. };
22.
23. It should_credit_the_to_account_by_the_amount_transferred =()=>
24. {
25. toAccount.Balance.ShouldEqual(2m);
26. };
27. }
Naast het feit dat de specificatie redelijk te lezen is (als je even gewend ben aan de syntax die nogal zwaar leunt op ambda-expressies) produceert de MSpec-runner ook een HTML rapport waarop staat welke requirements je allemaal gaat implementeren, welke er al klaar zijn en welke nog niet. En dat allemaal op een manier die leesbaar is voor project-managers of problem-owners.
Nog niet overtuigd? Laat ik het dan anders zeggen: je hebt executeerbare requirements! Ja, echt, daar wordt je blij van, dat geeft je de missing-link tussen dat ene Word document dat die FO-er heeft geschreven en jouw eigenste code!
JavaOne 2009 – it’s a ghost town
Geplaatst door Marcel Offermans in Uncategorized op juni 7, 2009
We flew in on friday and spent the weekend in San Francisco. One thing that became obvious very quickly is that the recession has hit this economy hard. Big stores, like the Virgin Megastore, CompUSA, Disney Store and the Sony Centre: gone! The NL-JUG get together on sunday underlined that. The group, last year about 120 people big, now was a much more manageable size (about 30 in total). We all enjoyed the wine tour and dinner though!
Just as I expected, general attendance at JavaOne was dramatically low. Where one had to check in on sunday or monday on previous years to avoid long lines on the morning of the keynote, I could walk up to a counter directly, sign up, collect my goodies elsewhere and be in the keynote room only a minute or so later. It’s a funny feeling when compared to other years. It all went so quick I almost missed a big sign of Hans that was put up outside the Moscone center. Appearantly, he symbolizes the Java community!
With Oracle still in the process of buying Sun, I couldn’t help but feel that there was less news to announce than normal. The opening keynote certainly was pretty boring, partner after partner announcing how great their relation with Java and Sun is. At the end, Larry Ellison did appear on stage, together with Scott McNeally and Jonathan Schwartz. Not sure if it was bad rehearsal or a total lack of chemistry, but it came across a bit awkward. The other keynotes were no better, the exception being the final one by James Gosling, who did manage to show quite a few cool projects.
Appstores were definitely a big theme during the conference. If you did not have one yourself yet, you were definitely not cool. I signed up for the Sun one, but I don’t think it will become a big success. There are not that many killer desktop apps around in Java, especially not ones I would want to pay for. But then again, I never got the whole ringtones market either, and that’s huge.
A couple of highlights of the rest of JavaOne:
- Rich Hickey, author of Clojure, stating that mutable stateful objects are the new spaghetti code, dismissing Java and object oriented languages in general in a future where concurrency and parallelism are more and more present.
- At zembly.com they have tools to search for web service APIs and test them. If plugged into an IDE you can even drag and drop them into a source file and get a snippet generated automatically.
– After a talk about Filthy Rich Clients at earlier conferences, Guy and Haase did a talk about applying the 12 Disney animation principles to user interfaces. Interesting concept, but they should have spent more time coming up with good examples. Also, two or three bad jokes per presentation are enough guys! - Don Brown showed the new Atlassian plugin framework, and gave a good overview of some of the pitfalls of using OSGi. The plugin framework can be dropped in arbitrary applications, and he demonstrated that live on stage.
- Glassfish V3 was demo’d at one of the keynotes, running on Apache Felix, and launching in less than 2 seconds, showing almost instant develop/compile/run cycles by updating bundles automatically from within an IDE.
- Runescape, a massively online multiplayer game, designed to run on stone-age hardware. What impressed me most was the fact they created their whole 3D authoring environment themselves, instead of relying on industry standards like Lightwave or 3D Studio, claiming to work a lot quicker that way.
Want to know more? Come and visit us in Arnhem for the JavaOne Reloaded event. For more information, see a previous blog entry.




