I am using drools 5.6. In camel-server.xml I have my route defined as:
<route>
<from uri="cxfrs://bean://rsServer"/>
<policy ref="droolsPolicy">
<unmarshal ref="xstream-json" />
<to uri="drools:node1" />
<marshal ref="xstream-json" />
</policy>
</route>
I am not defining a ksession. Then in my knowledge-service.xml I have 2 sessions defined (by user) that point to different DRL files. These import the same common DRL file
<drools:kbase id="kbase1" node="node1">
<drools:resources>
<drools:resource ref="ruletemplate" />
<drools:resource type="DRL" source="classpath:7.drl"/>
</drools:resources>
</drools:kbase>
<drools:ksession id="ksession-7" type="stateless" kbase="kbase1" node="node1"/>
<drools:kbase id="kbase2" node="node1">
<drools:resources>
<drools:resource ref="ruletemplate" />
<drools:resource type="DRL" source="classpath:12.drl"/>
</drools:resources>
</drools:kbase>
<drools:ksession id="ksession-12" type="stateless" kbase="kbase2" node="node1"/>
The idea is the ksession will be defined in the JSON request passed in:
{"batch-execution": { "lookup":"ksession-12", "commands": [ { "insert": { "out-identifier": ...
The server starts up and changing the lookup between 7 and 12 works. HOWEVER whatever lookup I run first is the only rule that actually fires. So if I start the server and run ksession-7 it will run successfully, then change to ksession-12 nothing happens (does not hit debugging in 12.drl)
If I then restart the server and run 12 first it will run successfully, then change to ksession-7 and nothing happens
I am confused by this and believe I am missing something. My goal is to have a common rule template with specific rules for each user. Can anyone help guide me why this is not being directed correctly (or not processing)
EDIT: Adding example
t1.drl:
package org.company.t1.rules
import org.test.*
rule "check patients age" dialect "mvel"
when
$p : Patient( age >= 10)
then
System.out.println("t1 - age greater then 10")
$ca = new Message("age greater then 10")
$p.alerts.add($ca)
end
t2.drl:
package org.company.t2.rules
import org.test.*
rule "check patients age" dialect "mvel"
when
$p : Patient( age >= 15)
then
System.out.println("t2 - age greater then 15")
$ca = new Message("age greater then 15")
$p.alerts.add($ca)
end
ruletemplate.drl:
package org.test
declare Message
text : String
end
declare Patient
id:String
age : Integer
alerts : java.util.ArrayList
end
rule "setup rule for alerts" dialect "mvel" salience 100
when
$p : Patient()
then
System.out.println("initialize array")
$p.alerts = new java.util.ArrayList();
end
knowledge-server.xml:
<drools:resource id="ruletemplate" type="DRL" source="classpath:ruletemplate.drl" />
<drools:kbase id="kbase5" node="node1">
<drools:resources>
<drools:resource ref="ruletemplate" />
<drools:resource type="DRL" source="classpath:t1.drl"/>
</drools:resources>
</drools:kbase>
<drools:kbase id="kbase6" node="node1">
<drools:resources>
<drools:resource ref="ruletemplate" />
<drools:resource type="DRL" source="classpath:t2.drl"/>
</drools:resources>
</drools:kbase>
<drools:ksession id="ksession5" type="stateless" kbase="kbase5" node="node1"/>
<drools:ksession id="ksession6" type="stateless" kbase="kbase6" node="node1"/>
First request that works:
{"batch-execution": { "lookup":"ksession5", "commands": [ { "insert": { "out-identifier": "patient", "object": { "org.test.Patient":[{"age":16}]}}},{"fire-all-rules": ""}]}}
{"execution-results":{"results":{"result":{"identifier":"patient","value":{"org.test.Patient":{"age":16,"alerts":{"org.test.Message":{"text":"age greater then 10"}}}}},"fact-handle":{"identifier":"patient","external-form":"0:2:537549803:537549803:2:DEFAULT"}}}}
Request 2: (doesnt work unless run first after server restart:
{"batch-execution": { "lookup":"ksession6", "commands": [ { "insert": { "out-identifier": "patient", "object": { "org.test.Patient":[{"age":16}]}}},{"fire-all-rules": ""}]}}
{"execution-results":{"results":{"result":{"identifier":"patient","value":{"org.test.Patient":{"age":16}}},"fact-handle":{"identifier":"patient","external-form":"0:2:552327108:552327108:2:DEFAULT"}}}}
Tailing catalina.out shows the debugger output for t1 as it was run first, but nothing on t2
What are you inserting? what kind of rules do you have in there?
Could be that the first run everything works well and the second is crashing in the back?
Related
here is my Junit test result.xml
I am able to get hold of testsuite and testcase nodes. Now I need to check if test case is failed.
I am using an approach where I check if testcase node has any child and then check if that child is failure node. But when I try to get hold of child node and its type, it returns only the TEXT_NODE and displays failure message text. How do I check if child node is failure?
<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="com.Test" tests="47" failures="1" errors="0" skipped="0" time="0.425" timestamp="2017-05-25T10:04:14" hostname="localhost">
<properties>
<property name="device" value="Nexus_6_API_22(AVD) - 5.1.1" />
<property name="flavor" value="DEV" />
<property name="project" value="test" />
</properties>
<testcase name="test_1" classname="com.Test" time="0.053" />
<testcase name="test_2" classname="com.Test" time="0.081" />
<testcase name="test_3" classname="com.Test" time="0.0" />
<testcase name="test_4" classname="com.Test" time="0.001">
<failure>junit.framework.ComparisonFailure: expected:<512[]> but was:<512[fed_]>
at junit.framework.Assert.assertEquals(Assert.java:85)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1853)
</failure>
</testcase>
</testsuite>
Well, I figured this out as below, posting for the benefit of others -
//Get a list of test cases with below code -
testCaseList = docElement.getElementsByTagName(TEST_CASE_TAG);
//Iterate through the list and set each item to testElement
// Get Test Case status
TestStatus testCaseStatus = TestStatus.FAILED;
if(testElement.hasChildNodes()) {
//Check if test failed ?
elems = getDirectChildsByTagName(testElement, TEST_FAILURE_TAG);
if(elems != null && elems.size()>0) {
logger.info("failed Tests :"+elems.size());
testCaseStatus = TtuTestStatus.FAILED;
}
//Check if test skipped ?
else {
elems = getDirectChildsByTagName(testElement, TEST_SKIPPED_TAG);
if(elems != null && elems.size()>0) {
logger.info("Skipped Tests :"+elems.size());
testCaseStatus = TtuTestStatus.SKIPPED;
}
}
}
else {
testCaseStatus = TtuTestStatus.PASSED;
}
i spent a few hours trying to code this by myself, but i don't know much about editing the web.config and all the examples i found don't come close to what i need. CHANGE#1 is unique because it does include the typical key=value.
I want to be able to script (PowerShell) the required modifications of Web.Config, only if the values do not already exist.
CHANGE#1:
Onsert this
(if not already there and "true"): multipleSiteBindingsEnabled="true"
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
CHANGE#2:
Insert this if not already there:
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="SSL"
contract="Microsoft.UpdateServices.Internal.IClientWebService" />
<endpoint address="secured"
binding="basicHttpBinding"
bindingConfiguration="SSL"
contract="Microsoft.UpdateServices.Internal.IClientWebService" />
It goes between here:
<services>
<service
name="Microsoft.UpdateServices.Internal.Client"
behaviorConfiguration="ClientWebServiceBehaviour">
<!-- ... CODE FROM CHANGE#2 GOES HERE ... -->
</service>
</services>
This is the code so far for change#1 (not working):
$sWSUSwebConfig = "C:\Program Files\Update Services\WebServices\ClientWebService\Web.Config"
$xFileContent = [Xml](Get-Content $sWSUSwebConfig)
$root = $xFileContent.get_DocumentElement()
foreach ($item in $root."system.serviceModel"."serviceHostingEnvironment") {
if ($item."multipleSiteBindingsEnabled" -ine "true") {
$activeConnection = $root.serviceHostingEnvironment
$activeConnection.SetAttribute("multipleSiteBindingsEnabled", "true")
#$item.add."multipleSiteBindingsEnabled" = "true"
$iKeyFound = $true
}
}
$xFileContent.Save("c:\temp\web.config")
Reference for modifications: step 3 from kb3159706.
I am new to this Quartz.NET thing and I have some questions about it cause it don't seem to work as I want to.
Question 1: I am defining simple IJobDetail and ITrigger. [SOLVED]
NameValueCollection config = ConfigurationManager.GetSection("quartz") as NameValueCollection;
ISchedulerFactory schedFact = new StdSchedulerFactory(config);
IScheduler scheduler = schedFact.GetScheduler();
try
{
scheduler.Start();
IJobDetail job = JobBuilder.Create<HelloJobTestScheduling>()
.WithIdentity("job1", "group1")
.Build();
DateTimeOffset endDate = DateTime.Now.AddMinutes(5);
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.WithRepeatCount(2))
.EndAt(endDate)
.Build();
scheduler.ScheduleJob(job, trigger);
}
catch(SchedulerException se)
{
Console.WriteLine(se);
}
finally
{
scheduler.Shutdown();
}
HelloJobTestScheduling
public void Execute(IJobExecutionContext context)
{
JobKey key = context.JobDetail.Key;
JobDataMap dataMap = context.JobDetail.JobDataMap;
string connectionString = #"Data Source=localhost\dejan;Initial Catalog=QuartzTest;Integrated Security=True";
string query = "INSERT INTO test (id, datetime) " +
"VALUES (#id, #datetime) ";
// create connection and command
using (SqlConnection cn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(query, cn))
{
// define parameters and their values
cmd.Parameters.Add("#id", SqlDbType.Int).Value = "1";
cmd.Parameters.Add("#datetime", SqlDbType.DateTime).Value = DateTime.Now;
// open connection, execute INSERT, close connection
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
}
App.config
<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<quartz>
<add key="quartz.scheduler.instanceName" value="MyScheduler" />
<add key="quartz.scheduler.instanceId" value="AUTO" />
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
<add key="quartz.threadPool.threadCount" value="30"/>
<add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
<add key="quartz.jobStore.dataSource" value="default" />
<add key="quartz.dataSource.default.connectionString" value="Data Source=localhost\dejan;Initial Catalog=QuartzTest;Integrated Security=True" />
<add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
<add key="quartz.jobStore.clustered" value="false" />
<!--<add key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz" />-->
<add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz" />
<add key="quartz.dataSource.default.provider" value="SqlServer-20" />
<add key="quartz.jobStore.useProperties" value="false" />
</quartz>
What this job actually does in reality is this: inserting only one row in the database, and after that it won't do anything. It waits to the .endAt and shows in console that the scheduler is closed. What is wrong with my code?
Note: I have all the required database tables for the scheduler to work in the background.
Question 2: Why this CRON is not recognized?
.WithCronSchedule("0 1 0 ? * ?")
Visual Studio error says:
'?' can only be specified for Day-of-Month -OR- Day-of-Week.
Cron expressions in Quartz.Net are made up of 7 sub-expressions:
Seconds
Minutes
Hours
Day-of-Month
Month
Day-of-Week
Year (optional field)
The last one is optional.
Your cron expression is not valid.
If you want to run to execute something every minute the right one is: 0 0/1 * 1/1 * ? *
I would advice you to use this tool to generate your cron expressions.
It's easier.
Question 1 is solved. Just a short note, my mistake was that I close the scheduler too early in finally. If I comment that lane, everything works good.
But, I still need help about Question 2.
I have created a scenario by creating a myScenario.sdl in my local config folder /atg/registry/data/scenarios/myScenario.sdl
myScenario.sdl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE process SYSTEM "dynamosystemresource:/atg/dtds/pdl/pdl_1.0.dtd">
<process author="admin" creation-time="1413804041263" enabled="false" last-modified-by="admin" modification-time="1413804191188">
<segment migrate-subjects="true">
<segment-name>ItemAddedToOrder</segment-name>
<!--================================-->
<!--== Item added to order Quantity with fraction is defined -->
<!--================================-->
<event id="1">
<event-name>atg.commerce.order.ItemAddedToOrder</event-name>
<filter construct="event-property-filter" operator="isNotNull">
<event-property construct="event-property">
<property-name>quantityWithFraction</property-name>
</event-property>
</filter>
</event>
<!--================================-->
<!--== Log a message message: Quantity With Fraction is Defines logTriggeringEvent: true -->
<!--================================-->
<action id="2">
<action-name>Log a message</action-name>
<action-param name="message">
<constant>Quantity With Fraction is Defines</constant>
</action-param>
<action-param name="logTriggeringEvent">
<constant type="java.lang.Boolean">true</constant>
</action-param>
</action>
</segment>
</process>
And enabled the scenario:
Registry scenarioRegistry = scenarioManager.getScenarioRegistry();
byte[] data = (byte[]) scenarioRegistry.getItem(pScenarioPath);
String xml = null;
if (data != null) {
xml = new String(data, "UTF-8");
} else {
Assert.fail("No scenario is existed to enable/disable");
}
String updatedXml;
if (scenarioState && xml != null) {
updatedXml = xml.replaceAll("enabled=\"false\"", "enabled=\"true\"");
} else {
updatedXml = xml.replaceAll("enabled=\"true\"", "enabled=\"false\"");
}
scenarioRegistry.putItem(pScenarioPath, updatedXml.getBytes("UTF-8"));
Now with this above written code, I can both disable or enable the scenario by changing the state as false and true respectively. But I want to delete the scenario(please remember, my requirement is DELETE not DISABLE SCENARIO). I know using scenarioManager.updateScenario() deleted the scenario. Is my understanding right?
One more thing, I know I can delete the scenario directly from ACC. But I need to code via code not manually from ACC.
Please share your thoughts!
Did you try scenarioRegistry.removeItem(path);
I am calling a target by means of phingcall command.
I want to pass back a status variable from the called target or at least change the existing value from the calling target.
Goal: I want to branch in my main target controlling logic if the sub target fails which I indicate with a property.
The code below does not work. Any idea how to make it work or an altertive approach for my goal?
Thanks,
Juergen
<target name="main">
<echo>target a</echo>
<echo>${bOk}</echo>
<exec command="echo 1" outputProperty="bOk" />
<echo>bOk is 1: ${bOk}</echo>
<phingcall inheritRefs="true" target="sub">
</phingcall>
<echo>bOk should now be 0: ${bOk}</echo>
</target>
<target name="sub">
<echo>target b</echo>
<echo>bOk is 1: ${bOk}</echo>
<exec command="echo 0" outputProperty="bOk" />
<echo>bOk now is 0: ${bOk}</echo>
</target>
The problem here is that
<echo>bOk should now be 0: ${bOk}</echo>
echos
bOk should now be 0: 1
Even with the great help of #phing IRC I couldn't solve the problem.
I decided to write a custom task to account for data passing between targets:
<?php
require_once "phing/Task.php";
class rvGlobalTask extends Task {
private static $bOk = 1;
private $sMode = null;
private $bValue = null;
private $outputProperty = null;
public function setSMode( $sMode ) {
$this->sMode = $sMode;
}
public function setBValue( $bValue ) {
$this->bValue = $bValue;
}
public function setOutputProperty( $outputProperty ) {
$this->outputProperty = $outputProperty;
}
public function main() {
if ( $this->sMode == "set" ) {
rvGlobalTask::$bOk = $this->bValue;
} else {
$this->project->setProperty(
$this->outputProperty,
rvGlobalTask::$bOk
);
}
}
}
?>
This works fine for my problem. Perhaps someone else finds this useful as well.
Here's how you use an ExecTask to capture output.
<?xml version="1.0" encoding="UTF-8"?>
<project name="example" default="check-composer">
<!-- set a property to contain the output -->
<property name="whichComposer" value="" />
<!-- check if composer (getcomposer.org) is installed globally -->
<target name="check-composer">
<!-- put the output of "which" in our property -->
<exec command="which composer" outputProperty="whichComposer" />
<!-- act on what we found out -->
<if>
<contains string="${whichComposer}" substring="composer" />
<then>
<echo>Composer installed at ${whichComposer}</echo>
</then>
<else>
<echo message="better install composer. ${whichComposer}"/>
</else>
</if>
</target>
</project>