fix(manager-api-jpa): parse filter number into same numeric data type as target field.
Previously, we were assuming all the fields were `Long`. In some cases they are `Integer`
and this causes a data type mismatch with certain target fields.
Fixes:
MODIFY
manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java
manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java
@@ -44,6 +44,7 @@ import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.CriteriaBuilderFactory;
import com.blazebit.persistence.PagedList;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
+import com.blazebit.persistence.Path;
import org.hibernate.Session;
import org.jdbi.v3.core.Jdbi;
@@ -301,10 +302,10 @@ public abstract class AbstractJpaStorage {
List<SearchCriteriaFilterBean> filters = criteria.getFilters();
if (filters != null && !filters.isEmpty()) {
for (SearchCriteriaFilterBean filter : filters) {
+ Path path = cb.getPath(filter.getName());
+ Class<?> pathKlazz = path.getJavaType();
final String name = cb.getPath(filter.getName()).getPath();
if (filter.getOperator() == SearchCriteriaFilterOperator.eq) {
- com.blazebit.persistence.Path path = cb.getPath(filter.getName());
- Class<?> pathKlazz = path.getJavaType();
if (pathKlazz.isEnum()) {
cb = cb.where(name).eq(Enum.valueOf((Class) pathKlazz, filter.getValue()));
} else {
@@ -313,15 +314,15 @@ public abstract class AbstractJpaStorage {
} else if (filter.getOperator() == SearchCriteriaFilterOperator.bool_eq) {
cb = cb.where(name).eq(Boolean.valueOf(filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.gt) {
- cb = cb.where(name).gt(Long.valueOf(filter.getValue()));
+ cb = cb.where(name).gt(numberValueOf(pathKlazz, filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.gte) {
- cb = cb.where(name).ge(Long.valueOf(filter.getValue()));
+ cb = cb.where(name).ge(numberValueOf(pathKlazz, filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.lt) {
- cb = cb.where(name).lt(Long.valueOf(filter.getValue()));
+ cb = cb.where(name).lt(numberValueOf(pathKlazz, filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.lte) {
- cb = cb.where(name).le(Long.valueOf(filter.getValue()));
+ cb = cb.where(name).le(numberValueOf(pathKlazz, filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.neq) {
- cb = cb.where(name).notEq(Long.valueOf(filter.getValue()));
+ cb = cb.where(name).notEq(numberValueOf(pathKlazz, filter.getValue()));
} else if (filter.getOperator() == SearchCriteriaFilterOperator.like) {
cb = cb.where(name).like(false).value(filter.getValue().toUpperCase().replace('*', '%')).noEscape();
}
@@ -340,6 +341,19 @@ public abstract class AbstractJpaStorage {
return cb;
}
+ private Number numberValueOf(Class<?> klazz, String value) {
+ if (klazz.equals(long.class) || klazz.equals(Long.class)) {
+ return Long.valueOf(value);
+ }
+ else if (klazz.equals(int.class) || klazz.equals(Integer.class)) {
+ return Integer.valueOf(value);
+ }
+ else if (klazz.equals(byte.class) || klazz.equals(Byte.class)) {
+ return Byte.valueOf(value);
+ }
+ throw new IllegalArgumentException("This method accepts only Integer/int, Long/long, or Byte/byte");
+ }
+
@SuppressWarnings("unchecked")
protected <T> Optional<T> getOne(TypedQuery<T> query) {
List<T> resultList = (List<T>) query.getResultList();

ADD
manager/test/api/src/test/resources/test-plan-data/searching/queries/apis/013_query-integer-field-issue-2283.resttest
+POST /search/apis admin/admin
+Content-Type: application/json
+
+{
+ "filters": [
+ {
+ "name": "numPublished",
+ "value": "0",
+ "operator": "gt"
+ }
+ ]
+}
+----
+200
+Content-Type: application/json
+
+{
+ "beans":[],
+ "totalSize":0
+}

MODIFY
manager/test/api/src/test/resources/test-plans/searching-testPlan.xml
manager/test/api/src/test/resources/test-plans/searching-testPlan.xml
<test name="Query Api By Name Lowercase">test-plan-data/searching/queries/apis/010_query-by-name-lower.resttest</test>
<test name="Query Api By Name Mixedcase">test-plan-data/searching/queries/apis/011_query-by-name-mixed.resttest</test>
<test name="Query Api By Name Special">test-plan-data/searching/queries/apis/012_query-by-name-special.resttest</test>
+ <test name="Query integer field with numeric gt comparison (Issue 2283)">test-plan-data/searching/queries/apis/013_query-integer-field-issue-2283.resttest</test>
<!-- Misc -->
<test name="Query API Catalogs">test-plan-data/searching/queries/misc/001_query-api-catalog.resttest</test>
<test name="List API Catalog Namespaces">test-plan-data/searching/queries/misc/002_query-api-namespaces.resttest</test>

fix(manager-api-jpa): parse filter number into same numeric data type as target field.

Previously, we were assuming all the fields were `Long`. In some cases they are `Integer`
and this causes a data type mismatch with certain target fields.

Fixes: #2283