This chapter continues from where Creating the workspace definition left us.

Hello world with Eclipse

Next, as the wizard advised after defining the workspace, we'll generate eclipse settings. This is a mutation to the workspace, and iwant does not have full control over the files (eclipse is also able to modify them), so this wish needs to be a side-effect.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/side-effect/eclipse-settings/effective
(0/1 D! org.fluentjava.iwant.api.core.Concatenated eclipse-settings.bin-refs)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
Output asserted

Now we can import the projects to eclipse (without copying them to the workspace!) and study what we have. In fact, let's even make the first edit: another hello target alongside with the existing one.

~/iwant-tutorial $ $EDITOR "as-iwant-tutorial-developer/i-have/wsdef/src/main/java/com/example/wsdef/"
package com.example.wsdef;
import java.util.Arrays;
import java.util.List;
import org.fluentjava.iwant.api.core.HelloTarget;
import org.fluentjava.iwant.api.model.SideEffect;
import org.fluentjava.iwant.api.model.Target;
import org.fluentjava.iwant.api.wsdef.SideEffectDefinitionContext;
import org.fluentjava.iwant.api.wsdef.TargetDefinitionContext;
import org.fluentjava.iwant.api.wsdef.Workspace;
import org.fluentjava.iwant.eclipsesettings.EclipseSettings;
public class IwanttutorialWorkspace implements Workspace {
public List<? extends Target> targets(TargetDefinitionContext ctx) {
return Arrays.asList(new HelloTarget("hello", "hello from iwant\n"));
return Arrays.asList(new HelloTarget("hello", "hello from iwant\n"),
private static Target hello2() {
return new HelloTarget("hello2", "hello from my first target\n");
public List<? extends SideEffect> sideEffects(
SideEffectDefinitionContext ctx) {
return Arrays.asList(EclipseSettings.with().name("eclipse-settings")
.modules(ctx.wsdefdefJavaModule(), ctx.wsdefJavaModule())

We can see our new target in the list of targets.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/list-of/targets
(0/1 S~ org.fluentjava.iwant.api.javamodules.JavaClasses iwant-tutorial-wsdef-main-classes)
Output asserted

Building a target means wishing for a path to a file that contains the fresh content of the target. Let's try that for the two targets we have.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/hello/as-path
(0/1 D! org.fluentjava.iwant.api.core.HelloTarget hello)
Output asserted
~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/hello2/as-path
(0/1 D! org.fluentjava.iwant.api.core.HelloTarget hello2)
Output asserted

iwant only prints the requested path to stdout, all diagnostic output goes to stderr. This means we can redirect the path to further processing. This is a convenient idiom for showing the content of a target:

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/hello2/as-path | xargs -r cat
hello from my first target
Output asserted