ABAP/4 Programming for SAP book

My experience reading the ABAP/4 Programming for SAP book

Continue Reading Add comment October 11, 2009

Celebrity Apprentice II: Wedding Dresses

I am watching Celebrity Apprentice II. Today, the girl team has the advantage, because they are supposed to sell the wedding dresses. Of course, the girl team is good at it compared with the men team.

Continue Reading Add comment July 26, 2009

Why do I want a Mac computer

Brief reasons why I need a Mac instead of a PC.

Continue Reading Add comment July 20, 2009

Learn German from VW ads

Volkswagen Ads

Volkswagen Ads

“Schade, dass man nach Amerika nicht fahren kann” probably means “what a pity that a man can not drive to America.” At first, I thought that it meant “what a pity that a man can not travel to Americal” which does not make sense, because a man can travel to America by an airplane. The important verb word here is “fahren” which means “travel.” Then, I realized that the “fahren” word could mean “drive” as well. Then, it made sense to me.

Add comment June 21, 2009

Lost in Translation

My experineces regarding the use of new language.

German

1) Last month, I was in the terminal in Frankfurt airport. The airplane was late for 2 hours, so the airline  gave the passengers snacks and drinks. The airline also brought a big shelve of magazines. I heard, “Alles muss raus,” so I though they meant, “everything must go.” I went to take a lot of magazines, but then I realized that they meant, “everyone get out.” The ground workers were clearing the passengers to move out from the gate area. The ground workers wanted to check tickets of each passenger before the passengers can move into the gate area.

At first, I thought that they mean, “everything must go,” because they put out snacks, drinks and magazines. I remembered that when a store is closed, a sign written “alles muss raus”  is put in front of the store to advertise goods.

2) The word “Sie”  in German has many meanings. “Sie,” when starting a sentence,  could mean “they”, “you,” or “she.” I was speaking to one teacher telling her about my friends, and the teacher talked to me and used the word “Sie.” My German was very weak back then. I was not sure what the exact meaning that she meant. If I could catch the form of the verb used, I might be able to determine the exact meaning, so I asked back something like, “You mean Sie (you) or Sie (they). 

English

1) When I was a kid, I saw a westener come toward me and asked me if I can speak English. At that time, I just came out from the English course. I answered him, “yes.” However, after that I did not understand what he said. It’s quite funny. I should have said, “no.”

Add comment April 13, 2009

SAP BW/SEM online course

Last semester of my master study, I have taken the SAP online course from U. of Duisburg-Essen called, “Introduction to SAP BW/SEM (Einführung in SAP BW/SEM)” focussing on SAP BW and SEM modules.  This course is no longer offered anymore, but there is a new course called, “Introduction to SAP BI (Einführung in SAP BI)” focussing solely on SAP BW.

 

 The cost of the course is 450 EUR. It was a lot of money for me. I think that it would be more expensive If I am not a student. Anyway, I could experience and learn the SAP while I was a student. 

About about my experience taking this course, I liked the course. Students are required to complete exercises even though there are solution or answers to the exercises. I have an opportunity to learn the basic of  BW (Business Warehouse) and SEM (Strategic Enterprise Management) modules. There are scripts which contain the theory part and the practical part mixed together used by students to study at their own pace. 

The course is German. I moved slowly at the beginning due to my weakness in German. I spent sometimes opening a dictionary and translating text. It paid off well later. I spent less time opening a dictionary and translating text later.

For BW module, I have known the data warehouse concept before from my bachelor, so it helps me to quickly understand the theory part including data cube and star schema (kind of a design of tables in a data warehouse). The theory part is partially based on or similar to the “Data Warehousing mit dem SAP Business Information Warehouse“ theory script from Technical University of Munich (Technische Universität München). For the practical part, it was quite frustrating in the beginning to learn about various terms used in SAP BW including transfer structure, communication structure, data source, info source, data object, update rule, transfer rule, etc. Anyway, I was glad that I could overcome it and finish the course. You may read the “SAP BW Grundlagen (p. 29)” slides in German which is useful for explaning terms used in SAP BW.

Add comment April 13, 2009

Some German words are built by combining other words

I learned deutsch (German) today. It is better for me to write it down, so I do not forget.

1)  word + word

There are some words in Germany built by combining other words. For example, the “züruckbezahlen” (pays back) word   consists of two words: “zurück” (back) and “bezahlen” (pay). This word is listed in dictionaries. However, there are some combined words  not listed in dictionaries which could be quite frustrating for a new beginner when he or she can not find the combined word meaning from dictionaries.

