How to implement/setup BPMN2 diagram with two successive exclusive gateways - java

I have a BPMN2 diagram with two successive exclusive gateways. In my first gateway, I have two expression condition types for the yes and no lines:
${enoughDrinks}
${notenoughDrinks}
Following this exclusive gateway, I have a second exclusive gateway with the same yes and no lines and an additional third line "other option". My problem is: how do I have to set this up? When I run the process and get to the no line of the "Enough drinks" gateway, I get an error for the boolean expression condition of the second gateway:
Unknown property used in expression: ${otherOption}. Cause: Cannot resolve identifier 'otherOption'
I have declared the variable in the execute method of my class that implements the JavaDelegate class:
public void execute(DelegateExecution execution) throws Exception {
boolean otherOption = (Boolean)execution.getVariable("otherOption");
execution.setVariable("otherOption", otherOption);
}
Below is the BPMN diagram and the red arrow points to the problematic line.
Maybe the general question is: if it is even possible to have to successive exclusive gateways without a user task inbetween?

Since you do not seem to have any service tasks defined the in your process: where is the delegate executed?
Try to add it as a "start" listener to the 2nd gateway

Related

Why am I getting "Error processing transaction request: intrinsic gas too low" error when trying to add tUSDT to a particular account?

I am trying to send test USDT to a particular account in Java using the following code:
final Web3j web3 = createWeb3If(ethNetworkUrl);
final Credentials credentials = Credentials.create(privateKey);
final ERC20 usdtContract = ERC20.load(usdtContractAddress, web3, credentials, new TestGasProvider());
usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send();
The last statement results in the following exception:
java.lang.RuntimeException: Error processing transaction request: intrinsic gas too low
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
TestGasProvider is defined as:
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(10L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
usdtContract was deployed using this script, which calls deploy.js:
async function main() {
const USDT = await ethers.getContractFactory("USDT");
const usdt = await USDT.deploy(1000000000000000);
console.log("USDT contract deployed to:", usdt.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
This contract is running on a local testnet set up as described here.
What do I need to change in any of these components (testnet, contract, deploy scripts, Java code) in order to send any amount of USDT to a particular address (without any errors)?
Update 1: If I change TestGasProvider to
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1000000000L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
I get another error:
java.lang.RuntimeException: Error processing transaction request: exceeds block gas limit
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
Update 1
I am looking to submit a set of code changes to the branch i16 of the minimal-crypto-exchange project which passes the following test:
Step 1
Set up the environment as described here.
Step 2
Set a breakpoint on line usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send(); in TransferUsdtToExchangeAccount class:
Step 3
Start the process engine application in debug mode. Its Java main method is located here.
Wait until you see the message starting to acquire jobs in the console output:
11:59:16.031 [JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor]] INFO org.camunda.bpm.engine.jobexecutor - ENGINE-14018 JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor] starting to acquire jobs
Step 4
Login with the credentials demo/demo at http://localhost:8080.
After login you should see a page like this:
Step 5
Click on the tasklist link. You should see a page that looks like this:
Press the "Start process" link. Following screen will appear:
Click on Send USDT to the exchange account process link. Following dialog box will appear:
Enter an arbitrary value into the "business key" field and press the "Start" button.
Step 6
After a couple of seconds, the breakpoint from step 2 will activate.
The problem will be solved if usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send() is executed without errors.
Notes
You are allowed to modify the amount in usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send(); from 10 to something else.
You can also modify the parameters of the Ethereum testnet specified in docker-compose.yml and genesis.json, as well as those of the USDT smart contract which is deployed using this script.
Your solution must work in this controlled environment (i. e. no faucets must be used).
Update 2
I made following changes:
The set-up tutorial now contains step 7 in which ETH is added to the exchange account.
Now a new version of the ETH testnet is being used, major changes being that log output is more verbose and the gas price is set to 1 (see --miner.gasprice 1 in entrypoint.sh).
Modified the code in TransferUsdtToExchangeAccount so that now USDT is transferred not from the exchange account (which has zero balance), but from the buffer account.
Now I am receiving the error
org.web3j.protocol.exceptions.TransactionException: Transaction 0x4bce379a2673c4564b2eb6080607b00d1a8ac232fbddf903f353f4eeda566cae
has failed with status: 0x0. Gas used: 32767.
Revert reason: 'ERC20: transfer amount exceeds allowance'.
My skills with Ethereum are still not sharp enough to give you a proper answer, but I hope you get some guidance.
The error states that you are trying to transfer by a party A certain quantity in the name of another party B, to a third one C, but the amount you are trying to transfer, using transferFrom, is greater than the one party B approved party A to send.
You can check the actual allowance between to parties using the method with the same name of your contract.
Please, consider review this integration test from the web3j library in Github. It is different than yours but I think it could be helpful.
Especially, it states that the actual transferFrom operation should be performed by the beneficiary of the allowance. Please, see the relevant code:
final String aliceAddress = ALICE.getAddress();
final String bobAddress = BOB.getAddress();
ContractGasProvider contractGasProvider = new DefaultGasProvider();
HumanStandardToken contract =
HumanStandardToken.deploy(
web3j,
ALICE,
contractGasProvider,
aliceQty,
"web3j tokens",
BigInteger.valueOf(18),
"w3j$")
.send();
//...
// set an allowance
assertEquals(contract.allowance(aliceAddress, bobAddress).send(), (BigInteger.ZERO));
transferQuantity = BigInteger.valueOf(50);
TransactionReceipt approveReceipt =
contract.approve(BOB.getAddress(), transferQuantity).send();
HumanStandardToken.ApprovalEventResponse approvalEventValues =
contract.getApprovalEvents(approveReceipt).get(0);
assertEquals(approvalEventValues._owner, (aliceAddress));
assertEquals(approvalEventValues._spender, (bobAddress));
assertEquals(approvalEventValues._value, (transferQuantity));
assertEquals(contract.allowance(aliceAddress, bobAddress).send(), (transferQuantity));
// perform a transfer as Bob
transferQuantity = BigInteger.valueOf(25);
// Bob requires his own contract instance
HumanStandardToken bobsContract =
HumanStandardToken.load(
contract.getContractAddress(), web3j, BOB, STATIC_GAS_PROVIDER);
TransactionReceipt bobTransferReceipt =
bobsContract.transferFrom(aliceAddress, bobAddress, transferQuantity).send();
HumanStandardToken.TransferEventResponse bobTransferEventValues =
contract.getTransferEvents(bobTransferReceipt).get(0);
assertEquals(bobTransferEventValues._from, (aliceAddress));
assertEquals(bobTransferEventValues._to, (bobAddress));
assertEquals(bobTransferEventValues._value, (transferQuantity));
//...
This fact is also indicated in this OpenZeppelin forum post.

How to execute a void method automatically when a breakpoint is hit?

I'm using latest IntelliJ IDEA Ultimate 16 EAP. I have some code in a library that initializes an object with some setters:
X createSomething() {
X x = new X();
x.setY(z);
return x; // breakpoint on this line
}
I'm looking to modify this returned value's state from the debugger: calling x.setY(y). I tried with conditions, because I want it to happen on every hit of the breakpointstopping at the breakpoint and using the "Evaluate Expression" window is unfeasible.
It's not possible to do this in any of the normal object oriented ways (e.g. overriding that method), nor it is possible to capture the result outside the method and modify it there because it's deep within many calls.
Here are my tries that all failed due to no support for those language features in the debugger. They failed with a dialog asking "Would you like to stop at the breakpoint?". The language level is fixed at Java 6-7 because I'm developing for Android.
Try 1: Call the method
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition 'x.setY(y)'
Reason: Boolean value expected
Also tried variants like: x.setY(y); false;, but it needs to be an expression.
Try 2: Call the method using lambda
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition '() -> { x.setY(y); return false; }'
Reason: Lambdas evaluation is not supported
Try 3: Call the method to have a boolean expression
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition 'new java.util.concurrent.Callable<Boolean>() { #Override public Boolean call() { x.setY(y); return false; } }.call()'
Reason: Anonymous class evaluation is not supported
Try 4: Call a static method (working workaround)
I found a workaround that I want to share, but I'm still looking for a better solution if anyone knows one: that doesn't require recompiling and restarting.
Create a method in a class:
public class SomeClass {
public static boolean fixX(X x) {
x.setY(y);
return false; // don't actually stop on the breakpoint
}
}
In the breakpoint condition add
full.pkg.SomeClass.fixX(x)
This works, but any time you want to modify the condition you'll have to restart the app. Parametrized fixX(x, changeAbleY) is a solution to that.
Make sure to disable or remove the breakpoint to prevent headaches by modified behavior when debugging unrelated issues.
Steps:
Right click on the breakpoint
A tool popup will open, in that popup click on "More" link at the bottom then a window will open.
Now check "Log evaluated expression" checkbox in that window and enter your method call in the given text box e.g methodName().
Click OK and start debugging.
When the breakpoint will hit your method will get called before that line's execution.
Reference: https://www.jetbrains.com/idea/help/configuring-breakpoints.html
Screenshot: Screenshot of breakpoint configuration window.
IntelliJ has a feature to add "Watches" where you can execute your void method but that's manual, not automatic.

JMeter go back to previous sampler

I am quite new to jmeter, I am using it to load test an application. My current setup is good if running few threads at a time but gets problems when more users get connected.
Here's the scenario,
sample_1: request table data
sample_2: set table row with empty user column as used by current user
|
'-->post_process_beanshell: check if have error message
sample_3: do other stuff
Currently I am able to check if the 2nd sample has an error message, the question is how do I tell beanshell to go back to 1st sample when the 2nd sample has an error message?
I would recommend put your "sample_3" under If Controller like:
Loop Controller (define maximum number of n-tries)
sample_1
sample_2
post_process_beanshell
If Controller: condition ${JMeterThread.last_sample_ok}
sample_3
JMeterThread.last_sample_ok - is a pre-defined variable which returns "true" if previous sampler was successful and "false" if not so if your "sample_2" will fail - "sample_3" won't be executed and the whole sequence will start over
Assuming you want to keep going back to sampler1 until sampler2 beanshell returns true, use a While controller.
Stick both sampler1 and sampler2 in a while controller which is conditional on the result of your error check.

Akka: Stop actor after child actors are finished

I often find myself using a "main" actor that creates a number of child actors for sub-tasks. When the sub-tasks are finished, the main actor should also stop himself. So I watch the child actors and stop the main actor when context.children.isEmpty.
I often use this pattern, but as I never read about this. I am unsure, if this is a good idea or if there are problems with failing actors...?
I have read about Shutdown Patterns in Akka 2, but this approach seems to be more complicated in Java than my solution?
Here is my pseudo code for a main actor with two subtasks:
class MainActor extends AbstractActor {
public MainActor() {
receive(ReceiveBuilder
.match(SubTask1Response.class, this::handleSubTask1)
.match(SubTask2Response.class, this::handleSubTask2)
.match(Terminated.class, x -> checkFinished())
.build());
}
#Override
public void preStart() throws Exception {
context().watch(context().actorOf(SubTask1Worker.props(), "subTask1"));
context().watch(context().actorOf(SubTask2Worker.props(), "subTask2"));
}
private void checkFinished() {
if(context().children().isEmpty()) {
context().stop(self());
}
}
// ...
}
(I must use Java 8 :-(, but I am also happy to read Scala code if you can provide me another solution)
So context().children().isEmpty() seems to work as expected.
But while debugging my Akka application I found another problem with this approach: It is not deterministic when the Terminated message arrives in the MainActor: Sometimes there is the Terminated message before the SubTask1Response from the example!
I have changed now my code to count the running children myself and decrement the number whenever the MainActor receives a result response SubTask[1,2]Response.
=> So I wouldn't recommend my original pattern.

Jbpm6 . Asynchronous workitem and retry

Let me come directly to use case.
I am having a number of work-items in my process say A,B,C. It starts in A--->B--->C order.
In my case, B is a call to a 3rd party web service. C should process only if B is success. if the call to the web-service fails, system should retry after 5 min. The number of retries are limited to 3.
How can I achieve this using Jbpm6.?
Some options that I understand from doc are,
1) I can use a work item handler. Inside work item, I will start another thread which will do the retries and finally it calls the completeWrokItem() method. But in this case my process engine thread will wait unnecessarily for the completeWrokItem() call.
2)I can use command for retry . But if I call command it will execute in another thread and the process thread will execute C. Which is not a desirable way
How can I create a process so that, B will execute in back-end and will notify the engine that it can continue executing C?
Please advice.
Thanks in advance.
Please comment if my question is not clear enough to answer.
Your question is not completely clear; however, I provide an answer to hopefully provide some clarity:
For asynchronous execution, you should follow guidelines in documentation: JBMP 6.0 Async Documentation
Given your processes flow, if you use a Command and a process defined as: A->B->C; C will not start until the command completes.
To have commands run in parallel, you use parallel branches. In below pic, if Script1 and Script2 were commands they would execute in parallel, and Email would only execute once both Scripts complete:
A command signals complete by simply returning from execute method:
public ExecutionResults execute(CommandContext ctx) throws Exception {
// Set results if exist. Otherwise, return empty ExecutionResults.
ExecutionResults results = new ExecutionResults();
// This would match the name of an output parameter for the work item.
// results.setData("result", "result data");
logger.info("Command finished execution: " + this.getClass());
logger.debug("Results of executing command: ", results);
return results;
}
`
Add a XOR gateway after the node B, Add script to of the node B and set the status and retry_count of web-service(if success, status_b = true; if failed, status_b = false and retry_count ++),
XOR go to C if the retry_count>=3 or status_b == true
else go to B again

Categories

Resources