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

Defining Java modules

First we define one java source module with main and test java and test resources and dependency to the binary module junit.

We also add the module to the eclipse-settings side-effect, and also define a target that lists the java class directory artifacts of the module.

~/iwant-tutorial $ $EDITOR "as-iwant-tutorial-developer/i-have/wsdef/src/main/java/com/example/wsdef/IwanttutorialWorkspace.java"
package com.example.wsdef;
import java.util.Arrays;
import java.util.List;
import org.fluentjava.iwant.api.core.Concatenated;
import org.fluentjava.iwant.api.core.HelloTarget;
import org.fluentjava.iwant.api.javamodules.JavaBinModule;
import org.fluentjava.iwant.api.javamodules.JavaModule;
import org.fluentjava.iwant.api.javamodules.JavaSrcModule;
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.core.download.TestedIwantDependencies;
import org.fluentjava.iwant.eclipsesettings.EclipseSettings;
public class IwanttutorialWorkspace implements Workspace {
private final JavaModule junit = JavaBinModule
.providing(TestedIwantDependencies.junit()).end();
private final JavaSrcModule exampleHello = JavaSrcModule.with()
.name("example-hello").mavenLayout().noMainResources()
.testDeps(junit).end();
@Override
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"),
exampleHelloClasses());
}
private Target exampleHelloClasses() {
return Concatenated.named("hello-classes")
.unixPathTo(exampleHello.mainArtifact()).string("\n")
.unixPathTo(exampleHello.testArtifact()).string("\n").end();
}
@Override
public List<? extends SideEffect> sideEffects(
SideEffectDefinitionContext ctx) {
return Arrays.asList(EclipseSettings.with().name("eclipse-settings")
.modules(ctx.wsdefdefJavaModule(), ctx.wsdefJavaModule())
.modules(ctx.wsdefdefJavaModule(), ctx.wsdefJavaModule(),
exampleHello)
.end());
}
}

Then we generate Eclipse settings for it so we can use Eclipse for writing the code.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/side-effect/eclipse-settings/effective
(0/1 S~ org.fluentjava.iwant.api.javamodules.JavaClasses iwant-tutorial-wsdef-main-classes)
(0/1 D! org.fluentjava.iwant.core.download.GnvArtifact junit-4.8.2.jar)
(0/1 D! org.fluentjava.iwant.api.core.Concatenated eclipse-settings.bin-refs)
(example-hello)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdefdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)

Now we can import the project to Eclipse and write some code.

~/iwant-tutorial $ $EDITOR "example-hello/src/test/java/com/example/hello/HelloMainTest.java"
package com.example.hello;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class HelloMainTest {
@Test
public void greetingUsesGivenTarget() {
assertEquals("Hello world", HelloMain.greetingTo("world"));
assertEquals("Hello Finland", HelloMain.greetingTo("Finland"));
}
}
~/iwant-tutorial $ $EDITOR "example-hello/src/main/java/com/example/hello/HelloMain.java"
package com.example.hello;
public class HelloMain {
public static void main(String[] args) {
System.out.println(greetingTo(args[0]));
}
public static String greetingTo(String target) {
return "Hello " + target;
}
}

Finally, we can build and run some classes.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/hello-classes/as-path
(0/1 D! org.fluentjava.iwant.api.javamodules.JavaClasses example-hello-main-classes)
(0/1 D! org.fluentjava.iwant.api.javamodules.JavaClasses example-hello-test-classes)
(0/1 D! org.fluentjava.iwant.api.core.Concatenated hello-classes)
/home/hacker/iwant-tutorial/as-iwant-tutorial-developer/.i-cached/target/hello-classes
~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/hello-classes/as-path | xargs -r cat
/home/hacker/iwant-tutorial/as-iwant-tutorial-developer/.i-cached/target/example-hello-main-classes
/home/hacker/iwant-tutorial/as-iwant-tutorial-developer/.i-cached/target/example-hello-test-classes
~/iwant-tutorial $ java -cp as-iwant-tutorial-developer/.i-cached/target/example-hello-main-classes com.example.hello.HelloMain tutorial
Hello tutorial
Output asserted

Next we will use an optional convenience class for easier definition of modules.

First we'll enable the needed plugin and refresh eclipse settings.

~/iwant-tutorial $ $EDITOR "as-iwant-tutorial-developer/i-have/wsdefdef/src/main/java/com/example/wsdefdef/IwantTutorialWorkspaceProvider.java"
~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/side-effect/eclipse-settings/effective
(0/1 S~ org.fluentjava.iwant.api.javamodules.JavaClasses iwant-tutorial-wsdefdef-main-classes)
(0/1 org.fluentjava.iwant.api.javamodules.JavaClasses iwant-tutorial-wsdef-main-classes)
(example-hello)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdefdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)

Now we will use the class JavaModule to define more modules and utilize some convenience functionality of it.