There are words which have different meanings when combining it together. For example, the “sitzen bleiben” means to sit on the chair, and “sitzenbleiben” means to repeat the course in the school again.

There is a joke. There are two sentences. Words are the same. They are written a bit differently. They have different meaning. 

- Ich gehe in die Klasse, um dort sitzen zu bleiben. (I go into the class just to sit there.)

- Ich gehe in die Klasse, um dort sitzenzubleiben. (I go into the class to review the learned material again there)

A kid may say that I am going into the class just to sit there, but their parents may though that their child goes into the class to study. 

2) word + one character + word

Sometimes, two words are connected together with a single character. For example, the “Wirtschaftskrise” (Economic crisis) has a character “s” in the middle to connect “Wirtschaft” and “Krise.” The actual meaning is “Krise der Wirtschaft” (Crisis of the econimic). If you understand genitiv, then you would understand the function of the article “der” here which means “of.”  Another example is “Wirtschaftslage” (“Lage der Wirtschaft,” Situation of economic).

1 comment October 25, 2008

Scarce and Abundance

First of all, I am not an expert in economic. I just write what I think. It maybe incorrect.

I remembered that I attend the Informatics Entrepreneurship II course, and there was a student asking a teacher about how could the music industry deals with the copyright infringement problem. The music industry was losing money, because people do not buy their CDs. The guest speaker introduces the concept of scarce and abundance. At any given time for something, there are something a little (scarce), and there are something a lot (abundance). For example, for the music industry, the abundance is the music available from the Internet, and the scarce could be the concert ticket.

In my opinion, it is necessary for an entrepreneur to detect what is scarce and abundant. I agree with the guest speaker on the scarce and abundance concept. 

In 1997, there was  an economic crisis in Thailand. Before the crisis, the real estate was bubble. People bought real estate (houses or land) for investment, but they did not buy real estate for living or do something. They hoped that the prices would increase. The prices of real estate were indeed increased. However, after the economic crisis, the prices drop significantly. People do not have money to pay back to the bank. When people can not pay back, the banks took the real estate properties. The abundance would be a lot of cheap real estate. The scarce would be the money. If anyone had bought the cheap real estate properties at that time, they could sell at very high price now, because the real estate business has improved. The situation is similar to the credid crisis occurred in USA recently. If any one has money, they can buy a house cheaply. 

 

 

 

If I remembered correctly, the guest speaker also mentioned about the situation in 2001 for IT companies. A lot of companies laid out software developers. Abundance would be the programmers. If anyone with money, they can start an IT company cheaply by hiring those laid out  programmers cheaply. When the economic is back, they can sell their IT products.

Add comment October 20, 2008

Curious about the Correlation example in Microsoft Windows Workflow Foundation Step by Step book

I have read the Microsoft Windows Workflow Foundation Step by Step book.  Overall, it is a good reference book.

 

However, I am not quite sure about the application example illustrated in the Microsoft Windows Workflow Foundation Step by Step book in “External Data Communication” section. The example may not illustrate the true purpose of using the correlation parameter.

The example is about a process of a truck. One workflow has only one truck. There could be many workflows in the system. Each workflow has one truck ID. A truck ID is part of the correlation parameter. 

Perhaps, I am wrong. It seems to me that the application try to use the truck ID to differentiate different workflows, so the runtime could send the message to the correct workflow.  I think that the runtime uses Guid which is a workflow instance ID stored in the EventArgs object. The EventArgs is created when the runtime fires an event to the workflow. This Guid is used to differentiate between different workflows, but not the correlation parameter.

Activities in the same conversation are chained together through the value of the correlation parameter.  A better example of using the correlation parameter could be that there are many tasks running parallel in a workflow. Note, this example could be found in my previous blog, “Communication Between Inside And Outside Of A Workfow In Windows Workflow.” Each task sends a request and waits for response. Each task has uniquely Task ID. The response sent by task 1 would go back to task 1. The response sent by task 2 would go back to task 2. In this case, there are two values of Task ID which are 1 and 2. The example found in the book simply has  only one Truck ID for the whole workflow which is not make sense.

I think that the objective of the correlation parameter is to bring back an event from outside to the correct activity in a workflow, not to bring back an event to the correct workflow.

Add comment October 20, 2008

Communication between inside and outside of a workfow in windows workflow

In this blog, I will demonstrate an example of communication between outside of a workflow and the workflow.  Let’s assume that a workflow consists of tasks. We need to send task information to outside of a workflow, and outside can send a result back into a workflow. 

