How to ensure non null columns in Java (spring) - java

I have a project (in Java and Angular) about designing a financial website to manage some data like contracts. In our databases, some columns can't be null.
In SQL for example, it's very easy to set that condition, and for that example, I have to respect that rules :
ID NUMBER NOT NULL ,
USER_ID NUMBER NOT NULL,
PARENT_ID VARCHAR2(280) NULL,
PARENT_LEGAL_NAME VARCHAR2(280) NULL ,
POLICY_BUCODE VARCHAR2(280) NOT NULL,
POLICY_ID VARCHAR2(280) NOT NULL,
POLICY_TYPE_CODE VARCHAR2(280) NOT NULL ,
POLICY_ACTIVE_STATUS NUMBER(1),
POLICY_LEGAL_NAME VARCHAR2(280) NOT NULL ,
PA_FLAG NUMBER(1) DEFAULT 0 NOT NULL ,
RISK_FLAG NUMBER(1) DEFAULT 0 NOT NULL ,
CC_FLAG NUMBER(1) DEFAULT 0 NOT NULL ,
VISIBLE_FLAG NUMBER(1) DEFAULT 1 NOT NULL
The problem is that I had to ensure that in java-side... and I had a lot of difficulty to fix that.
The idea for that is that if we read a Contract object from an array of Contract objects (like when someone want to enter new data in a table in SQL), we will check for that. So, if we are reading an array of contacts and a contract doesn't have a required field (for example POLICY_BUCODE), we will just skip it and jump to the next element. We can do that easily with a for loop.
The problem is that I got lost in the long code and I don't how to find those variables... For example, a Contract object has an ID which is an object of a class called ID!!!! Which I found very strange and I got very confused about that... I found also strange that some classes has name with underscore (ex : Coreinfo_.java)
So, I tried to do something like that :
for (contract in contractList) {
if (contract.getId() == null || contract.getId().getId() == null || contract.getId().getBuCode == null) {
//don't do anything, just jump to the next element
} else {
//the rest of other codes
}
The problem is that I'm not good enough in Java and I REALLY got lost in that long code. With my example, I "think" that i'm ensuring non null values for ID, POLICY_ID and POLICY_BYCODE but i'm not sure at all...
Here is my plunker with some of our java classes :
https://plnkr.co/edit/BylPPjXLJ7PY0aBP5xPF
Can you just give me a little help to do that? at least by understanding the model and where are those variables located?

The problem is that I had to ensure that in java-side... and I had a
lot of difficulty to fix that.
You can set the constraints/rules even in Java classes like how you did in your SQL.
For setting the constraints on Java class variables, you need to use javax.validation.constraints package rules.
For your Contract class #NotNull can be set on id variable as shown below :
public class Contract {
#NotNull
private long id;
//other variables
}
You can apply various constraints like #Min, #Max, etc.. as well and you can look here for more details.

Related

Validate facts having nested maps using drools

I have a class Fact which is a extends java.util.HashMap class. I am passing object of this class as fact to drools.
Now an instance of fact looks like this (Map<String, Object>):
{
"key1": "value"
"attributes": [{"name": "name1", "value": "value1"},{"name": "name2", "value": "value2"},{"name": "name3", "value": "value3"}...]
"locks": [{"type": "type1", "value": "value1", "attributes": {"key_a1": "val_a1""key_a2": "val_a2"...}}]
}
Running validations on root level entries in this map is straight forward e.g. running validations on key1.
Now, I want to run some validations on attributes and locks.
For attributes, I want to ensure that all attributes which are needed are present in this map and their corresponding values are correct. So I do this in the when block:
fact: Fact(this["key1"] != null && this.containsKey("attributes"));
attributesEntries: Entry(key == "attributes") from fact.entrySet();
attributesMaps: LinkedHashMap() from attributesEntries;
fact is HashMap
attributes are of type ArrayList<LinkedHashMap<String, String>> (an id key is also added for the LinkedHashMap whose value is the value of key name only).
locks are of type ArrayList<LinkedHashMap<String, Object>>
locks have attributes of type Map<String, String>
but it is not working. When I evaluate attributesEntries it is ArrayList<LinkedHashMap> and it has all the expected values but attributesMaps comes as empty. I also tried passing filters like LinkedHashMap(key == 'key1', value == 'val1') but that also didn't work. Tried looking for solutions and none were available for this sort of structure. Whatever was available I tried to extend but didn't work.
Is this possible to achieve and if so how? Also, how do I validate value (not empty and matches a pattern) once I am able to get it from the Map.
I am new to drools and we are using 5.4.0.Final version of drools.
Also, how can I work with the next level nested Map in locks.
I once had the misfortune of working on a project where we made this same mistake and had our class extend HashMap. (Fair warning: HashMap doesn't serialize well so you're going to use a lot of extra memory.)
I'm going to assume several things about your model because you neglected to share the class definition itself.
But I'm going to assume the following, based on your example JSON:
You have added a string value ("value") with the key "key1"
You have added a List<Map<String, ?>> value (possibly a List<Fact>) with the key "locks"
You have added a List<Map<String, ?>> value (possibly a List<Fact>) with the key "attributes"
The HashMap's get(key) method will return an object value; you've already noted the special this[ key ] syntax.
From your partial rule attempt, it's not entirely clear what you're trying to do. I think you're trying to get the List<Map<String, ?>> that is saved in your map under the "attributes" key.
rule "Do something with the attributes"
when
$fact: Fact( this["key1"] != null,
$attr: this["attributes"] != null )
then
System.out.println("Found " + $attr.size() + " attributes");
end
this["attributes"] returns the value associated with the key attributes. In this case, it's a List or whatever you shoved in there. If the key doesn't exist, the null check handles that.
You also asked how you could do stuff with a child map inside one of those lists. Let's say that want to do something with the attribute that has "name": "name1" ...
rule "Do something with the 'name = name1' attribute"
when
$fact: Fact( this["key1"] != null,
$attributes: this["attributes"] != null )
$nameAttr: Map( this["name"] == "name1" ) from $attributes
then
// do something with $nameAttr
end
The pattern repeats, of course. Let's say you've shoved yet another List<Map<String, ?>> into your attribute maps:
rule "Do something with a child of 'name' attribute"
when
$fact: Fact( this["key1"] != null,
$attributes: this["attributes"] != null )
$nameAttr: Map( this["name"] == "name1",
$attrKids: this["children"] != null ) from $attributes
$childNameAttr: Map( this["name"] == "child1" ) from $attrKids
then
// etc.
end
I strongly recommend reconsidering your object model to not be Map-based. At the company I worked at where all of our projects were built against a nested Map-based model and running Drools 5.0.1, I spent significant time and effort upgrading parts of it to Drools 7 and a proper model that passed in just the data we needed. It saved a ton of resources and ended up being much faster.

ObjectUtils defaultIfNull returning default value even when first param is not null

target = ObjectUtils.defaultIfNull(getCustomerByAddressID(sourceData, supportParam),
createNewCustomer(supportParam));
I am passing 2 functions to ObjectUtils.defaultIfNull. First is function which returns Customer if found by AddressID else null, second param is function which create new Customer.
After execution I am seeing 2 Customers, debug is showing even after getCustomerByAddressID(sourceData, supportParam) returns not null value - createNewCustomer(supportParam) is getting executed.
Is this issue because of Code formatting or what am I missing? Should I use Optional.ofNullable().orElse() instead of ObjectUtils.defaultIfNull?
You can use Optional.ofNullable(getCustomerByAddressID(sourceData, supportParam)).orElseGet(() -> createNewCustomer(supportParam)) if you don't want createNewCustomer(supportParam) to be invoked, even if getCustomerByAddressID(sourceData, supportParam) is null
You should use
target = Optional.ofNullable(getCustomerByAddressID(sourceData, supportParam))
.orElseGet(() -> createNewCustomer(supportParam));
Because both Optional.ofNullable().orElse() and ObjectUtils.defaultIfNull() which uses ternary operator internally, always call "orElse" part.

How to properly check for Boolean value in Spring EL expression?

I'm a bit new to using Spring Expression Language but I'm trying to see what is the best way to check a that a Boolean value is not null and true?
For type "Display" there is a property "removeMessage" which is of type java.lang.Boolean.
So I want to first check that this value is not null and that it is true. Based on if this is true or not I will either return an empty string or a calculatedMessage.
I am currently checking with below expression:
display?.removeMessage != null && display?.removeMessage ? '' : display.calculatedMessage
While this works, I was hoping to find a more nicer way to do the null and true check. I was thinking/hoping for something more like how we would check normally such as e.g. BoolenUtils.isTrue(value) (apache), or even just checking like Boolean.TRUE.equals(value) which takes care of the null check.
Just having this should work , and already include your null check:
display?.removeMessage ? null : display.calculatedMessage

How to handle `null` strings coming from a RESTful API in JSONObject?

Here's a service return, that gives us user's profile info:
{
email: 'someone#example.com',
pictureUrl: 'http://example.com/profile-pictures/somebody.png',
phone: null,
name: null
}
Now we get this JSON in our android app, and turn it into JSONObject model:
JSONObject profileInfo = new JSONObject(profileInfoJson);
And we bind UI views to data:
email.setText(profileInfo.getString("email"));
phone.setText(profileInfo.getString("phone"));
name.setText(profileInfo.getString("name"));
Then in our TextView or EditView we have null string, instead of having nothing.
It's possible that we check null values using if-then statements, but that's too much for a real-world application with so many fields.
Is there a way to configure JSONObject to gracefully handle null strings?
Update: I used optString with a fallback, as suggested, but it has no effect:
firstName.setText(profileInfo.optString("firstName", ""));
And the result is the same EditText has null in it.
Use optString, if no suitable value is found then the second parameter will be returned instead of exception or null
phone.setText(profileInfo.optString("phone","nophone"));
name.setText(profileInfo.optString("name","noname"));
Returns the value mapped by name if it exists, coercing(try to cast) it if
necessary, or fallback(return second parameter)if no such mapping exists.

hbase: querying for specific value with dynamically created qualifier

Hy,
Hbase allows a column family to have different qualifiers in different rows. In my case a column family has the following specification
abc[cnt] # where cnt is an integer that can be any positive integer
what I want to achieve is to get all the data from a different column family, only if the value of the described qualifier (in a different column family) matches.
for narrowing the Scan down I just add those two families I need for the query. but that is as far as I could get for now.
I already achieved the same behaviour with a SingleColumnValueFilter, but then the qualifier was known in advance. but for this one the qualifier can be abc1, abc2 ... there would be too many options, thus too many SingleColumnValueFilter's.
Then I tried using the ValueFilter, but this filter only returns those columns that match the value, thus the wrong column family.
Can you think of any way to achieve my goal, querying for a value within a dynamically created qualifier in a column family and returning the contents of the column family and another column family (as specified when creating the Scan)? preferably only querying once.
Thanks in advance for any input.
UPDATE: (for clarification as discussed in the comments)
in a more graphical way, a row may have the following:
colfam1:aaa
colfam1:aab
colfam1:aac
colfam2:abc1
colfam2:abc2
whereas I want to get all of the family colfam1 if any value of colfam2 has e.g. the value x, with regard to the fact that colfam2:abc[cnt] is dynamically created with cnt being any positive integer
I see two approaches for this: client-side filtering or server-side filtering.
Client-side filtering is more straightforward. The Scan adds only the two families "colfam1" and "colfam2". Then, for each Result you get from scanner.next(), you must filter according to the qualifiers in "colfam2".
byte[] queryValue = Bytes.toBytes("x");
Scan scan = new Scan();
scan.addFamily(Bytes.toBytes("colfam1");
scan.addFamily(Bytes.toBytes("colfam2");
ResultScanner scanner = myTable.getScanner(scan);
Result res;
while((res = scanner.next()) != null) {
NavigableMap<byte[],byte[]> colfam2 = res.getFamilyMap(Bytes.toBytes("colfam2"));
boolean foundQueryValue = false;
SearchForQueryValue: while(!colfam2.isEmpty()) {
Entry<byte[], byte[]> cell = colfam2.pollFirstEntry();
if( Bytes.equals(cell.getValue(), queryValue) ) {
foundQueryValue = true;
break SearchForQueryValue;
}
}
if(foundQueryValue) {
NavigableMap<byte[],byte[]> colfam1 = res.getFamilyMap(Bytes.toBytes("colfam1"));
LinkedList<KeyValue> listKV = new LinkedList<KeyValue>();
while(!colfam1.isEmpty()) {
Entry<byte[], byte[]> cell = colfam1.pollFirstEntry();
listKV.add(new KeyValue(res.getRow(), Bytes.toBytes("colfam1"), cell.getKey(), cell.getValue());
}
Result filteredResult = new Result(listKV);
}
}
(This code was not tested)
And then finally filteredResult is what you want. This approach is not elegant and might also give you performance issues if you have a lot of data in those families. If "colfam1" has a lot of data, you don't want to transfer it to the client if it will end up not being used if value "x" is not in a qualifier of "colfam2".
Server-side filtering. This requires you to implement your own Filter class. I believe you cannot use the provided filter types to do this. Implementing your own Filter takes some work, you also need to compile it as a .jar and make it available to all RegionServers. But then, it helps you to avoid sending loads of data of "colfam1" in vain.
It is too much work for me to show you how to custom implement a Filter, so I recommend reading a good book (HBase: The Definitive Guide for example). However, the Filter code will look pretty much like the client-side filtering I showed you, so that's half of the work done.

Categories