onTaskCahanged event is not hit when inside a while activity - sharepoint-2007

I have a workflow that creates a new task at the time of creation of a new item in a given list. This new task is assigned to a user when created. Then, this task can either be reassigned or completed. If the task is completed, the workflow ends. If the task is reassigned, the task should be completed, another task should be created assigned to another user, and the workflow continues.
I have the issue that when the second task is created(first task is reassigned) the workflow ends and the onTaskChanged of the second task is never hit.
Any Ideas?

I found the error I had. I was trying to store an instance of SPFieldUserValue in a class variable of the workflow class. SPFieldUserValue is not serializable and was trhowing an error. This caused that the workflow terminated, so it just halted.

Related

Why Hybris modelService.save() doesn't work inside the ifPresent() method?

private void doSomething(someProcessModel process){
CustomerModel customer = process.getCustomerModel();
customer.getFoos().stream()
.filter(foo -> foo.getCountryCode().equals(process.getCountryCode()))
.findFirst()
.ifPresent(foo -> {
if(foo.getSomeNumber() == null){
foo.setSomeNumber("1234567");
modelService.save(foo);
}
});
}
As seen in the code snippet above, I have a 'CustomerModel' that has an attribute 'Foos'. It's a one-to-many relationship. As you can see I have done some filtering and in the end, I want to update the value of 'someNumber' attribute of 'Foo' if it is null. I've confirmed that everything is working as the "someNumber" attribute's value is updated during the debugging. It doesn't save at all as I have done my checking in the HMC. I have also validated that the Interceptor doesn't have any condition that would throw an error. There is nothing being shown in the log either.
I am wondering is it a legal approach to do the "modelService.save()' inside the 'ifPresent()' method? What could be the possible issue here?
I have found the root cause now as I have face the same issue again.
Context to my original question
To give more context to my original question, the #doSomething method resides in a Hybris Business Process action class and I have ended the action prematurely while I am debugging it (by stopping the debugging) once the #doSomething method is ran.
Root cause
The mentioned problem happened when I was debugging the action class. I assumed that the ModelService#save will persist the current state of the business process once it has been ran. However, the Hybris OOTB business process will do a rollback if there is any error (and I believe it was caused by me stopping the debugging half-way).
SAP Commerce Documentation:
All actions are performed inside their own transaction. This means that changes made inside the action bean run method are rolled back in case of an error.
Solution
Let the action runs completely!
Good to know
Based on the SAP Documentation and this blog post, there will be times that we will need to bypass a business process rollback even though there is an exception being thrown and there are ways to achieve that. More info can be found in this SAP Commerce Documentation and the mentioned blog post.
However, in some circumstances it may be required to let a business exception reach the outside but also commit the transaction and deal with the exception outside. Therefore, it is possible to make the task engine not roll back the changes made during a task which failed.
You have to be cautious with a list in models as they are immutable, you have to set the whole new list. Also you called save only on a particular model, which changes its Jalo reference, that's why your list is not updated. Mutating stream and collecting it in the end will create new list that's why you can stream over the list directly from the model.
private void doSomething(someProcessModel process){
CustomerModel customer = process.getCustomerModel();
ArrayList<FooModel> foos = doSomethingOnFoos(customer.getFoos());
customer.setFoos(foos);
modelService.saveAll(foos, customer);
}
//compare the value you know exists with something that might be NULL as equals can handle that, but not the other way around
private ArrayList<FooModel> doSomethingOnFoos(ArrayList<FooModel> fooList) {
return fooList.stream()
.filter(Objects::nonNull)
.filter(foo -> process.getCountryCode().equals(foo.getCountryCode()))
.filter(foo -> Objects.isNull(foo.getSomeNumber()))
.map(foo -> foo.setSomeNumber(1234))
.collect(toList());
}

DJI Waypoint mission listeners

I need to create/upload/start waypoint mission on one button. When user press button drone should move up for certain number of point based on current position. User can stop mission and again start new one. My logic here is next:
I initialize mission with points
Load mission
Add Listeners to mission operator
Upload mission
Mission starts on listener
missionOperator.addListener(toUploadEvent: self, with: DispatchQueue.main) { (event) in
if event.currentState == .readyToExecute {
self.startMission()
}
}
I'm reading documentation for days and trying to understand how this thing work, but I'm missing something obviously. Listeners are created on waypoint mission operator, but if I create listeners before loading mission they are not called. If I create listeners every time I load mission, startMission() is called multiple times (first time is called ones, but after one mission is stopped or finished, next time startMission() gets called two times)
So, I guess that my questions would be:
What is right moment to add listeners and to remove them since I'm calling startMission() from listeners? Actually what is appropriate way to init/upload/start mission on one button, and be able to do that multiple times?
You need to remove the upload listener when the the upload succeeded and the event state is readyToExecute. Also when the event contains an error, or the state is readytoupload/notsupported/disconnected. Pretty much in every case except when it's still in the state 'uploading'.
When you start the mission, add a listener for execution events, and one for finished. Remove those again when the mission is stopped/cancelled, has an error, or finishes successfully.
Even though you use Swift, I suggest looking at the more complete Objective C sample code, which includes examples of several different types of missions.

