Getting key value from key of hazelcast IMap - spring

I put my object to hazelcast map using spring annotation:
#Cacheable(value = "cacheName", key = "{ #someId1,#someId2}")
public String generateValue(Long someId1, Long someId2)
I would like to invalidate object from cache based on condition placed on key of the Imap. I found that key is a ArrayList with size equal 2. That is expected result.
Set set = cache.keySet(); // this returns Set<ArrayList<Long>>
I try to set condition on key:
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate predicateKey = e.key().get("__key#get(0)").equal(someId1).and(e.get("__key#get(1)").equal(someId2));
But invoking this predicate end up in failure:
Set<Long> idKeysToInvalidate = cache.keySet(predicateKey);
com.hazelcast.query.QueryException: java.lang.IllegalArgumentException: There is no suitable accessor for '__key#get(0)' on class 'class java.util.ArrayList'
at com.hazelcast.query.impl.getters.ReflectionHelper.createGetter(ReflectionHelper.java:176)
Did anyone encounter the same issue?

I haven't done it myself, at least on a key, but can you try __key#[0] otherwise see here: http://docs.hazelcast.org/docs/3.8/manual/html-single/index.html#querying-in-collections-and-arrays

I solved issue as below:
EntryObject e = new PredicateBuilder().getEntryObject();
List<Long> input = Arrays.asList(someId1, someId2);
Predicate predicateKey = e.key().get("hashCode").equal(input.hashCode());
Set<List> idKeysToInvalidate = cache.keySet(predicateKey);

Related

Web3j: Get value of transaction token transfered using Transaction Hash

With Web3j (not Web3js), how do I get the value of token transferred using transaction hash?
I found this example for web3j:
String transactionHash = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
TransactionReceipt transReceipt = web3j.ethGetTransactionReceipt(transactionHash).send().getTransactionReceipt();
Transaction transaction = ethTransaction.getResult();
int size = tokenImpl.getTransferEvents(transReceipt).size();
size = size -1;
BigInteger valueTransaction = tokenImpl.getTransferEvents(transReceipt).get(size).value;
The value will be recieved in BigInteger

How to make Javers compare by field values rather than ID/object reference

I have an object like:
class Person {
Phone phone;
}
class Phone {
String number;
String prefix;
Phone(String n, String p) {
number = n;
prefix = p;
}
}
Now consider this code:
Person p = new Person();
p.phone = new Phone("444444", "01");
javers.commit(p);
p.phone = new Phone("555555", "01");
javers.commit(p);
In this case sees that the reference of Phone has changed. While that's good info, I don't really care about that. I just want to know when the value of the number field has changed, that's really what I am tracking.
How would I achieve that? I tried defining the Phone class as a ValueObject, but it doesn't seem to do the job, I still get it as reference change rather than value change in the resulting Commit snapshot. Should I register it as a Value instead?
Map Phone as ValueObject or let JaVers to apply default mapping, which is also ValueObject object. ValueObject are always compared property by property and never by reference. What do you mean by it doesn't seem to do the job?

Java8 stream average of object property in collection