~/iwant-tutorial $ $EDITOR "as-iwant-tutorial-developer/i-have/wsdef/src/main/java/com/example/wsdef/IwanttutorialWorkspace.java"
package com.example.wsdef;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import org.fluentjava.iwant.api.core.Concatenated;
import org.fluentjava.iwant.api.core.Concatenated.ConcatenatedBuilder;
import org.fluentjava.iwant.api.core.HelloTarget;
import org.fluentjava.iwant.api.javamodules.JavaBinModule;
import org.fluentjava.iwant.api.javamodules.JavaModule;
import org.fluentjava.iwant.api.javamodules.JavaSrcModule;
import org.fluentjava.iwant.api.javamodules.JavaSrcModule.IwantSrcModuleSpex;
import org.fluentjava.iwant.api.model.Path;
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.core.download.TestedIwantDependencies;
import org.fluentjava.iwant.core.javamodules.JavaModules;
import org.fluentjava.iwant.eclipsesettings.EclipseSettings;
public class IwanttutorialWorkspace implements Workspace {
private final JavaModule junit = JavaBinModule
.providing(TestedIwantDependencies.junit()).end();
private final JavaSrcModule exampleHello = JavaSrcModule.with()
.name("example-hello").mavenLayout().noMainResources()
.testDeps(junit).end();
static class ExampleModules extends JavaModules {
@Override
protected IwantSrcModuleSpex commonSettings(IwantSrcModuleSpex m) {
return super.commonSettings(m).testDeps(junit);
}
final JavaBinModule hamcrestCore = binModule("org/hamcrest",
"hamcrest-core", "1.3");
final JavaBinModule junit = binModule("junit", "junit", "4.11",
hamcrestCore);
final JavaSrcModule helloUtil = srcModule("example-helloutil")
.noMainResources().end();
final JavaSrcModule hello = srcModule("example-hello").noMainResources()
.mainDeps(helloUtil).end();
}
private final ExampleModules modules = new ExampleModules();
@Override
public List<? extends Target> targets(TargetDefinitionContext ctx) {
return Arrays.asList(new HelloTarget("hello", "hello from iwant\n"),
exampleHelloClasses());
classpathStringOfAll());
}
private Target exampleHelloClasses() {
return Concatenated.named("hello-classes")
.unixPathTo(exampleHello.mainArtifact()).string("\n")
.unixPathTo(exampleHello.testArtifact()).string("\n").end();
private Target classpathStringOfAll() {
ConcatenatedBuilder cp = Concatenated.named("all-as-cp");
cp.string(".");
for (Path jar : JavaModules
.mainArtifactJarsOf(modules.allSrcModules())) {
cp.string(File.pathSeparator).nativePathTo(jar);
}
return cp.end();
}
@Override
public List<? extends SideEffect> sideEffects(
SideEffectDefinitionContext ctx) {
return Arrays.asList(EclipseSettings.with().name("eclipse-settings")
.modules(ctx.wsdefdefJavaModule(), ctx.wsdefJavaModule(),
exampleHello)
.end());
.modules(ctx.wsdefdefJavaModule(), ctx.wsdefJavaModule())
.modules(modules.allSrcModules()).end());
}
}

We write some code to the new module

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/side-effect/eclipse-settings/effective
(0/1 S~ org.fluentjava.iwant.api.javamodules.JavaClasses iwant-tutorial-wsdef-main-classes)
(0/1 D! org.fluentjava.iwant.core.download.GnvArtifact junit-4.11.jar)
(0/1 D! org.fluentjava.iwant.core.download.GnvArtifact junit-4.11-sources.jar)
(0/1 D! org.fluentjava.iwant.core.download.GnvArtifact hamcrest-core-1.3.jar)
(0/1 D! org.fluentjava.iwant.core.download.GnvArtifact hamcrest-core-1.3-sources.jar)
(0/1 D~ org.fluentjava.iwant.api.core.Concatenated eclipse-settings.bin-refs)
(example-hello)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(example-helloutil)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
(as-iwant-tutorial-developer/i-have/wsdefdef)
( .project)
( .classpath)
( .settings/org.eclipse.jdt.core.prefs)
( .settings/org.eclipse.jdt.ui.prefs)
~/iwant-tutorial $ $EDITOR "example-helloutil/src/test/java/com/example/helloutil/HelloUtilTest.java"
package com.example.helloutil;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class HelloUtilTest {
@Test
public void spaceSeparatedStrings() {
assertEquals("Hello world",
HelloUtil.spaceSeparatedWords("Hello", "world"));
assertEquals("w0 w1", HelloUtil.spaceSeparatedWords("w0", "w1"));
}
}
~/iwant-tutorial $ $EDITOR "example-helloutil/src/main/java/com/example/helloutil/HelloUtil.java"
package com.example.helloutil;
public class HelloUtil {
public static String spaceSeparatedWords(String word1, String word2) {
return word1 + " " + word2;
}
}
~/iwant-tutorial $ $EDITOR "example-hello/src/main/java/com/example/hello/HelloMain.java"
package com.example.hello;
import com.example.helloutil.HelloUtil;
public class HelloMain {
public static void main(String[] args) {
System.out.println(greetingTo(args[0]));
}
public static String greetingTo(String target) {
return "Hello " + target;
return HelloUtil.spaceSeparatedWords("Hello", target);
}
}

Now we can get all our classes as a classpath string.

~/iwant-tutorial $ as-iwant-tutorial-developer/with/bash/iwant/target/all-as-cp/as-path | xargs -r cat
(0/1 D! org.fluentjava.iwant.api.javamodules.JavaClasses example-helloutil-main-classes)
(0/1 D~ org.fluentjava.iwant.api.javamodules.JavaClasses example-hello-main-classes)
(0/1 D! org.fluentjava.iwant.api.zip.Jar example-hello.jar)
(0/1 D! org.fluentjava.iwant.api.zip.Jar example-helloutil.jar)
(0/1 D! org.fluentjava.iwant.api.core.Concatenated all-as-cp)

Let's use the classpath to run the application again.

~/iwant-tutorial $ java -cp $(as-iwant-tutorial-developer/with/bash/iwant/target/all-as-cp/as-path | xargs -r cat) com.example.hello.HelloMain "same tutorial"
Hello same tutorial
Output asserted