How to control jobs of different families in eclipse - eclipse

How to control jobs from different families
For example, when I perform the following actions in eclipse:
From the "Project" menu , select "Clean". Then the dialog appears I click on "OK" button.
Then " Cleaning all Projects " operation begins. In the middle of the operation I try to delete some file from my workspace.
the following dialog appears, "User operation is waiting" where the first operation which I did "Cleaning all operation" progress continues. And the second "Delete" operation will be blocked showing the "lock" symbol with message "Blocked: the user operation is waiting for cleaning all projects to complete". After completing the first operation only, the "Delete" operation dialog appears.
What I need?
I am trying to get the similar situation as above in my project.
I have created one job family for my project following the tutorial "On the Job eclipse".
I schedule the job to perform some operation in background.
as soon as the operation progresses, i tried to delete the file. As soon as I select "Delete" , Delete dialog appears. However, what I need is to Block this Delete operation until the first operation which I performed completes similar way as I told in the above example.
How it can be done using eclipse jobs.? I tried with job.join(), job.setPriority() and all....
If you have any idea please share

You use 'scheduling rules' to define which jobs can run at the same time. A scheduling rule is a class which implements the ISchedulingRule interface.
A simple rule would be:
public class MutexRule implements ISchedulingRule
{
#Override
public boolean isConflicting(ISchedulingRule rule)
{
return rule == this;
}
#Override
public boolean contains(ISchedulingRule rule)
{
return rule == this;
}
}
which will only allow one job with this rule to run at a time. Use like this:
ISchedulingRule rule = new MutexRule();
Job job1 = new ....
Job job2 = new ....
job1.setRule(rule);
job2.setRule(rule);
job1.schedule();
job2.schedule();
Note that IResource extends ISchedulingRule and implements a rule to stop two jobs accessing the same resources at a time.
So to have only one job modifying the workspace at a time you can use:
ISchedulingRule rule = ResourcesPlugin.getWorkspace().getRoot();
(since IWorkspaceRoot extends IResource). Eclipse uses this rule for many jobs.
You can also use IResourceRuleFactory to create rules for controlling access to resources.
IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory();
There is also a MultiRule class which allows you to combine several scheduling rules.

Related

Eclipse P2 IUQuery alway has empty result

I try to use eclipse P2 to enable a tool of mine for auto-updating itself on eclipse start up. While doing so, I want to use an UpdateOperation which is only suited to "my" feature with id "my.feature.id". Whenever this query gets issued in an eclipse installation it has an empty result and thus nothing to update.
So: How do I use the QueryUtil right to get a collection containing only my feature for update as input for an UpdateOperation?
The following method is called when wanting to start the update on eclipse start up:
public class P2Util {
public static IStatus checkForUpdates(IProvisioningAgent agent, IProgressMonitor monitor) {
ProvisioningSession session = new ProvisioningSession(agent);
IQuery<IInstallableUnit> query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery("my.feature.id"));
UpdateCheckActivator.info("Update Query Expression: " + query.getExpression());
IProfileRegistry registry= (IProfileRegistry)agent.getService(IProfileRegistry.SERVICE_NAME);
IProfile profile= registry.getProfile(IProfileRegistry.SELF);
IQueryResult<IInstallableUnit> result = profile.query(query, monitor);
Set<IInstallableUnit> unitsForUpdate = result.toUnmodifiableSet();
UpdateOperation operation = new UpdateOperation(session, unitsForUpdate);
}
}
The solution is very simple but confusing at first. The query trying to find features with "my.feature.id" was querying for the wrong id.
In the feature.xml of my feature it is "my.feature.id" but the installable unit gets for unobvious reasons the suffix "feature.group". If one adds this to the id in the query, you get the correct result and the update operation succeeds as expected.

Jbehave : GivenStories in the end of execution

I'm using a GivenStories for executing Login scenario which is located in different story.
I was wondering if there is a way to use something similar in order to execute a logout story which is also located in different story than one I actually executing.
I know that I can do some tricks with #before/after annotations , but the question is if I can execute a "post" story
Thanks
Based on the jBehave annotation documentation a post story step can be implemented by annotating a step class method with #AfterStory (or #AfterStories if you want to execute only after all stories complete). The #AfterStory method will execute regardless of whether your executing story contains a step from the related step class (i.e. is guaranteed to execute after every story - see below for restricting to given stories).
The #BeforeStory and #AfterStory annotations allow the corresponding
methods to be executed before and after each story, either a
GivenStory or not:
#AfterStory // equivalent to #AfterStory(uponGivenStory=false)
public void afterStory() {
// ...
}
#AfterStory(uponGivenStory=true)
public void afterGivenStory() {
// ...
}
This is the answer I got from the jbehave dev channel.
Hi,
there is no such mechanism, but you could:
use the Lifecycle to execute steps (not stories) after the execution
of a scenario (executed after each scenario) have a final scenario
which invokes the given stories

