'Null checking in spring expression language
I am experiencing a strange behaviour when checking null pointer in a date field inside a collection object
public class FilterTest {
public static void main(String[] args) {
Collection<EmployeeDto> employees = new ArrayList<EmployeeDto>();
employees.add(new EmployeeDto("", 1111, new Date()));
employees.add(new EmployeeDto("123", 2222, null));
employees.add(new EmployeeDto("22", 3333, new Date()));
employees.add(new EmployeeDto("22", 4444, null));
employees.add(new EmployeeDto("11", 5555, null));
employees.add(new EmployeeDto("22", 6666, null));
employees.add(new EmployeeDto(null, 6666,null));
StandardEvaluationContext stdContext = new StandardEvaluationContext();
stdContext.setVariable("emps", employees);
ExpressionParser parser = new SpelExpressionParser();
**String key4= "#emps.?[dateOfBirth != null ? T(DateUtil).formatDate(dateOfBirth), 'dd/MM/yyyy').contains('25/07/2012') : false]" ;**
Collection<Object> proj1 = (Collection<Object>) parser.parseExpression(
key4).getValue(stdContext);
System.out.println(proj1);
}
class EmployeeDto {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
int age;
Date dateOfBirth;
public EmployeeDto(String name, int age, Date dateOfBirth) {
this.name = name;
this.age = age;
this.dateOfBirth = dateOfBirth;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}
The expression should return collection of objects satisfying the condition. But now , I am getting an exception that dateOfBirth cannot be found on null. So I tried with a new expression
String key4= "#emps.?[dateOfBirth != null ? T(DateUtil).formatDate(#emps.![dateOfBirth], 'dd/MM/yyyy').contains('25/07/2012') : false]" ;
This works fine. But when I add null in the first object of the collection, it return results as 0, and when I checked, I found that null is passed to the DateUtil class formatDate method. ie the emploee collection is like `
employees.add(new EmployeeDto("", 1111, null)); // first value is null, and I am getting empty result, but there is one corrrect result
**employees.add(new EmployeeDto("12", 2222, null));**
employees.add(new EmployeeDto("22", 3333, new Date()));
employees.add(new EmployeeDto("33", 4444, null));
employees.add(new EmployeeDto("FIVE", 5555, null));
employees.add(new EmployeeDto("SIX", 6666, null));
employees.add(new EmployeeDto(null, 6666,null));
Could you please help me to solve this issue, can anyone tell the correct expression I should use?
Solution 1:[1]
In your DateUtil class, add a method like:
public static boolean isSameDay(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return false;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return isSameDay(cal1, cal2);
}
Then just do:
StandardEvaluationContext stdContext = new StandardEvaluationContext();
stdContext.setVariable("emps", employees);
stdContext.setVariable("yourTestDate", new Date());
ExpressionParser parser = new SpelExpressionParser();
String key4 = "#emps.?[T(DateUtil).isSameDate(dateOfBirth, yourTestDate)]" ;
Collection<Object> proj1 = (Collection<Object>) parser.parseExpression(key4).getValue(stdContext);
System.out.println(proj1);
Solution 2:[2]
You asked a similar question the other day - in this case, you need to perform the projection on the RESULTS of a collection selection. Here is a simpler example...
Expression exp = new SpelExpressionParser()
.parseExpression("(#emps.?[name != null]).![name.toUpperCase()]");
The first part (...) selects those elements that meet the criteria; it then performs projection on that new collection.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Vincent Devillers |
| Solution 2 | Gary Russell |