Basically, our workflow consists of tasks. There is nothing much going on in a task except that there is communication between a workflow and outside of a workflow. A workflow needs to inform the outside what task is, and the outside has to inform the workflow result of the task. We would like to group of these logics into a composite activity.

Mike Taulty provided an easy understanding screencast called, “Windows Workflow Foundation: Two-Way Host/Workflow Communication,”  ”Windows Workflow Foundation: Workflow to Host Communication,” and “Windows Workflow Foundation: Host to Workflow Communication.” Source codes presented here are adapted from Mike Taulty’s screencasts.

1) Defining an interface for a local service

A local service is needed  for communication.  Please refer to this MSDN page, “Using Local Services in Workflows” for a better understanding of the local service. A local service runs independently outside of a workflow. If a workflow would like to send a message to outside, it sends through a local service. If an outside wants to send a message to a workflow, it sends through a local service. We need to define the interface containing a function which a workflow will call to outside and an event which outside sends an event to a workflow. We have defined an interface called ILocalService1. A local service is a class which will implement this ILocalService1 interface.

[ExternalDataExchange]

public interface ILocalService1

{

void distributeTask(int task_id, string workDescription, Guid workflowInstanceID);

event EventHandler<TaskEventArgs> taskEventArgsEventHandler;

}

The interface defines one function, distributeTask, and one  event, taskEventArgsEventHandler.  

- The distributeTask function is used by a workflow to send a message to outside of a workflow which can be done using the CallExternalMethod activity. Please refer to Tiago Oliveira blog, “Using WF CallExternalMethod activity in Windows Workflow” for a better understanding of the CallExternalMethod activity.

- The taskEventArgsEventHandler event is used when the outside wants to send a message to a workflow which can be done by the HandleExternalEvent activity. The TaskEventArgs class is used to contain data sent from outside. Following is the TaskEventArgs class. 

[Serializable]

public class TaskEventArgs : ExternalDataEventArgs

{

public TaskEventArgs(Guid instanceId) : base(instanceId) 

}

private int task_id;

public int Task_id

{

get { return task_id; }

set { task_id = value; }

}

private string status;

public string Status

{

get { return status; }

set { status = value; }

}

}

A workflow instance ID, instanceId, is needed for creating a TaskEventArgs object, so that an event is sent to the correct workflow. The TaskEventArgs class contains two fields: task_id and status. These two fields are data that we send into a workflow.

2) Creating a local service class by implementing an interface

Next, we need to to create a local service class by implementing the ILocalService1. The distributeTask function is fake. It does not distribute a task to a resource. It just sleeps for a period of time to stimulate that someone has performed a task. 

[Serializable]

public class LocalService1 : ILocalService1

{

        private int count = 5;

        void ILocalService1.distributeTask(int task_id, string description,  Guid workflowInstanceID)

        {

            ThreadPool.QueueUserWorkItem(delegate

            {

                count–;

                Thread.Sleep(count * 15000); //sleep for a certain period of time

               //create taskEventArgs and set its field

                TaskEventArgs taskEventArgs = new TaskEventArgs(workflowInstanceID);

                taskEventArgs.Task_id = task_id;

                taskEventArgs.Status = “finished”;

 

                if (taskEventArgsEventHandler != null)

                {

                    taskEventArgsEventHandler(this, taskEventArgs); //Firing the taskEventArgsEventHandler 

                }

            }

            );

        }

        public event EventHandler<TaskEventArgs> taskEventArgsEventHandler;

}

The distributeTask function is called by a workflow. It sleeps for a certain period of time. It creates a taskEventArgs parameter which it will sent into a workflow when it firs an taskEventArgsHandler event. 

3) Custom activity for communication between a workflow and outside

Our composite activity has to call the distributeTask defined in the local service, LocalService1, to send a task data to outside. When  outside finishes performing a task, it sends back a task’s result through firing the taskEventArgsEventHandler event.

3.1 Go ahead and add a new activity into a workflow project.

3.1 Add four activites sequentially : codeActivity1, callExternalActivity1, handleExternalActivity1, and codeactivity2. 

 

Creating a custom activity which would call an external method and wait for an external event

Creating a custom activity which would call an external method and wait for an external event

We would like to define two dependency properties as metadata for this composite activity. Please refer to my previous blog for creating a metadata.

3.2 Open the code view of this composite activity and add two dependency properties : Task_idProperty and WorkDescriptionProperty. A dependency property is used here as a metadata property for our custom activity. Metadata property can be edited only in design time, not in the runtime. 

Task_idProperty represents the task ID.

WorkDescriptionProperty represents the work description of this particular task.

 

