In the tutorial Hello World with Process Flows and Tasks, the fabric tasks did not accept any data from the client, but returned a static string "Hello World!". This works fine for a simple Hello World application, however, real world tasks need to accept input and return output. In this tutorial, we explore the various options for marshaling data into and and out of fabric task code. The the Fabric Task API provides several ways to accomplish this and tries to minimize and eliminate a need to adapt code to the Fabric APIs.
You may create your own fabric application and client application, or you may use the files and projects provided in tutorial_samples.zip and tutorial_samples.tgz archives. These files and projects are not included in the Fabric Software Development Kit (SDK) installation, but will be available for later versions. The fabric APIs are not dependent on a particular build tool or development environment (IDE), so you may use your preferred build tools. For your convenience, we have included project files for several platforms. These can be seen in the table to the right.
In this Kick Start tutorial we will
create and examine a series of Hello World tasks to handle input and output
What our extended Hello World tasks will do
accept input from the fabric client request object
construct a new Hello World string from the input data
return the new string to the client via the fabric request
Projects Provided For Tutorial Samples
Language
Platform
Project Type
Java 1.5
All
Eclipse
Java 1.5
All
Ant scripts
.NET 2.0
Windows
Visual Studio 2005
'C'
Windows
Visual Studio 2005
'C'
Linux
Make scripts
Click the language of your choice for this page:
To create your own fabric application and client, you will need to have done the following:
Read through all the pages in Appistry EAF Essentials to become familiar with the fabric application components and services.
Install the Fabric SDK on your development workstation. Please refer to the Installation procedure.
Download either the tutorial_samples.zip or tutorial_samples.tgz archive from here, and copy the archive into the top level SDK directory ("/usr/local/appistry_eaf_sdk" on unix or "C:\Program Files\Fabric" on Windows) that was created during the SDK install in step #2.
Extract the .zip or .tgz tutorial samples archive into the top level SDK directory. A "tutorial_samples" subdirectory should be created with a path of "/usr/local/appistry_eaf_sdk/tutorial_samples" on unix or "C:\Program Files\Fabric\tutorial_samples" on Windows. Make sure when you extract your archive, particularly using the .zip file, that you do not end up with two tutorial_samples directories like this: "C:\Program Files\Fabric\tutorial_samples\tutorial_samples\...."
Have your build environment setup for Java, .NET, and/or 'C'. We presume in this tutorial that you know how to use the build environment of your choice. We have provided projects for several, as mentioned, for your convenience.
Install at least one fabric worker on a computer. This may be on your development workstation or one or more separate boxes. If the worker is not on your local workstation, then the worker or workers must be accessible over the network from your development workstation. Please refer to the Installing the Fabric procedure.
What each task sample in this tutorial has in common
Each Hello World task in this tutorial has the same functionality, but they achieve the result using different approaches. The tasks in this tutorial accept as input two strings from the fabric request map: greeting and greetee. The value of greeting may be "Hello" or "Howdy", and the value of greetee maybe "World" or "Fred". The tasks return a string named "hello" to the fabric request (and consequently to the client). The value of the output string "hello" is "Hello Fred!" or "Howdy World!", depending on the input. Some of the samples get the fabric client user's name from the fabric request, and uses that to produce an output string like "Tom says hello Fred!".
How data is mapped from and into the fabric request object depends on the programming language, and your implementation choice. In Java and .NET, the mapping is accomplished using Java annotations or .NET attributes. In 'C', the Task API manipulates the fabric request object directly. Please note that the Java Task API 3.5 version of the sample task also required this direct approach in some cases, whereas the Java Task API 3.7 version does not, and can be accomplished using annotations.
What is a fabric request object? When a fabric client submits an execution request into a fabric, the request and it's user data is passed in a fabric request object. The fabric request object exists for the duration of the request, and is passed to each task executed to fulfill the request. When the fabric has fulfilled the client's request, the fabric request object is returned to the client. A fabric developer can get values from, and set values to the fabric request object using the fabric client API and fabric task API. The Java and .NET task API in particular support several methods for manipulating values in the fabric request object. This Kick Start tutorial demonstrates just one way to return a value to the client from the task via the fabric request object.
The sample tasks are arranged by the following priority:
least intrusive use of the fabric task API,
up to a full dependence on the fabric task API.
Each sample builds on the prior one, sometimes using a prior approach, for example, for input, but a different approach for output.
For Java and .NET, the examples line up by name for similar fabric task API usage.
For 'C', has only one extended example.
HelloWorldOne.java (in tutorial_samples/java/extended_hello_world/com/appistry/samples/extended_hello_world/)
001. package com.appistry.samples.extended_hello_world;
002.
003. import com.appistry.task.Annotations.TaskField;
004. import com.appistry.task.Annotations.TaskReturnValue;
005.
006. public class HelloWorldOne {
007.
008. // INPUT: on execution, map value for009. // key "greeting" into member property
010. @TaskField
011. publicString greeting;
012.
013. // INPUT: on execution, map value for014. // key "greetee" into member property
015. @TaskField
016. publicString greetee;
017.
018. // OUTPUT: map method return value into "hello"019. // key in current fabric request object
020. @TaskReturnValue(name="hello")
021. publicString greet() {
022. return greeting + " " + greetee + "!";
023. }
024. }
025.
HelloWorldTwo.java (in tutorial_samples/java/extended_hello_world/com/appistry/samples/extended_hello_world/)
001. package com.appistry.samples.extended_hello_world;
002.
003. import com.appistry.task.Annotations.FieldType;
004. import com.appistry.task.Annotations.TaskField;
005.
006. public class HelloWorldTwo {
007.
008. // INPUT: on execution, map value for009. // key "greeting" into member property
010. @TaskField
011. publicString greeting;
012.
013. // INPUT: on execution, map value for014. // key "greetee" into member property
015. @TaskField
016. publicString greetee;
017.
018. // OUTPUT: after execution, map local property as
019. // output value for"hello" key in current
020. // fabric request object
021. @TaskField(name = "hello", type = FieldType.OUT)
022. publicString hello;
023.
024. // NOTE: this is a void method, as we are
025. // returning value using @TaskField above.
026. public void greet() {
027. hello = greeting + " " + greetee + "!";
028. }
029. }
HelloWorldThree.java (in tutorial_samples/java/extended_hello_world/com/appistry/samples/extended_hello_world/)
001. package com.appistry.samples.extended_hello_world;
002.
003. import com.appistry.task.Annotations.FieldType;
004. import com.appistry.task.Annotations.TaskField;
005. import com.appistry.task.Annotations.TaskParameter;
006.
007. public class HelloWorldThree {
008.
009. // OUTPUT: after execution, map local property as
010. // output value for"hello" key in current
011. // fabric request object
012. @TaskField(name = "hello", type = FieldType.OUT)
013. publicString hello;
014.
015. // NOTE: this is a void method, as we are
016. // returning value using @TaskField above.
017.
018. // INPUT: on execution, map values from current
019. // fabric request object into method parameters
020. public void greet(@TaskParameter("greeting") String greeting,
021. @TaskParameter("greetee") String greetee) {
022.
023. hello = greeting + " " + greetee + "!";
024. }
025. }
HelloWorldFour.java (in tutorial_samples/java/extended_hello_world/com/appistry/samples/extended_hello_world/)
001. package com.appistry.samples.extended_hello_world;
002.
003. import com.appistry.task.ITaskRequest;
004. import com.appistry.task.Annotations.TaskParameter;
005. import com.appistry.task.Annotations.TaskRequest;
006.
007. public class HelloWorldFour {
008.
009. // NOTE: expose the current fabric request
010. // object as a local property, so that we
011. // can manipulate it in our task code.
012. @TaskRequest
013. public ITaskRequest request;
014.
015. // INPUT: on execution, map values from current
016. // fabric request object into method parameters
017. public void greet(@TaskParameter("greeting") String greeting,
018. @TaskParameter("greetee") String greetee) {
019.
020. String greeter = request.getUsername();
021. String hello = greeter + " says " + greeting + " " + greetee + "!";
022.
023. // OUTPUT: put value into key "hello" in
024. // current fabric request object
025. request.put("hello", hello);
026. }
027. }
HelloWorldFive.java (in tutorial_samples/java/extended_hello_world/com/appistry/samples/extended_hello_world/)
001. package com.appistry.samples.extended_hello_world;
002.
003. import com.appistry.task.ITaskRequest;
004. import com.appistry.task.Annotations.TaskRequest;
005.
006. public class HelloWorldFive {
007.
008. // NOTE: expose the current fabric request
009. // object as a local property, so that we
010. // can manipulate it in our task code.
011. @TaskRequest
012. public ITaskRequest request;
013.
014. public void greet() {
015. // INPUT: get input values from keys in
016. // current fabric request object
017. String greeter = request.getUsername();
018. String greeting = (String) request.get("greeting");
019. String greetee = (String) request.get("greetee");
020.
021. String hello = greeter + " says " + greeting + " " + greetee + "!";
022.
023. // OUTPUT: put value into key "hello" in
024. // current fabric request object
025. request.put("hello", hello);
026. }
027. }
HelloWorldOne.cs (in tutorial_samples/dotnet/extended_hello_world/extended_hello_world_app/)
0001. using System;
0002. using Appistry.Task;
0003.
0004. namespace Appistry.Samples.ExtendedHelloWorld
0005. {
0006. public class HelloWorldOne
0007. {
0008. // INPUT: on execution, map value for0009. // key "greeting" into member property
0010. private string greeting;
0011. [TaskProperty("greeting")]
0012. public string Greeting
0013. {
0014. get { return greeting; }
0015. set { greeting = value; }
0016. }
0017.
0018. // INPUT: on execution, map value for0019. // key "greetee" into member property
0020. private string greetee;
0021. [TaskProperty("greetee")]
0022. public string Greetee
0023. {
0024. get { return greetee; }
0025. set { greetee = value; }
0026. }
0027.
0028. // OUTPUT: map method return value into "hello"0029. // key in current fabric request object
0030. [return: TaskReturnValue("hello")]
0031. public string Greet()
0032. {
0033. returnString.Format("{0} {1}!", greeting, greetee);
0034. }
0035. }
0036. }
HelloWorldTwo.cs (in tutorial_samples/dotnet/extended_hello_world/extended_hello_world_app/)
00001. using System;
00002. using Appistry.Task;
00003.
00004. namespace Appistry.Samples.ExtendedHelloWorld
00005. {
00006. public class HelloWorldTwo
00007. {
00008. // INPUT: on execution, map value for00009. // key "greeting" into member property
00010. private string greeting;
00011. [TaskProperty("greeting")]
00012. public string Greeting
00013. {
00014. get { return greeting; }
00015. set { greeting = value; }
00016. }
00017.
00018. // INPUT: on execution, map value for00019. // key "greetee" into member property
00020. private string greetee;
00021. [TaskProperty("greetee")]
00022. public string Greetee
00023. {
00024. get { return greetee; }
00025. set { greetee = value; }
00026. }
00027.
00028. // OUTPUT: after execution, map local property as
00029. // output value for"hello" key in current
00030. // fabric request object
00031. private string hello;
00032. [TaskProperty("hello", PropertyType.OUT)]
00033. public string Hello
00034. {
00035. get { return hello; }
00036. set { hello = value; }
00037. }
00038.
00039. // NOTE: this is a void method, as we are
00040. // returning value using @TaskField above.
00041. public void Greet()
00042. {
00043. Hello = String.Format("{0} {1}!", greeting, greetee);
00044. }
00045. }
00046. }
HelloWorldThree.cs (in tutorial_samples/dotnet/extended_hello_world/extended_hello_world_app/)
0001. using System;
0002. using Appistry.Task;
0003.
0004. namespace Appistry.Samples.ExtendedHelloWorld
0005. {
0006. public class HelloWorldThree
0007. {
0008. // OUTPUT: after execution, map local property as
0009. // output value for"hello" key in current
0010. // fabric request object
0011. private string hello;
0012. [TaskProperty("hello", PropertyType.OUT)]
0013. public string Hello
0014. {
0015. get { return hello; }
0016. set { hello = value; }
0017. }
0018.
0019. // NOTE: this is a void method, as we are
0020. // returning value using @TaskField above.
0021.
0022. // INPUT: on execution, map values from current
0023. // fabric request object into method parameters
0024. public void Greet([TaskParameter("greeting")] string greeting,
0025. [TaskParameter("greetee")] string greetee)
0026. {
0027. Hello = String.Format("{0} {1}!", greeting, greetee);
0028. }
0029. }
0030. }
HelloWorldFour.cs (in tutorial_samples/dotnet/extended_hello_world/extended_hello_world_app/)
0001. using System;
0002. using Appistry.Task;
0003.
0004. namespace Appistry.Samples.ExtendedHelloWorld
0005. {
0006. public class HelloWorldFour
0007. {
0008. // NOTE: expose the current fabric request
0009. // object as a local property, so that we
0010. // can manipulate it in our task code.
0011. private ITaskRequest request;
0012. [TaskRequest]
0013. public ITaskRequest Request
0014. {
0015. get { return request; }
0016. set { request = value; }
0017. }
0018.
0019. // INPUT: on execution, map values from current
0020. // fabric request object into method parameters
0021. public void Greet([TaskParameter("greeting")] string greeting,
0022. [TaskParameter("greetee")] string greetee)
0023. {
0024. string greeter = Request.Username;
0025. string hello = String.Format("{0} says {1} {2}!", greeter, greeting, greetee);
0026.
0027. // OUTPUT: put value into key "hello" in
0028. // current fabric request object
0029. request["hello"] = hello;
0030. }
0031. }
0032. }
HelloWorldFive.cs (in tutorial_samples/dotnet/extended_hello_world/extended_hello_world_app/)
0001. using System;
0002. using Appistry.Task;
0003.
0004. namespace Appistry.Samples.ExtendedHelloWorld
0005. {
0006. public class HelloWorldFive
0007. {
0008. // NOTE: expose the current fabric request
0009. // object as a local property, so that we
0010. // can manipulate it in our task code.
0011. private ITaskRequest request;
0012. [TaskRequest]
0013. public ITaskRequest Request
0014. {
0015. get { return request; }
0016. set { request = value; }
0017. }
0018.
0019. public void Greet()
0020. {
0021. // INPUT: get input values from keys in
0022. // current fabric request object
0023. string greeter = Request.Username;
0024. string greeting = (string) request["greeting"];
0025. string greetee = (string) request["greetee"];
0026.
0027. string hello = String.Format("{0} says {1} {2}!", greeter, greeting, greetee);
0028.
0029. // OUTPUT: put value into key "hello" in
0030. // current fabric request object
0031. request["hello"] = hello;
0032. }
0033. }
0034. }
extended_hello_world.cpp (in tutorial_samples/cpp/extended_hello_world/extended_hello_world_app/)
The complete fabric applications for these samples can be found in the tutorial_samples/<lang>/extended_hello_world_app/ directory. This includes all of the process flow, task, and application definition files ready for fabric packaging. You just need to build the source code for the tasks.
Likewise, a client has been provided in each language that runs each of these fabric applications. The client source can be found in the tutorial_samples/<lang>/extended_hello_world directories.