Converting dates in drools workbench decision rule template - drools

Hi I have been trying with drools decision rule templates. I have tried converting between dates in drools decision template. The template is shown below.
The generated rule is shown below.
package com.myspace.sample;
import java.time.format.DateTimeFormatter;
rule "DataUnification_0"
dialect "mvel"
when
cus : Customer( )
data : Data( dateOfBirth != null )
DateTimeFormatter( )
then
modify( cus ) {
setDateOfBirth( data.dateOfBirth.format(DateTimeFormatter.ofPattern("dd-MMM-yy")) )
}
end
But when trying to validate error is thrown as below.
[KBase: defaultKieBase]: Unable to Analyse Expression #Modify with( cus ) { setDateOfBirth( data.dateOfBirth.format(DateTimeFormatter.ofPattern("dd-MMM-yy")) ) };: [Error: unable to resolve method using strict-mode: com.myspace.sample.Customer.setDateOfBirth(java.lang.String)] [Near : {... fy with( cus ) { setDateOfBirth( data.dateOfBir ....}] ^ [Line: 5, Column: 0]
The date formatter wasn't available in the initial list of objects. I added it to external objects in the projects. Is there anyway to solve this problem?

Related

Can't insert string to Delta Table using Update in Pyspark

I have encountered an issue were it will not allow me to insert a string using update and returns. I'm running 6.5 (includes Apache Spark 2.4.5, Scala 2.11), but it is not working on 6.4 runtime as well.
I have a delta table with the following columns, partitioned by the created date
ID string
, addressLineOne string
, addressLineTwo string
, addressLineThree string
, addressLineFour string
, matchName string
, createdDate
And I'm running a process that hits an API and updates the matchName column.
Using Pyspark if it do this, just to test writing
deltaTable.update(col("ID") == "ABC123", {"matchName ": "example text"})
I get the following error:
Py4JJavaError: An error occurred while calling o1285.update.
: org.apache.spark.sql.catalyst.analysis.UnresolvedException: Invalid call to dataType on unresolved object, tree: 'example
If I try this, change the string to 123, it updates without an issue
deltaTable.update(col("ID") == "ABC123", {"matchName ": "123"})
Yet if I use sql and do
UPDATE myTable SET matchName = "Some text" WHERE ID = "ABC123"
It inserts fine. I've searched and can't see a similar issue, Any suggestions? Have I missed something obvious?
Looks like you have an extra space after matchName in your python code

Adding rule condition based on two objects in drools