//class Activity1

public static DependencyProperty Task_idProperty = DependencyProperty.Register(

            “Task_id”, typeof(System.Int32), 

            typeof(callexternal.Activity1),

             new PropertyMetadata(DependencyPropertyOptions.Metadata) );

 

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]

        [BrowsableAttribute(true)]

        [CategoryAttribute("Parameters")]

        public Int32 Task_id

        {

            get

            {

                return ((int)(base.GetValue(callexternal.Activity1.Task_idProperty)));

            }

            set

            {

                base.SetValue(callexternal.Activity1.Task_idProperty, value);

            }

        }

 

        public static DependencyProperty WorkDescriptionProperty = DependencyProperty.Register(

            ”WorkDescription”, typeof(System.String), typeof(callexternal.Activity1),

             new PropertyMetadata(DependencyPropertyOptions.Metadata));

 

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]

        [BrowsableAttribute(true)]

        [CategoryAttribute("Parameters")]

        public String WorkDescription

        {

            get

            {  

                return ((string)(base.GetValue(callexternal.Activity1.WorkDescriptionProperty)));

            }

            set

            {

                base.SetValue(callexternal.Activity1.WorkDescriptionProperty, value);

            }

        }

3.3 Add two fields to our custom activity class. They are tmpWorkflowInstanceID of type Guid representing a workflow’s instance ID and tmpTaskEventArgs of type TaskEventArgs representing an input from outside.  This field will store a workflow instance ID which we can retrieve in the codeActivity1. It will be passed to outside when calling the distributeTask function in the LocalService1. 

public static Guid tmpWorkflowInstanceID ;

public TaskEventArgs tmpTaskEventArgs = default(callexternal.TaskEventArgs);

3.4 Implementing the codeActivity1   

- Type the function name which is “StartActivity” in the ExecuteCode textbox in the properties window of the codeActivity1. Press enter and the StartActivity function is generated.

 

Add a function for the codeActivity1

Add a function for the codeActivity1

The StartActivity function looks like following.

private void StartActivity(object sender, EventArgs e)

{

          //initialize the workflow instance ID

            tmpWorkflowInstanceID = this.WorkflowInstanceId;

            Console.WriteLine(“Task : “ + this.Task_id+ ” is started of workflow ” + tmpWorkflowInstanceID);

            Console.WriteLine(“Description : “ + this.WorkDescription );

}

3.5 Implement the callExternalActivity1

3.5.1 Select an interface implemented by a local service.

 

Select an interface implemented by a local service

Select an interface implemented by a local service

 

The callExternalActivity1  activity will call distributeTask function which has three parameters: int task_id, string description and  Guid workflowInstanceID. These variable appeared on the properties window. We bind these varibles into fields of the custom activity which we have declared before in the 3.2 and 3.3 section. When binding, there are two things to set: name and path. Name is the parent object containing a field. In this case, it is the custom activity, Activity1. Path is the field in the parent object. Path refers to a field of the parent object. You can bind variables easily by clicking on a small button at each variable textbox in the property window.

3.5.2 Bind task_id to Task_id field.

Binding a task_id parameter of the function that the workflow calls to the Task_id field of the custom activity, Activity1

Binding the task_id parameter of the function that the workflow calls to the Task_id field of the custom activity, Activity1

3.5.3 Bind workDescription to WorkDescription field.

Binding the workDescription parameter to the WorkDescription field of the custom activity, Activity1.

Binding the workDescription parameter to the WorkDescription field of the custom activity, Activity1.

3.5.4 Bind workflowInstanceID to tmpWorkflowInstanceID.

Binding the workflowInstanceID parameter to the tmpWorkflowInstanceID field of the custom activity, Activity1.

Binding the workflowInstanceID parameter to the tmpWorkflowInstanceID field of the custom activity, Activity1.

 

3.6 Implement the handleExternalEventActivity1  

When the local service fires an event, it passes TaskEventArgs object into a workflow, so we store it into a variable of the custom activity, Activity1, called tmpTaskEventArgs.

Binding an event argument passed from outside into a workflow to tmpTaskEventArgs of the custom activity, Activity1

Binding an event argument passed from outside into a workflow to tmpTaskEventArgs of the custom activity, Activity1

 

3.7 Implement the codeActivity2  

Finally, we just print out the values of fields here. Type “finishActivity” in the executeCode textbox in the property window of the codeActivity2 activity.

 private void finishActivity(object sender, EventArgs e)

{

            Console.WriteLine(“Task “ + this.Task_id  + ” receives taskEventArgs “ + tmpTaskEventArgs.Task_id + ” : “ + tmpTaskEventArgs.Status );

}

 