how to determine whether a queue is empty in Simevents and do some actions based on this observation?

I want to model a queue with vacations. When the queue is empty, the server will have a period of vacation with certain distribution.(I can use use gate to block the server ) So I need to get the data of the number of entity in queue block. Could you please tell me how to do that?
Many thanks.
The "number of entities in the Queue" can be found in the 'Statistics' tab of the Queue's properties.
Enabling it (clicking it's checkbox) will enable the signal of interest on the block (#n) that can be connected to other Simulink blocks.
Connect the #n signal to "compare to constant" block to create a boolean signal that indicates if the queue is / is not empty.

Adding a "Final" NSOperation to a Queue with Undetermined Number of Operations

I'm using AFNetworking as my network stack to communicate with a web service and populate a local data store. During synchronization runs, I have an array of API endpoints to run through, and when that run is complete, I add a final operation, which takes the resulting JSON to fill up the database.
The problem I'm having is that the result of some of those JSON-fetching operations requires me to call other endpoints, and now I don't know when I should add that "Final" operation.
The way I have things working now, I have a series of primary operations, and then add the "final" operation. During that time, the primaries have returned and caused me to create secondary operations, like so:
* Primary Fetch Operation A
* Primary Fetch Operation B
* Final Operation
* Secondary Fetch Operation B1
I need to figure out how to ensure that "Final Operation" is always going to run last.
One thing I've tried is adding an observer to the operation queue's operationCount property, but it seems that it can run down to 0 before a secondary operation is added.
Unfortunately I believe the observer won't work, AFNetworking invokes callbacks from the completionBlock of NSOperation and this means that the operation is already finished and removed from the queue, which explains why you have reached a operationCount of 0 before submit the secondary operation.
You could use a dispatch_group_t to accomplish this, before scheduling an operation (primary or secondary) you enter the group (dispatch_group_enter) and then when the operation completes you leave the group (dispatch_group_leave). If the finished operation requires a secondary operation before leaving the group follow the same pattern, enter the group again and schedule the secondary operation. Finally you will be notified (dispatch_group_notify) when all the operations have completed making the perfect time to schedule the final operation.

troubleshooting a NullPointerException in grails

preface note: I'm just starting to learn Grails, so I'm sure there are many other problems and room for optimization.
I've got two domains, a parent (Collection) and child (Event), in a one-to-many mapping. I'm trying to code an integration test for the deletion of children. Prior to the code in question, I've successfully created a parent and three children. The point where I'm having problems is getting a single child in preparation to delete it. The first line of my sample code is only there because of my rudimentary attempt to troubleshoot.
// lines 95-100 of my EventIntegrationTests.groovy file
// delete a single event
assertEquals("2nd Event", event2.title) // passes
def foundEvent = Event.get(event2.id) // no apparent problems
assertEquals("2nd Event", foundEvent.title) // FAILS (line #98)
foundEvent.delete()
assertFalse Event.exists(foundEvent.id)
The error message I'm getting is:
Cannot get property 'title' on null object
java.lang.NullPointerException: Cannot get property 'title' on null object
at edu.learninggrails.EventIntegrationTests.testEventsDelete(EventIntegrationTests.groovy:98)
What should my next troubleshooting steps be? (Since the first assertEquals passes, event2 is clearly not null, so at this point I have no idea how to troubleshoot the failure of the second assertEquals.)
This is not evident from the code: did you persist event2 by calling save()? Get will try to retrieve it from the persistent storage (the in-memory database for example) and if the event wasn't saved, the retrieved instance will be null.
If you did save it, did the save go through OK? Calling event.save() will return false if there was something wrong while saving the item (like a validation error). Lastly, you might try calling event.save(flush:true) in case the Hibernate session doesn't handle this case as you might expect (I'm not entirely sure about this one, but it can't hurt to try).
Try to print or inspect the event2.id on line 97 and check if you actually have an id, if so check if you actually get an Event object on line 97.
I dont think you saved the parent and its children successfully. after you save, you should make sure that every object that was persisted has a non null id, in your test.
What you are seeing is you created the event2 with a title, but didnt save it. It passes the first assertion because you created it. When you do the get, null is returned because your save failed.
in general for DAO integration tests i do the following
Setup -- create all objects Ill use in the test.
Save -- assert that all ids on saved objects are NOT null.
Clear the hibernate session -- this is important because if you don't do it, objects can be in the session from the previous operations. In your real world scenario, you are probably going to start with a find, i.e. an empty session. In other words, you are not going to start with anything in the session. If you are you need to adjust this rule so that the session in the test, when you start the actual testing part, is the same as the session of the code in the wild
Load the objects on which you want to operate and do what you need to do.

Resources