> { "batch-execution":{
> "lookup":"defaultKieSession",
> "commands":[
> {
> "insert":{
> "out-identifier":"FieldData1",
> "object":{
> "FieldData":{
> "name":"abc",
> "value":"111"
> }
> }
> }
> },
> {
> "insert":{
> "out-identifier":"FieldData2",
> "object":{
> "FieldData":{
> "name":"xyz",
> "value":"222"
> }
> }
> }
> },
> {
> "fire-all-rules":{
>
> }
> }
> ] } }
Now i want to write a condition in drl similar to this:
rule "testrule"
when
fieldData(name == "abc" , value == "111") && fieldData(name == "xyz",value = "222")
then
System.out.println("Condition executed")
Can someone help on how this can be done in drools ?
Of course you can! Your "example" rule is nearly perfect as-is.
The way drool works is that it evaluates the conditions of all of the objects in working memory, and only if all conditions are met will it trigger that rule.
So you could write a rule that looks like this:
rule "Test Rule"
when
exists( FieldData( name == "abc", value == "111") )
exists( FieldData( name == "xyz", value == "222") )
then
System.out.println("Condition Executed")
end
This rule will trigger if there exists an object in working memory that has a name of 'abc' and a value of '111', and there also exists an object in working memory with the name of 'xyz' and value of '222'.
In the example above, I used the 'exists' predicate because we weren't going to actually be doing anything with those values, and we just wanted to confirm that there is such a FieldData object in memory that matches the required conditions.
Note that this assumes that you've entered your FieldData objects directly into the working memory as standalone objects. (Eg you fired the rules and passed it a List of FieldData.) If you're working with bigger structures, you'll have to extract the FieldData objects, and then do an exists check like I had in my previous example.
For example, let's say you had a set of classes like this (which mimic your example JSON; getters and setters omitted for brevity):
class FieldData {
String name;
String value;
}
class Command {
String outIdentified;
FieldData object;
}
class BatchExecution {
String action; // eg "insert"
String lookup;
List<Command> commands;
}
If you passed a BatchExecution into the rules, you'll need to pull the field data out of the commands before you can check that two FieldData exist with the conditions you want. Your rule would therefore look more like this:
rule "Test Rule 2"
when
// Get the BatchExecution in working memory and pull out the Commands
BatchExecution( $commands: commands != null )
// Get the FieldData from each of the commands
$data: ArrayList( size >= 2) from
accumulate( Command( $fd: object != null ) from $commands,
init( ArrayList fieldDatas = new ArrayList() ),
action( fieldDatas.add( $fd ) ),
reverse( fieldDatas.remove( $fd ) ),
result( fieldDatas ))
// Confirm there exist FieldData with our criteria inside of the Commands
exists( FieldData( name == "abc", value == "111" ) from $data
exists( FieldData( name == "xyz", value == "222" ) from $data
then
System.out.println("Condition executed, 2");
end
Basically what we have to do is drill down from the object actually inserted into working memory until we can get to the objects that we need to be doing work against, in this case the FieldData. I used the accumulate aggregate to pull all of the FieldData into a List that we then check for the presence of the two FieldData that we're looking for in this particular rule.
For more information, you should consider reading the Drools documentation, specifically the part on the "Rule Language Reference" (section 4) which is very well written and contains plenty of examples that you can adapt or expand upon.
The rule firing in drools only happens on the occurrence of some event. Read about sessions and execution of rules here.
Coming to the your question of writing the above rule. I am not sure how you want the rule to be executed. As per my understanding if you want to write a separate rule each to check name as xyz and abc, then you can write the rule as below:
rule "testrule1"
when
fieldData(name == "abc" , value == "111")
then
System.out.println("Condition executed 1")
end
rule "testrule2"
when
fieldData(name == "xyz" , value == "222")
then
System.out.println("Condition executed2")
end
If you want to combine the rule then you can write it as:
rule "testrule"
when
fieldData(name == "abc" || name == "xyz" && value == "111" || value == "222")
then
System.out.println("Condition executed")
end
Note: You cannot define a rule like above if you want to work on the occurrence of multiple events. If you want to work on multiple events you can read about windowing in drools. Add more information on your use case to get better answers.

Sequelize update function expects all fields to be provided

Am using Sequlize 5.8.5 and trying to update a model but, it doesn't seem to be possible unless all fields are provided. For example performing Project.update(args) where args cloud sometimes has a name field with changed value and sometimes not even passed at all, if the name field doesn't need to be updated, am getting an error such as err: { SequelizeValidationError: notNull Violation: projects.name cannot be null ... }.
This method is possible in Sequelize. Here's a test I ran:
let u1 = {username : 'Test User', title_id: 4};
let u2 = {title_id: 4};
User.update(u1, {where : {id : 3}});
User.update(u2, {where : {id : 5}});
Here is the generated SQL:
Executing (default): UPDATE `muser` SET `username`='Test User',`title_id`=4 WHERE `id` = 3
Executing (default): UPDATE `muser` SET `title_id`=4 WHERE `id` = 5
How are you creating your args object? The error suggests something like this: let args = {field1 = null} where Project.field1 does not allow null values.

JPA Criteria "IS NULL OR NOT IN"

I am trying to build the CriteriaQuery equivalent of the following SQL where clause, using OpenJPA 2.4.0:
where employee_status is null or employee_status not in ('Inactive','Terminated')
I have created a list of employeeStatuses, and this is how I am adding the predicate:
predicates.add(
criteriaBuilder.or(
criteriaBuilder.isNull(domainEntity.get("employeeStatus")),
criteriaBuilder.not(domainEntity.get("employeeStatus").in(employeeStatuses))
)
);
The generated SQL looks like this:
AND (t0.EMPLOYEE_STATUS IS NULL OR NOT (t0.EMPLOYEE_STATUS = ? OR t0.EMPLOYEE_STATUS = ?) AND t0.EMPLOYEE_STATUS IS NOT NULL)
As you can see, the 'not in' statement is being transformed into multiple comparisons, with 't0.EMPLOYEE_STATUS IS NOT NULL' added at the end. In order for this to work, the translated clause should be contained in another set of parenthesis.
Any ideas about how I can get this to work?

grails domain constraints mapping to postgresql Gist constraint

I have a PostgreSQL table
CREATE TABLE reservation_table (
idreservation SERIAL NOT NULL,
entry_datetime TIMESTAMPTZ NOT NULL DEFAULT 'NOW',
start_end_dates DATERANGE NOT NULL ,
property_id INT NOT NULL REFERENCES property_table,
...
)
and a constraint to prevent 2 reservations of the same property on same date
ALTER TABLE ONLY reservation_table
ADD CONSTRAINT reservation_double_booking_constraint
EXCLUDE USING gist
(property_id WITH =, start_end_dates WITH &&)
;
Can I enforce my SQL constraint within my Grails Reservation domain ?
I am considering accessing reservation using a view, to avoid problems with postgresql range in groovy
create view resView as
select idReservation,
lower(start_end_dates) AS startDate,
upper(start_end_dates) AS endDate,
property_id
from reservation_table
Ok , but you specified very minimum information to solve this kind of problem , since i have not understood it fully , i have the following suggestion.
How about using before and after interceptor on grails.
class Reservation {
Date startDate ...
def beforeInterceptor = {
//do some date validation here start data or end date
//for exmaple you might check that we have
//any start date currently existing on db
//by findbyStartDate or endDate
//then reject the reservation or saving of this model
println "validation error here , cancel save"
}
static constraints = {
//do some validation here related to ur constraint
startDate max: new Date()
}
}
let me know anything if u need more help . . .