4) Create a workflow

You need to build first. If the build is successful, the activity1 will be added into the toolbox of the workflow designer. 

4.1 Open up the workflow in the workflow designer and drop the custom activity, Activity1. Add five of the activity1. A ParallelActivity is needed at the top. Then add SequenceActivity up to 5. Then add the custom activity, Activity1, into each SequenceActivity.

Design a workflow

Design a workflow

4.2 Remember that we have declared two metadata properties in the section 3.2 (Task_id and WorkDescription). Let’s initialize it by selecting a custom activity and typing a value in the property window as shown below.

Initialize the metadata properties (Task_id and WorkDescription) that we have declared as dependency properties of the custom activity, Activity1, before.

Initialize the metadata properties (Task_id and WorkDescription) that we have declared as dependency properties of the custom activity, Activity1, before.

 

 

5) Add the ExternalDataExchangeService and the local service to the workflow runtime

In the main function, declare a new ExternalDataExchangeService object called dataService. Add dataService into the workflow runtime. Finally, add the local service class, LocalService1, into the dataService.

 

class Program

{

        static void Main(string[] args)

        {

            ExternalDataExchangeService dataService = new ExternalDataExchangeService();

 

            using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())

            {

                workflowRuntime.AddService(dataService);

                dataService.AddService(new LocalService1());//add local service

                AutoResetEvent waitHandle = new AutoResetEvent(false);

                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};

                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)

                {

                    Console.WriteLine(e.Exception.Message);

                    waitHandle.Set();

                };

 

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(callexternal.Workflow1));

                instance.Start();

                waitHandle.WaitOne();

            }

            Console.ReadLine();

        }

    }

 

6) Run the workflow

You would see that the workflow works incorrectly. A TaskEventArgs for task 1 should go back to task 1. If you noticed, I have changed reverse the order that the local service will send an event back to the workflow.

 

Incorrect result

Incorrect result

Therefore, we need to use the correlation parameter.

 

7) Adding correlation parameter

The purpose of the correlation parameter is to identify an activity which outside sends a message to. 

You can also read about the correlation parameter from the Programming Windows Workflow Foundation book (chapter eight). Please refer to ”Mike Taulty’s screencast on Correlation” for a quick tutorial on the correlation parameter.

7.1) Add Correlation Attributes to the Local Service Interface

The task_id parameter is chosen as the correlate parameter. Please remember that each custom activity, Activity1, has a unique Task_id field. The value in the Task_id field will be passed through the distributeTask function. Please refer to the MSDN page, “Using Correlation in Workflows,” for further information on correlation attributes: CorrelationParameter, CorrelationInitializer and CorrelationAlias.

 

[CorrelationParameter("task_id")]

[ExternalDataExchange]

public interface ILocalService1

{

[CorrelationInitializer]

void distributeTask(int task_id, string workDescription, Guid workflowInstanceID);

[CorrelationAlias("task_id", "e.Task_id")]

event EventHandler<TaskEventArgs> taskEventArgsEventHandler;

}

 

7.2) Set correlation token name

7.2.1 A Correlation Token is a string indicating a conversation between activities.  A correlation token   on both  handleExternalEventActivity1 and callExternalMethodActivity1  activities are needed to be set to the same value, so both activities binded into the same conversation, and when a call is made from the callExternalMethodActivity1, the workflow runtime can return it to this handleExternalActivity1 in this custom Activity1, not other handleExternalActivity1 of other  activities.  In this case, we set the correlation token to be “tc1″ on both activities.

 

Set CorrelationToken of the CallExternalMethodActivity1 of the custom activity, Activity1.

Set CorrelationToken of the callExternalMethodActivity1 of the custom activity, Activity1.

 

iii

Set CorrelationToken of the handleExternalActivity1 of the custom activity, Activity1.

 

7.2.2 Run the application 

Correct result

Correct result

 

Finally, the result is correct.

 

 

 

 

Project file : without correlation and with correlation.

1 comment October 18, 2008

Previous Posts


Categories

Top Posts

Recent Posts

Pages

Archives

 

November 2009
M T W T F S S
« Oct    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Blogroll

Books

Blog Stats

Top Clicks

Category Cloud

database Distributed application Education emergency response entrepreneurship firefighter (Feuerwehr) Flex/Flash German Language (Deutsch) Java Microsoft and .NET Risk Management (Disaster) Software Testing Uncategorized User Interface Design and Technology wcf Windows Workflow

Spam Blocked