reusable sub process in JBPM 6.1

I want to create a reusable sub processes in jbpm 6, but I cant't see any processes in Called Element pop up. It doesn't load any process information. Please can anyone give me the reason for this situation?
I'm not sure I completely understand your question/issue. However, I have successfully used reusable suprosses in JBPM 6.1.0.Final and eclipse.
These are steps:
Create a resuable subprocess with and ID. Make note the ID for steps 2-5.
Drag and Drop a "Call Activity" Activity to the bpmn
Edit the properties of the "Call Activity" - click on "Call Activity" and go to eclipse properties tab.
Click on "pencil" edit icon:
Enter the reusable subprocess id in edit window and type reusable subprosses id and hit o.k.
You should be able to run you bpmn and see the execution of subprocess.
I've just hitted this error today at work, using 6.1.0.Final. If process id has underscores it will not show in workbench called activity popup. Look at the sources:
Asset<String> processContent = ServletUtil.getProcessSourceContent(p, profile);
Pattern idPattern = Pattern.compile("<\\S*process[^\"]+id=\"([^_\"]+)\"", Pattern.MULTILINE);
Matcher idMatcher = idPattern.matcher(processContent.getAssetContent());
if(idMatcher.find()) {
String pid = idMatcher.group(1);
String pidcontent = ServletUtil.getProcessImageContent(processContent.getAssetLocation(), pid, profile);
if(pid != null && !(packageName.equals(processPackage) && pid.equals(processId))) {
processInfo.put(pid+"|"+processContent.getAssetLocation(), pidcontent != null ? pidcontent : "");
}
}
That regex used to get process id will not match "_". Check that your process id is valid.

CQ5 / AEM5.6 Workflow: Access workflow instance properties from inside OR Split

