Java 8 compilation error “inference variable D has incompatible bounds”

Java 8 won’t compile the code below (Java 7 used to do it fine). I understand the error somewhat but have no idea how to fix my code, can you help me?

The error is on this line:

spec = spec.and(toSpecification(range));

I obviously need to either change the parameter passed, or to rewrite the toSpecification code, but have not found anything that will work.

public class RangeSpecification {

    public static <E> Specification<E> andRangeIfSet(Specification<E> spec, final List<Range<E, ?>> ranges) {
        for (Range<E, ?> range : ranges) {
            if (range.isSet()) {
                spec = spec.and(toSpecification(range));
            }
        }
        return spec;
    }

    public static <E, D extends Comparable<? super D>> Specification<E> toSpecification(final Range<E, D> range) {
        Validate.isTrue(range.isSet(), "You must provide a usable criterion");
        return new Specification<E>() {
            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<E> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Predicate rangePredicate = null;

                if (range.isBetween()) {
                    rangePredicate = builder.between(root.get(range.getField()), range.getFrom(), range.getTo());
                } else if (range.isFromSet()) {
                    rangePredicate = builder.greaterThanOrEqualTo(root.get(range.getField()), range.getFrom());
                } else if (range.isToSet()) {
                    rangePredicate = builder.lessThanOrEqualTo(root.get(range.getField()), range.getTo());
                }

                if (rangePredicate != null) {
                    if (!range.isIncludeNullSet() || range.getIncludeNull() == Boolean.FALSE) {
                        return rangePredicate;
                    } else {
                        return builder.or(rangePredicate, builder.isNull(root.get(range.getField())));
                    }
                }

                // Pas de range
                if (range.getIncludeNull() == Boolean.TRUE) {
                    return builder.isNull(root.get(range.getField()));
                }

                if (range.getIncludeNull() == Boolean.FALSE) {
                    return builder.isNotNull(root.get(range.getField()));
                }

                throw new IllegalStateException("Vous devez passer un critère exploitable !!!(ne devrait jamais ce produire ici)");
            }
        };
    }
}

The full error is:

/D:/xxx/repository/support/RangeSpecification.java:[23,33] method toSpecification in class xxx.repository.support.RangeSpecification cannot be applied to given types;
required: xxx.repository.support.Range
found: xxx.repository.support.Range
reason: inference variable D has incompatible bounds
equality constraints: capture#1 of ?
upper bounds: java.lang.Comparable

I need code that compiles! Eclipse builds without error but compiling with Java 1.8.191 errors out. Many thanks in advance.

Answer

Actually, the code should be like that:

public static <E, D extends Comparable<? super D>> Specification<E> andRangeIfSet(Specification<E> spec, final List<Range<E, D>> ranges) {
    for (Range<E, D> range : ranges) {
        if (range.isSet()) {
            spec = spec.and(toSpecification(range));
        }
    }
    return spec;
}

I’m not able to compile and test that, but the bound of parameter “D” was missing. In general, try to avoid the wildcard “?” whereever possible.

Note that you’ll have to refactor all callers of that method.

Leave a Reply

Your email address will not be published. Required fields are marked *