#StackBounty: #spring #mongodb #spring-boot #spring-data #querydsl Cannot Query for a field within a Set using Spring Data Repository w…

Bounty: 50

I have implemented a Rest API using Spring Boot version 1.5.12, Spring Data MongoDB, and QueryDSL with Web Support. Anytime I try to execute a query like the following (http://localhost:8080/loads?itemName=Towel&itemIds=5b20677e8bb7390001a16ab8,5b20677e8bb7390001a16abs) I get the error below:

{
    "status": 500,
    "message": "com.querydsl.core.types.dsl.SetPath cannot be cast to com.querydsl.core.types.dsl.StringPath",
    "detailedMessage": "ClassCastException: com.querydsl.core.types.dsl.SetPath cannot be cast to com.querydsl.core.types.dsl.StringPath"
}

I would like my model class to be queried with queries that include “like”, “startsWith”, “endsWith”, and “equals ignore case”. Somehow the mechanism I implemented forces this on Sets within my model (Item). I have been trying to figure out, with out success, how to fix this. I would greatly appreciate it if the community here can help me resolve this issue. Below is my code.

Model Class:

@Document
@QueryEntity
@ApiModel
public class Item {
  @Id
  private String id;
  private int itemSize;
  private String itemName;
  private Set<String> itemIds = new HashSet();

  ...

Controller Layer:

  @GetMapping
  @ApiOperation(value = "Get Items", notes = "Returns Items")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization Bearer JWT Token",
          required = true, dataType = "string", paramType = "header")
  })
  public ResponseEntity<ItemResponse> list(
      @QuerydslPredicate(root = Item.class) final Predicate predicate,
      final Pageable pageable) {

    ItemResponse data = ItemService.list(predicate, pageable);

    if (data == null) {
      return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    return new ResponseEntity<>(data, HttpStatus.OK);
  }

Service Layer:

  @Override
  public ItemResponse list(final Predicate predicate, final Pageable pageable) {

    ItemResponse ItemResponse = new ItemResponse();

    ItemResponse.setCount(ItemRepository.count(predicate));
    ItemResponse.setData(Lists.newArrayList(ItemRepository.findAll(predicate, pageable)));

    return ItemResponse;
  }

Repository Layer:

@Repository
public interface ItemRepository extends MongoRepository<Item, String>,
    QueryDslPredicateExecutor<Item> , QuerydslBinderCustomizer<QItem> {

  default void customize(QuerydslBindings bindings, QItem data) {

    bindings.bind(String.class).all((MultiValueBinding<StringPath, String>) (path, values) -> {
      BooleanBuilder predicate = new BooleanBuilder();
      values.forEach(value -> {
            if (value.startsWith("~") && !value.endsWith("~")) {

              predicate.or(path.endsWithIgnoreCase(value.substring(1)));

            } else if (!value.startsWith("~") && value.endsWith("~")) {

              predicate.or(path.startsWithIgnoreCase(value.substring(0,value.length() - 1)));

            } else if (value.startsWith("~") && value.endsWith("~")) {

              predicate.or(path.containsIgnoreCase(value.substring(1, value.length() - 1)));

            } else {
              predicate.or(path.equalsIgnoreCase(value));
            }
          }
      );
      return predicate;
    });
  }
}

Driver class:

@SpringBootApplication
@EnableSpringDataWebSupport
public class Application {

  public static void main(String[] args) {

    SpringApplication.run(Application.class, args);
  }
}

Pom.xml

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.12.RELEASE</version>
  </parent>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
      <groupId>com.querydsl</groupId>
      <artifactId>querydsl-mongodb</artifactId>
      <version>4.2.1</version>
    </dependency>
    <dependency>
      <groupId>com.querydsl</groupId>
      <artifactId>querydsl-apt</artifactId>
      <version>4.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
...
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>com.mysema.maven</groupId>
        <artifactId>apt-maven-plugin</artifactId>
        <version>${mysema.maven.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>process</goal>
            </goals>
            <configuration>
              <outputDirectory>target/generated-sources/java</outputDirectory>
              <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
...


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.