i am defining a Workflow using WSO2 BPMN which will be integrated with our Application. When Instantiating a Process (from our application), i need to pass few information from our application to a BPMN Task which will be displayed in the Task screen.That information will be persisted in all the Task of the Workflow. How can i achieve this?
Yes, you can do that by introducing form variables for each task (user tasks). But if it is a service task you should have to write a custom java class to read the variables and then add it to the class name field in Main config tab as a property in activiti designer. A sample custom java class to read process variables through service task can be implemented as below. As you can see in the below code, employeeSalary and workingPeriod are the two variables which can be passed from a particular process (from your application). And you can set these variables to the task variables by invoking execution.setVariable("variableName", value) method.
package org.wso2.bps.serviceTask;
import java.util.Random;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
/**
* Service task to calculate Bonus for employees
*
*/
public class App implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
int salary = Integer.parseInt((String) execution.getVariable("employeeSalary"));
int numOfWorkingDays = Integer.parseInt((String) execution.getVariable("workingPeriod"));
Random randomGenerator = new Random();
int value = randomGenerator.nextInt(10);
int result = salary + (numOfWorkingDays * value);
execution.setVariable("result", result);
}
}
Hope this resolves your issue.
Related
Using WSO2 BPS 3.6.0 - is there a (standard) way to update an instance variable in an already running instance?
The reason behind is - the client passes incorrect data at the process initialization, the client may fix its data, but the process instance remembers the wrong values.
I believe I may still update a data in the database, but I wouldn't like to see process admins messing with the database
Edit:
I am working with the BPEL engine and my idea is to update a variable not from a process design, but as a corrective action (admin console? api?)
Thank you for all ideas.
You are setting the instance variables during process initialization based on client's request.
For your requirement, where the variables need to be retrieved for the request. You can do this by using the execution entity to read the data instead of the instance variables that were set during process initialization.
Refer example below :
public class SampleTask implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
String userId = execution.getVariable("userId");
//perform your logic here
}
}
If you want to keep using the instance variables, I suggest you to change the instance variable during the process execution.
public class SampleTask implements JavaDelegate {
private String userId;
public void execute(DelegateExecution execution) throws Exception {
String newUserId = execution.getVariable("userId");
setUserId(newUserId);
//perform your logic here
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
}
With the new release of Azure Webjobs 3.0.0 SDK it was announced the:
http://azure.microsoft.com/blog/2014/06/18/announcing-the-0-3-0-beta-preview-of-microsoft-azure-webjobs-sdk/
Improved function discovery
We added an ITypeLocator and INameResolver to enable customizing how the WebJobs SDK looks >for functions. This enables scenarios such as the following:
You can define functions where the QueueName is not explicit. You can read Queue names from a config source and specify this value at runtime.
Restrict function discovery to a particular class or assembly.
Dynamic functions at indexing time: you can define the function signature at runtime.
But there's no sample code on how to do it.
Does anyone know how to define the queue name at runtime (e.g. from app.config)?
If you take advantage of the new INameResolver in the configuration you can make your own implementation of the interface and replace it in the JobHostConfiguration. Take a look at this blog post where I made a small POC on the topic.
To use an external runtime service to define the name of the queue:
public class QueueNameResolver : INameResolver
{
public string Resolve(string practiceId)
{
//define in appsettings the queuename property
return CloudConfigurationManager.GetSetting("queuname");
//or some other service of your design
}
}
In the WebJob Code, Program.cs:
public void init()
{
// Retrieve storage account from connection string.
string azureJobStorageConnectionString = ConfigurationManager.ConnectionStrings["AzureWebJobsStorage"].ConnectionString;
var config =
new JobHostConfiguration(azureJobStorageConnectionString)
{
NameResolver = new QueueNameResolver()
};
host = new JobHost(config);
host.RunAndBlock();
}
as per azure doco
I am developing an Azure WebJobs executable that I would like to use with multiple Azure websites. Each web site would need its own Azure Storage queue.
The problem I see is that the ProcessQueueMessage requires the queue name to be defined statically as an attribute of the first parameter inputText. I would rather have the queue name be a configuration property of the running Azure Website instance, and have the job executable read that at runtime when it starts up.
Is there any way to do this?
This can now be done. Simply create an INameResolver to allow you to resolve any string surrounded in % (percent) signs. For example, if this is your function with a queue name specified:
public static void WriteLog([QueueTrigger("%logqueue%")] string logMessage)
{
Console.WriteLine(logMessage);
}
Notice how there are % (percent) signs around the string logqueue. This means the job system will try to resolve the name using an INameResolver which you can create and then register with your job.
Here is an example of a resolver that will just take the string specified in the percent signs and look it up in your AppSettings in the config file:
public class QueueNameResolver : INameResolver
{
public string Resolve(string name)
{
return ConfigurationManager.AppSettings[name].ToString();
}
}
And then in your Program.cs file, you just need to wire this up:
var host = new JobHost(new JobHostConfiguration
{
NameResolver = new QueueNameResolver()
});
host.RunAndBlock();
This is probably an old question, but in case anyone else stumbles across this post. This is now supported by passing a JobHostConfiguration object into the JobHost constructor.
http://azure.microsoft.com/en-gb/documentation/articles/websites-dotnet-webjobs-sdk-storage-queues-how-to/#config
A slight better implementation of name resolver to avoid fetching from configuration all time. It uses a Dictionary to store the config values once retrieved.
using Microsoft.Azure.WebJobs;
using System.Collections.Generic;
using System.Configuration;
public class QueueNameResolver : INameResolver
{
private static Dictionary<string, string> keys = new Dictionary<string, string>();
public string Resolve(string name)
{
if (!keys.ContainsKey(name))
{
keys.Add(name, ConfigurationManager.AppSettings[name].ToString());
}
return keys[name];
}
}
Unfortunately, that is not possible. You can use the IBinder interface to bind dynamically to a queue but you will not have the triggering mechanism for it.
Basically, the input queue name has to be hardcoded if you want triggers. For output, you can use the previously mentioned interface.
Here is a sample for IBinder. The sample binds a blob dynamically but you can do something very similar for queues.
I am trying to use a web service as part of a dataflow task in SSIS. Right now i have a script task within a data flow with a web service reference.
What the task has to ultimately do is: collect all postal codes from an inernal database > use the web service i created to get the lay/long of thos postal codes > export the lat/long to a table.
As i said before i have the scrip set up and looks to be working, but when i go to execute the package i get an CannotCreateUserComponentException error.
Any help on this would be awesome, or another approach to it? I am new to the web services in SSIS so this is the best solution i could come up with.
Edit:
Right now the script is accepting the postal code from an OLE DB Source and will ouput a string in for format of "lat,long" (presumably). The web Service was created by someone within the company and has one method called FindCoordinates which takes in a string value (Postal code)(which i think calls the google geocode xml, not exactly sure what he did). Here is the code that is currently in my script:
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using SC_6c1b642acd544cd5b01c032b6f8dfd03.csproj.MyService;
using System.Xml;
using System.Web.Services;
[WebService(Namespace = "http://microsoft.com/webservices/")]
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
/*
Add your code here for preprocessing or remove if not needed
*/
}
public override void PostExecute()
{
base.PostExecute();
/*
Add your code here for postprocessing or remove if not needed
You can set read/write variables here, for example:
Variables.MyIntVar = 100
*/
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
String postal = Row.PostalCode;
Service service = new Service();
Row.LatLong = service.FindCoordinates(postal);
}
}
Hope this help.
Goal:
Retrieve data from Dynamics CRM 2011 to my database from SQL server R2 by using webservice through integration services (SSIS). Webservice needed to be located inside of SSIS. Gonna use the data for data warehouse.
Problem:
How do I do it?
We only write to Dynamics so I can't address the specific method name but the general idea below should get you started.
Assumptions
Two variables have been defined in your package and they are passed to the script component as ReadOnlyVariables: CrmOrganizationName, CrmWebServiceUrl.
A script component has been added to the dataflow as a Source component. On the Inputs and Outputs tab, an appropriate number of columns have been added to Output 0 (or whatever you define your output collection as) with appropriate data types.
Inside the script, add a web reference to your CRM instance. This code assumes it's called CrmSdk.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
// web reference
using CrmSdk;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void CreateNewOutputRows()
{
// Get a reference to the CRM SDK
CrmSdk.CrmService CrmService = new CrmSdk.CrmService();
// An Authentication Token is required because CRM requires an OrganizationName
// to identify the Organization to be used
CrmSdk.CrmAuthenticationToken token = new CrmSdk.CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = this.Variables.CrmOrganizationName;
CrmService.CrmAuthenticationTokenValue = token;
// Use default credentials
CrmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Get the web service url from the config file
CrmService.Url = this.Variables.CrmWebServiceUrl;
//////////////////////////////////////////////////
// This code is approximate
// Use the appropriate service call to get retrieve
// data and then enumerate through it. For each
// row encountered, call the AddRow() method for
// your buffer and then populate fields. Be wary
// of NULLs
//////////////////////////////////////////////////
foreach (CrmSdk.entity person in CrmService.Get())
{
Output0Buffer.AddRow();
Output0Buffer.FirstName = person.FirstName;
Output0Buffer.LastName = person.LastName;
}
}
}
Caveats
There is no error handling, checks for nulls or anything elegant. The service should probably have been defined with the using statement, etc, etc, etc. It should provide an appropriate starting point for understanding how to consume a web service and load data into the pipeline.
The easiest solution for your requirement is to use a third-party library for SSIS. The commercial COZYROC SSIS+ library includes Dynamics CRM adapters, which support all deployment models: Premise, Live, Hosted, Federation, Office 365.