TL;DR version:
In CQ workflows, is there a difference between what's available to the OR Split compared to the Process Step?
Is it possible to access the /history/ nodes of a workflow instance from within an OR Split?
How?!
The whole story:
I'm working on a workflow in CQ5 / AEM5.6.
In this workflow I have a custom dialog, which stores a couple of properties on the workflow instance.
The path to the property I'm having trouble with is: /workflow/instances/[this instance]/history/[workItem id]/workItem/metaData and I've called the property "reject-or-approve".
The dialog sets the property fine (via a dropdown that lets you set it to "reject" or "approve"), and I can access other properties on this node via a process step (in ecma script) using:
var actionReason;
var history = workflowSession.getHistory(workItem.getWorkflow());
// loop backwards through workItems
// and as soon as we find a Action Reason that is not empty
// store that as 'actionReason' and break.
for (var index = history.size() - 1; index >= 0; index--) {
var previous = history.get(index);
var tempActionReason = previous.getWorkItem().getMetaDataMap().get('action-message');
if ((tempActionReason != '')&&(tempActionReason != null)) {
actionReason = tempActionReason;
break;
}
}
The process step is not the problem though. Where I'm having trouble is when I try to do the same thing from inside an OR Split.
When I try the same workflowSession.getHistory(workItem.getWorkflow()) in an OR Split, it throws an error saying workItem is not defined.
I've tried storing this property on the payload instead (i.e. storing it under the page's jcr:content), and in that case the property does seem to be available to the OR Split, but my problems with that are:
This reject-or-approve property is only relevant to the current workflow instance, so storing it on the page's jcr:content doesn't really make sense. jcr:content properties will persist after the workflow is closed, and will be accessible to future workflow instances. I could work around this (i.e. don't let workflows do anything based on the property unless I'm sure this instance has written to the property already), but this doesn't feel right and is probably error-prone.
For some reason, when running through the custom dialog in my workflow, only the Admin user group seems to be able to write to the jcr:content property. When I use the dialog as any other user group (which I need to do for this workflow design), the dialog looks as though it's working, but never actually writes to the jcr:content property.
So for a couple of different reasons I'd rather keep this property local to the workflow instance instead of storing it on the page's jcr:content -- however, if anyone can think of a reason why my dialog isn't setting the property on the jcr:content when I use any group other than admin, that would give me a workaround even if it's not exactly the solution I'm looking for.
Thanks in advance if anyone can help! I know this is kind of obscure, but I've been stuck on it for ages.
a couple of days ago i ran into the same issue. The issue here is that you don't have the workItem object, because you don't really have an existing workItem. Imagine the following: you are going through the workflow, you got a couple of workItems, with means, either process step, either inbox item. When you are in an or split, you don't have existing workItems, you can ensure by visiting the /workItems node of the workflow instance. Your workaround seems to be the only way to go through this "issue".
I've solved it. It's not all that elegant looking, but it seems to be a pretty solid solution.
Here's some background:
Dialogs seem to reliably let you store properties either on:
the payload's jcr:content node (which wasn't practical for me, because the payload is locked during the workflow, and doesn't let non-admins write to its jcr:content)
the workItem/metaData for the current workflow step
However, Split steps don't have access to workItem. I found a fairly un-helpful confirmation of that here: http://blogs.adobe.com/dmcmahon/2013/03/26/cq5-failure-running-script-etcworkflowscriptscaworkitem-ecma-referenceerror-workitem-is-not-defined/
So basically the issue was, the Dialog step could store the property, but the OR Split couldn't access it.
My workaround was to add a Process step straight after the Dialog in my workflow. Process steps do have access to workItem, so they can read the property set by the Dialog. I never particularly wanted to store this data on the payload's jcr:content, so I looked for another location. It turns out the workflow metaData (at the top level of the workflow instance node, rather than workItem/metaData, which is inside the /history sub-node) is accessible to both the Process step and the OR Split. So, my Process step now reads the workItem's approveReject property (set by the Dialog), and then writes it to the workflow's metaData node. Then, the OR Split reads the property from its new location, and does its magic.
The way you access the workflow metaData from the Process step and the OR Split is not consistent, but you can get there from both.
Here's some code: (complete with comments. You're welcome)
In the dialog where you choose to approve or reject, the name of the field is set to rejectApprove. There's no ./ or anything before it. This tells it to store the property on the workItem/metaData node for the current workflow step under /history/.
Straight after the dialog, a Process step runs this:
var rejectApprove;
var history = workflowSession.getHistory(workItem.getWorkflow());
// loop backwards through workItems
// and as soon as we find a rejectApprove that is not empty
// store that as 'rejectApprove' and break.
for (var index = history.size() - 1; index >= 0; index--) {
var previous = history.get(index);
var tempRejectApprove = previous.getWorkItem().getMetaDataMap().get('rejectApprove');
if ((tempRejectApprove != '')&&(tempRejectApprove != null)) {
rejectApprove = tempRejectApprove;
break;
}
}
// steps up from the workflow step into the workflow metaData,
// and stores the rejectApprove property there
// (where it can be accessed by an OR Split)
workItem.getWorkflowData().getMetaData().put('rejectApprove', rejectApprove);
Then after the Process step, the OR Split has the following in its tabs:
function check() {
var match = 'approve';
if (workflowData.getMetaData().get('rejectApprove') == match) {
return true;
} else {
return false;
}
}
Note: use this for the tab for the "approve" path, then copy it and replace var match = 'approve' with var match = 'reject'
So the key here is that from a Process step:
workItem.getWorkflowData().getMetaData().put('rejectApprove', rejectApprove);
writes to the same property that:
workflowData.getMetaData().get('rejectApprove') reads from when you execute it in an OR Split.
To suit our business requirements, there's more to the workflow I've implemented than just this, but the method above seems to be a pretty reliable way to get values that are entered in a dialog, and access them from within an OR Split.
It seems pretty silly that the OR Split can't access the workItem directly, and I'd be interested to know if there's a less roundabout way of doing this, but for now this has solved my problem.
I really hope someone else has this same problem, and finds this useful, because it took me waaay to long to figure out, to only apply it once!

Can I add a button in eclipse which performs custom a list of Actions in order?

This may not be possible but I'm looking for a way to add a button (or option in right click menu of project) that allows me to perform what would normally be multiple separate actions , specifically I would like an option that would:
perform a Maven clean on the current project
clean the project in eclipse
clean the server and rebuild (normally or Debug)
I have tried to Google this but I couldn't find anything that might help (I may not of phrased it correctly though as I am not sure what to search for)
All of the actions you listed can be done by separate builders. So you can create a launch config to run the Maven clean action, another launch config to run the Eclipse clean command and so on.
When you have all of those launch configs available, install the CDT launch group feature to run them together with one click: https://stackoverflow.com/a/11905444/44089
There have been a number of scripting attempts with eclipse, but not many of them are successful. You can always write your own command and handler, and from there you can execute any number of commands that you can specify:
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil
.getActiveWorkbenchWindowChecked(event);
IHandlerService handlerService = (IHandlerService) window
.getService(IHandlerService.class);
try {
handlerService.executeCommand(
IWorkbenchCommandConstants.HELP_ABOUT, null);
handlerService.executeCommand(
IWorkbenchCommandConstants.FILE_REFRESH, null);
} catch (NotDefinedException | NotEnabledException
| NotHandledException e) {
throw new ExecutionException("Failed", e);
}
return null;
}
Then you just need to track down command IDs that correspond to what you want to do. ALT+SHIFT+F2 and then selecting a menu item can provide the command ID (or action definition ID, which is the same thing).