MWS Task API behaviour

hi All,
Facing an issue with the Task API method calls. Could you please have a look at it?

Issue:

Trying to copy Task data from Task#1 to Task#2 immediately after an updation to Task #1.

pseudo code as follows:
Step 1: call applyChanges() method of MWS Task API for Task#1.
Step 2: call getTask() method of wmTaskClient API to get Task #1 details.
Step 3: call updateTask() method for Task#2 by giving the result of getTask() operation of Task#1.

Result: The task data modifications which I did by calling applyChanges() method is not reflected in Task#2.
But Task#1 has the updated details.

Environment details: webMethods 7.1.2, Clustered (2 MWS nodes are present in cluster, these 2 nodes are controlled by 1 load balancer)

I am trying to find the root cause of this problem. Can any one of the below hypothesis be true?

Hypothesis #1: applyChanges() method has an asynchronous behavior.

Analysis: Because of this, even before Task#1 changes are updated to MWS task database, control came to Step 2 and took the old details of Task#1 from database and gave it to updateTask method which is present in Step 3.

Hypothesis #2: applyChanges() and updateTask() methods have asynchronous behavior.

Analysis: Because of this, eventhough applyChanges() method is called ahead of updateTask() method, due to the asynchronous functionality of these two methods, updateTask() method executed first.

Hypothesis #3: applyChanges() and updateTask() methods have synchronous behavior but there is a delay(may be in milli sec.s) in the details propegation between the clustered nodes.

Analysis: applyChanges() method is called first and it copied the details to cluster node 1. Before the details gets copied to cluster node2, getTask operation is getting the task from node2 which does not has updated details.

Can any of these hypothesis be correct? If not, could you please let me know what could be the reason?

And what could be the work around for this issue?

Kind regards,
Raja sekhar Kintali

Hi
it is not clear to me if you’re using the MWS Task API directly in the java code of your portlet, if you’re using the IS WmTaskClient API or if you’re using both.
And, why do you call getTask() if you already have the Task#1 task data? you could use it directly for your Task#2, or?

best regards,
Javier

hi Javier,

Thanks for the response.

Step 1 (applyChanges method of MWS Task API call) is done in java code of my portlet.
After that we are calling one custom ESB service in which getTask() of wmTaskClient API for Task#1 (step 2) and updateTask() of Task#2 (step 3) is called.

We are re using this custom ESB service in 3 different portal packages. That is the reason we had to put this copy paste mechanism in ESB service.

Please let me know if I can provide more information.

Kind regards,
Raja sekhar Kintali

If possible, i’d recommend trying to perform the majority of your updates from within the Task Portlet Application itself. This is especially true if you are invoking the ESB services from within your task portlet.

So if the control flow looks like this:

User Action → Task Portlet App → ESB Service → WmTaskClient → Update Task

I’d recommend changing your approach to:

User Action → Task Portlet App → ESB Service → Data returned to Task Portlet App → Update Task

Regards,
–mark

hi Mark, Javier,

Thanks for your reply.

I could move the update functionality to portal, but still not clear the root cause of this issue.

The problem which I posted above is one of the few issues I am facing with Task Data updations.

Let me give you one more observation: (I am giving the details here instead of creating a new post, as both the problems are closely related, kindly excuse me if this is not the way).

Step 1: called applyChanges() method of MWS Task API for a task.
Step 2: called refresh() method of MWS Task API on the same task.
Step 3: checked the result TaskData of Step2 by putting logs in my code. It doesn’t has the details which I updated using applyChanges() method in Step1.

Please note that, this issue I observed only in cluster environment (with 2 nodes).

As per my understanding, this could only happen if any one of the above mentioned hypothesis(in Post#1) is correct.

Could you please give some inputs why refresh() method is not always giving the updated values in Cluster environment?

Kind regards,
Raja sekhar Kintali

BTW: Hypotheses #3 is correct as long as you are talking about the in-proc Task API (not the wmTaskClient API)

Regards,
–mark

hi Mark,

Thank you for the reply.

To make sure that I always get consistent data from the two Clustered MWS Nodes, is there any workaround available for the following scenarios?

  1. Is there any way to make sure that applyChanges() method of MWS Task API gives response to the calling party only after all the MWS nodes in Cluster are updated without drastic impact on performance?

(If there is no way, then on what presumption we can say that applyChanges() method has synchronous behavior?)

  1. Is there any way for refresh() method of MWS Task API to always get consistent data (a mechanism something like, refresh() method will wait till both the MWS nodes are in sync and then will give the results back to the calling party) in Cluster environment?

Kind regards,
Raja sekhar Kintali

Great questions.

The applyChanges() is synchronous in that before the API returns, the state of the current VM, Task Engine and the Database are all in sync. What isn’t synchronous is that the invalidation messages won’t be guaranteed to propagate across the cluster.

There isn’t a reasonable mechanism that one Task Engine Process can block until all the other Task Engine instances are notified.

There is a mechanism that you can ensure that you only update the latest version of any task instance, but that isn’t exactly what you are asking. What you are asking is for a cluster-wide lock of a task so that no other node can modify the task while you are interacting with it.

Another way to restate your question is:
Is there a cluster wide synchronization primitive that allows me to lock a task for exclusive write access?

The answer to that question is no. As i briefly touched on above, there is a mechanism to ensure that your code will only modify the newest version of the task.

Regards,
–mark

hi Mark,

Thank you so much for the detailed explanations to my questions and for your time.

As there isn’t a cluster wide synchronization primitive that allows me to lock a task for exclusive write access, it will impact our application with respect to task data retrieval and updations.

Could you please tell me the procedure to follow to ensure that my code will always modify the latest version of a task in cluster environment (for me, it sounds like providing exclusive write access on a task to cluster nodes, may be im not clear :frowning: )

Kind regards,
Raja sekhar Kintali

Our Task architect has provided a code example.



            int tries = 0;

            while (tries++ < 3) {

                  try {

                        // apply change to business data

                        getMyTask().getTaskData().setDataField1("data1");

                        getMyTask().getTaskData().setDataField2("data2");

                        // attempt to save changes

                        getMyTask().applyChangesNoAccept();

                  }

                  catch (ContentProviderException e) {

                        // check for specific error

                        if (e.getMessage()!= null && e.getMessage().contains("Task is out of date")) {

                              // reload task and try to update again

                              getEnterProposal().refresh();

                        }

                        else throw e; 

                  }

            }

Did not mean to hijack it, but it may be there is some mis-communication happening here:

This is what you describe is happening:

Step 1: called applyChanges() method of MWS Task API for a task.
Step 2: called refresh() method of MWS Task API on the same task.
Step 3: checked the result TaskData of Step2 by putting logs in my code. > It doesn’t has the details which I updated using applyChanges() method in Step1.

If that is indeed true - then it must be a bug OR we are missing some additional parts in this picture (like task being updated from IS services also). applyChanges() synchronously writes to the database all updates data and updates writeThrough cache. refresh() reads from the cache or if record is not in the cache from database. So it must be the same data you have just applied to.

Hi Alex,

As you mentioned, applyChanges() method synchronously writes to the database and cache.

As per the above quote, in cluster environment, applyChanges() method
has no control over the other cluster nodes, to copy the updated changes to the other cluster node’s cache,
which makes Hypothesis#3 to true!

Is this an expected behavior or a bug?

Kind regards,
Raja sekhar Kintali