Hazelcast PredicateBuilder with nested key - java

I am trying to add an entrylistener to my hazelcast map using a predicate to filter the entries.
The method I am calling is:
String addEntryListener(MapListener listener,
Predicate<K,V> predicate,
boolean includeValue)
I am trying to build a predicate to filter by my key. My keys are of type HazelKey which have the fields:
KeyOne keyOne;
KeyTwo keyTwo;
KeyThree keyThree;
Then these three Keys have the field:
String code
Therefore i am trying to do something along the lines of:
PredicateBuilder predicate = EntryObject.key().get("keyOne").get("code").equal("1234");
to build a predicate to filter all the entries with the keyOne value 1234.
However once the listener has been added, the entries get updated, hazelcast throws the error:
Caused by: com.hazelcast.query.QueryException: java.lang.IllegalArgumentException: There is no suitable accessor for 'code' on class 'class com.sun.proxy.$Proxy45'
I believe this is because the predicateBuilder is just ignoring the top level 'KeyOne' paramater and just using 'code' so my question is: How do I do this multilevel predicatebuilding?
Thanks in advance.

I am not too familiar with PredicateBuilder, but I believe this should work for you:
import static com.hazelcast.query.Predicates.equal;
[...]
Predicate p = equal("keyOne.code", 1234);

Related

JOOQ: How to map a record to an aliased table (from a nested query)

I have a nested query with a join and I'm trying to map the results back to a table. The query is similar to this:
var nested = context.select(BUSINESS.fields()).from(BUSINESS).limit(size).offset(size * page);
var idField = nested.field(BUSINESS.UIDBUSINESSID);
var result = context.select(nested.fields()).select(BUSINESSALIAS.fields())
.select(BUSINESSCONTACT.fields()).select(BUSINESSIDENTIFIER.fields())
.select(SITEADDRESS.fields()).select(WEBSITE.fields())
.from(nested)
.leftJoin(BUSINESSALIAS)
.on(idField.eq(BUSINESSALIAS.BUSINESSID))
.leftJoin(BUSINESSCONTACT)
.on(idField.eq(BUSINESSCONTACT.BUSINESSID))
.leftJoin(BUSINESSIDENTIFIER)
.on(idField.eq(BUSINESSIDENTIFIER.BUSINESSID))
.leftJoin(SITEADDRESS)
.on(idField.eq(SITEADDRESS.BUSINESSID))
.leftJoin(WEBSITE)
.on(idField.eq(WEBSITE.BUSINESSID))
.fetch();
Mapping the results back to the BUSINESS like this record.into(BUSINESS).into(Business.class) causes a large number of exceptions because there are ambiguous matches for some fields.
The actual error is:
Ambiguous match found for BusinessId. Both "alias_34775958"."BusinessId" and "MCDH"."dbo"."SiteAddress"."BusinessId" match
How to I tell JOOQ that the BUSINESS table qualifier should be the alias alias_34775958 when mapping the record into the table?
Your call to record.into(BUSINESS) causes this ambiguity, because your query doesn't really have any columns from the BUSINESS table (despite your using this table in a derived table).
Try using record.into(nested.fields()) instead, which will produce the exact field references including the generated alias. Alternatively, you can also use a table with an explicit alias:
var nested = table(select(BUSINESS.fields())
.from(BUSINESS)
.limit(size)
.offset(size * page)).as("b");
And now, that nested is of type Table<?> instead of Select<?>, you can use it directly in your record.into(nested) call.

How to use JOOQ's parser to extract table names from SQL statements [duplicate]