I'm new to Java so if this has already been answered somewhere else then I either don't know enough to search for the correct things or I just couldn't understand the answers.
So the question being:
I have a bunch of objects in a list:
try(Stream<String> logs = Files.lines(Paths.get(args))) {
return logs.map(LogLine::parseLine).collect(Collectors.toList());
}
And this is how the properties are added:
LogLine line = new LogLine();
line.setUri(matcher.group("uri"));
line.setrequestDuration(matcher.group("requestDuration"));
....
How do I sort logs so that I end up with list where objects with same "uri" are displayed only once with average requestDuration.
Example:
object1.uri = 'uri1', object1.requestDuration = 20;
object2.uri = 'uri2', object2.requestDuration = 30;
object3.uri = 'uri1', object3.requestDuration = 50;
Result:
object1.uri = 'uri1', 35;
object2.uri = 'uri2', 30;
Thanks in advance!
Take a look at Collectors.groupingBy and Collectors.averagingDouble. In your case, you could use them as follows:
Map<String, Double> result = logLines.stream()
.collect(Collectors.groupingBy(
LogLine::getUri,
TreeMap::new,
Collectors.averagingDouble(LogLine::getRequestDuration)));
The Collectors.groupingBy method does what you want. It is overloaded, so that you can specify the function that returns the key to group elements by, the factory that creates the returned map (I'm using TreeMap here, because you want the entries ordered by key, in this case the URI), and a downstream collector, which collects the elements that match the key returned by the first parameter.
If you want an Integer instead of a Double value for the averages, consider using Collectors.averagingInt.
This assumes LogLine has getUri() and getRequestDuration() methods.

How to define a map of SqlParameter specifing the SqlType in grovvy?

I want to create a list of parameter using the constructor MapSqlParameterSource that take a map as input.
Only thing is I don't know how to write a map that will tell MapSqlParameterSource not only ID and Value, but also SqlType.
id = 1
desc = "Description"
insertSql = "INSERT INTO table(id,desc) VALUES (:idCode,:descCode)"
SqlParameterSource mapParam = new MapSqlParameterSource([idCode: id, descCode: desc])
In this way I can create the SqlParameterSource, but I can't specify directly the SqlTypes, and I got in one of the test an exception:
oracle.jdbc.driver.OracleSql.computeBasicInfo(OracleSql.java:950)
oracle.jdbc.driver.OracleSql.getSqlKind(OracleSql.java:623)
oracle.jdbc.driver.OraclePreparedStatement.<init>(OraclePreparedStatement.java:1212)
oracle.jdbc.driver.T4CPreparedStatement.<init>(T4CPreparedStatement.java:28)
oracle.jdbc.driver.T4CDriverExtension.allocatePreparedStatement(T4CDriverExtension.java:68)
oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:3140)
oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:3042)
oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:6022)
That I'm assuming means that couldn't find the SqlType. Do you agree with my assumption and do you have a solution that is not something like this?
mapParam = new MapSqlParameterSource()
mapParam.addValue("idCode", stock, Types.NUMBER)
mapParam.addValue("descCode", stockType, Types.VARCHAR)
Try wrapping the value in an SqlParameterValue object using the SqlParameterValue(int sqlType, Object value) constructor

Unable to create a constant value - only primitive types or Enumeration types allowed

I have seen some questions related to this Exception here but none made me understand the root cause of the problem. So here we have one more...
var testquery =
((from le in context.LoanEMIs.Include("LoanPmnt")
join lp in context.LoanPmnts on le.Id equals lp.LoanEMIId
where lp.PmntDtTm < date && lp.IsPaid == false
&& le.IsActive == true && lp.Amount > 0
select new ObjGetAllPendingPmntDetails
{
Id = lp.Id,
Table = "LoanEMI",
loanEMIId = lp.LoanEMIId,
Name = le.AcHead,
Ref = SqlFunctions.StringConvert((double)le.FreqId),
PmntDtTm = lp.PmntDtTm,
Amount = lp.Amount,
IsDiscard = lp.IsDiscarded,
DiscardRemarks = lp.DiscardRemarks
}).DefaultIfEmpty(ObjNull));
List<ObjGetAllPendingPmntDetails> test = testquery.ToList();
This query gives the following Exception Message -
Unable to create a constant value of type CashVitae.ObjGetAllPendingPmntDetails. Only primitive types or enumeration types are supported in this context.
I got this Exception after I added the SQL function statement to convert le.FreqId which is a byte to a string as ToString() is not recognized in the LINQ Expression Store.
ObjGetAllPendingPmntDetails is a partial class in my model which is added as it is used too many times in the code to bind data to tables.
It has both IDs as long, 'Amount' as decimal, PmntDtTm as Datetime,IsDiscard as bool and remaining all are string including 'Ref'.
I get no results as currently no data satisfies the condition. While trying to handle null, I added DefaultIfEmpty(ObjNull) and ObjNull has all properties initialized as follows.
ObjGetAllPendingPmntDetails ObjNull = new ObjGetAllPendingPmntDetails()
{ Id = 0, Table = "-", loanEMIId = 0, Name = "-", Ref = "-",
PmntDtTm = Convert.ToDateTime("01-01-1900"),
Amount = 0, IsDiscard = false, DiscardRemarks = "" };
I need this query to work fine as it has Union() called on it with 5 other queries. All returning the same ObjGetAllPendingPmntDetails columns. But there is some problem as this query has no data satisfying the conditions and the Exception Shared Above.
Any suggestions are appreciated as I am unable to understand the root cause of the problem.
#AndrewCoonce is right, the .DefaultIfEmpty(ObjNull) is the culprit here. Entity Framework turns DefaultIfEmpty into something like...
CASE WHEN ([Project1].[C1] IS NULL) THEN #param ELSE [Project1].[Value] END AS [C1]
...but there's no way to coerce an instance of ObjGetAllPendingPmntDetails into something that can take the place of #param, so you get an exception.
If you move the DefaultIfEmpty call to after the ToList it should work correctly (although you'll need to call ToList again after that if you really want a concrete list instance).

Resources