Using the JOOQ parser API, I'm able to parse the following query and get the parameters map from the resulting Query object. From this, I can tell that there is one parameter, and it's name is "something".
However, I haven't been able to figure out how to determine that the parameter "something" is assigned to a column named "BAZ" and that column is part of the table "BAR".
Does the parser API have a way to get the table/column metadata associated to each parameter?
String sql = "SELECT A.FOO FROM BAR A WHERE A.BAZ = :something";
DSLContext context = DSL.using...
Parser parser = context.parser();
Query query = parser.parseQuery(sql);
Map<String, Param<?>> params = query.getParams();
Starting from jOOQ 3.16
jOOQ 3.16 introduced a new, experimental (as of 3.16) query object model API, which can be traversed, see:
The manual
A blog post about traversing jOOQ expression trees
Specifically, you can write:
List<QueryPart> parts = query.$traverse(
Traversers.findingAll(q -> q instanceof Param)
);
Or, to conveniently produce exactly the type you wanted:
Map<String, Param<?>> params = query.$traverse(Traversers.collecting(
Collectors.filtering(q -> q instanceof Param,
Collectors.toMap(
q -> ((Param<?>) q).getParamName(),
q -> (Param<?>) q
)
)
));
The Collectors.toMap() call could include a mergeFunction, in case you have the same param name twice.
Pre jOOQ 3.16
As of jOOQ 3.11, the SPI that can be used to access the internal expression tree is the VisitListener SPI, which you have to attach to your context.configuration() prior to parsing. It will then be invoked whenever you traverse that expression tree, e.g. on your query.getParams() call.
However, there's quite a bit of manual plumbing that needs to be done. For example, the VisitListener will only see A.BAZ as a column reference without knowing directly that A is the renamed table BAR. You will have to keep track of such renaming yourself when you visit the BAR A expression.

Esper - Using user-defined function in filter expressions in patterns

I don't understand why I am unable to do this:
select * from pattern [every A = EventA -> EventB(myFunction(A.property))]
From Esper documentation :"All expressions can be used in filters, including static method invocations that return a boolean value".
If I don't try to reference properties from the first matched event (EventA) and instead I only try to pass properties from EventB to myFunction, it works OK.
The error I get is this :
com.espertech.esper.client.EPException: java.lang.ArrayIndexOutOfBoundsException: 1
at com.espertech.esper.core.service.EPRuntimeImpl.processWrappedEvent(EPRuntimeImpl.java:464)
at com.espertech.esper.core.service.EPRuntimeImpl.processEvent(EPRuntimeImpl.java:437)
at com.espertech.esper.core.service.EPRuntimeImpl.sendEvent(EPRuntimeImpl.java:196)
.................
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at com.espertech.esper.epl.expression.ExprIdentNodeEvaluatorImpl.evaluate(ExprIdentNodeEvaluatorImpl.java:30)
at com.espertech.esper.epl.expression.ExprDotEvalStaticMethod.get(ExprDotEvalStaticMethod.java:133)
at com.espertech.esper.filter.FilterParamIndexEquals.matchEvent(FilterParamIndexEquals.java:28)
at com.espertech.esper.filter.FilterParamIndexEquals.matchEvent(FilterParamIndexEquals.java:51)
at com.espertech.esper.filter.FilterHandleSetNode.matchEvent(FilterHandleSetNode.java:97)
at com.espertech.esper.filter.EventTypeIndex.matchType(EventTypeIndex.java:171)
at com.espertech.esper.filter.EventTypeIndex.matchEvent(EventTypeIndex.java:109)
at com.espertech.esper.filter.FilterServiceImpl.evaluate(FilterServiceImpl.java:75)
at com.espertech.esper.core.service.EPRuntimeImpl.processMatches(EPRuntimeImpl.java:911)
at com.espertech.esper.core.service.EPRuntimeImpl.processWrappedEvent(EPRuntimeImpl.java:459)
... 30 more
Perhaps the event type information for EventA and the actual event object do not match so Esper is not able to retrieve the property value. Try to compare the type information and actual object that is sent in.

Google app engine query with a list of string

I have a list of property values named 'token'. I am trying to filter an entity of kind
This is what i have tried.
List<String> tokens = getTokensFrom(invitations);
PersistenceManager pm = this.dataStoreService.getObjectDBConnection();
Query query = pm.newQuery(Invitations.class);
query.setFilter("tokens.contains(token)");
query.declareVariables(List.class.getName() + " tokens");
List<Invitations> invites = (List<Invitations>) query.execute(tokens);
But I'm getting the below error message.
Problem with query <SELECT FROM com.mypackage.shared.domainobjects.Invitations WHERE tokens.contains(token) VARIABLES java.util.List tokens>: Unsupported method <contains> while parsing expression: InvokeExpression{[VariableExpression{tokens}].contains(PrimaryExpression{token})}
com.google.appengine.datanucleus.query.DatastoreQuery$UnsupportedDatastoreFeatureException: Problem with query <SELECT FROM com.testbudha.shared.domainobjects.PublishedExam WHERE tokens.contains(token) VARIABLES java.util.Collection tokens>: Unsupported method <contains> while parsing expression: InvokeExpression{[VariableExpression{tokens}].contains(PrimaryExpression{token})}
at com.google.appengine.datanucleus.query.DatastoreQuery.newUnsupportedQueryMethodException(DatastoreQuery.java:993)
at com.google.appengine.datanucleus.query.DatastoreQuery.handleContainsOperation(DatastoreQuery.java:971)
at com.google.appengine.datanucleus.query.DatastoreQuery.addExpression(DatastoreQuery.java:830)
at com.google.appengine.datanucleus.query.DatastoreQuery.addFilters(DatastoreQuery.java:739)
at com.google.appengine.datanucleus.query.DatastoreQuery.compile(DatastoreQuery.java:248)
at com.google.appengine.datanucleus.query.JDOQLQuery.performExecute(JDOQLQuery.java:158)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1789)
at org.datanucleus.store.query.Query.executeWithArray(Query.java:1666)
at org.datanucleus.api.jdo.JDOQuery.execute(JDOQuery.java:243)
I had a similar problem previously but it works because the filter criteria was the other way round i.e. this.token.contains(tokens) where 'token' was part of the entity and was of type List of String. But I'm not sure why this is not working. Can someone please help me?
You declare some variable called "tokens" yet pass in a parameter (presumably what you intended to be the tokens variable). A variable is not a parameter, they are different. Either use an explicit parameter, or an implicit parameter (with : prefix) as any decent JDO docs would tell you

how can I get dynamic property in drools

I have a XML file containing metadata like a field's maximum length. I have to use drools to build rules to validate this metadata against a list of facts. I don't want to hardcode the name of each field that may or may not be specified in the XML.
I tried to do this :
when
$metadata: Metadata(maxLength != null);
$obj: Object(eval($metadata.getFieldName()).length > $metadata.maxLength);
then
// TODO
end
It does not work and I get the following error :
java.lang.IllegalStateException: Errors while building rules : Unable
to Analyse Expression $metadata.getFieldName() > $metadata.maxLength:
[Error: Comparison operation requires compatible types. Found class
java.lang.String and class java.lang.Integer] [Near : {...
$metadata.getFieldName() > $metadata.maxLength ....}]
Is it possible to dynamically get a field name and compare its maximum length? Will I have to create a java object to accomplish this?
Thank you
You talk of XML and metadata. Can you distinguish all entities? For example, if it is about orders, can you extract each order, and attributes of each order?
I solved a similar problem with using maps to store each attribute.
public class Order{
private int id;
private Map<String, Integer> num_attribute_map = new HashMap<String, Integer>();
public Map getNumAttributeMap(){
return this.num_attribute_map;
}
If an order has customer_satisfaction = 5,
order_obj.getNumAttributeMap().put("customer_satisfaction" , 5);
And thus you have created Orders with their attributes stored in the numAttributeMap.
For implementing a rule on an Order
$ord : Order(
getNumAttributeMap[$attribute] >= $value
)
where $attribute would be "customer_satisfaction", of course. The [] notation is used to access elements of a list, given index or values of a map, given the key.
Hope you "get" the concepts of maps. Also, do look up Drools language support for list and map access.
I have also implemented maps of lists of strings to perform an "is in" operation, in addition to maps of integers that do comparison operations. Please refer https://stackoverflow.com/a/9241089/604511 too
Finally, I have decided to generate my drools file dynamically from my XML using rule templates.

Categories

Resources