Querying against int column returns error

Issue #5 resolved
Mike Samsel created an issue

Everything complies fine and can use postman to retrieve data against a string. http://localhost:8080/airpts/search?page=0&size=2&sort=type,asc&sort=municipality,desc&municipality=eq(Sylvania)

However, when I try against a column that is an integrer I get an error. http://localhost:8080/airpts/search?elev=eq(200)

"status": 500, "error": "Internal Server Error",

"message": "Failed to convert from type [java.lang.String] to type [@javax.persistence.Basic @javax.persistence.Column int] for value 'eq(200)'; nested exception is java.lang.NumberFormatException: For input string: \"eq(200)\""


Controller:

@RestController @RequestMapping(value = "/airpts")

public class AirptController {

@Autowired
private AirptService airptService;

@Autowired
private AirptRepository airptRepo;

@PostMapping("/airpt")
public Airpt save(@RequestBody Airpt airpt){
    return airptService.save(airpt);
}

@GetMapping("/airpt/{id}")
public Optional<Airpt> getById(@PathVariable(value = "id") Long id){
    return airptService.find(id);
}

@GetMapping("/airpt")
public List<Airpt> getAll(){
    return airptService.findAll();
}

@DeleteMapping("/airpt/{id}")
public void deleteById(@PathVariable(value = "id") Long id){
    airptService.delete(id);
}

@DeleteMapping("/airpt")
public void deleteAll(){
    airptService.deleteAll();
}

@GetMapping("/airpt/count")
public long count(){
    return airptService.count();
}

@RequestMapping(path = {"/search"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET,RequestMethod.POST})
public ResponseEntity<Iterable<Airpt>> searchAirpt(@ApiIgnore @QuerydslPredicate(root = Airpt.class) Predicate predicate, @PageableDefault Pageable pageable) {
    if (predicate == null || (BooleanBuilder.class.isAssignableFrom(predicate.getClass())
            && !((BooleanBuilder) predicate).hasValue())) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    } else {
        return ResponseEntity.ok(airptRepo.findAll(predicate, pageable));
    }
}

}


Repository:

@Transactional @Repository @RepositoryRestResource(collectionResourceRel = "airpts", path = "/airpts") public interface AirptRepository extends JpaRepository<Airpt, Long>, QuerydslPredicateExecutor<Airpt>, QuerydslBinderCustomizer<QAirpt> {

@Override
default void customize(QuerydslBindings bindings, QAirpt root) {

    bindings.excluding(
            root.airptId,
            root.dst
    );

    bindings.bind(root.name)
            .all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));

    bindings.bind(root.type)
            .all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));

    bindings.bind(root.municipality)
            .all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));

    bindings.bind(root.elev)
            .all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));

}

}


Model (not complete):

@Entity @Table(name = "AIRPT", schema = "OPX") public class Airpt { private byte[] airptId; private String type; private String municipality; private String name; private int elev;

@Id @Column(name = "AIRPT_ID", nullable = false) public byte[] getAirptId() { return airptId; }

public void setAirptId(byte[] airptId) {
    this.airptId = airptId;
}

@Basic
@Column(name = "TYPE", nullable = true, length = 50)
public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}

@Basic
@Column(name = "MUNICIPALITY", nullable = true, length = 50)
public String getMunicipality() {
    return municipality;
}

public void setMunicipality(String municipality) {
    this.municipality = municipality;
}

@Basic
@Column(name = "ELEV", nullable = false)
public int getElev() {
    return elev;
}

public void setElev(int elev) {
    this.elev = elev;
}

}

Perhaps it is something I missing. Let me know if you require more information. I really want to be able to use this library.

Comments (8)

  1. GT Tech repo owner

    Thank you for reporting the issue you are facing. There's a known issue with Spring QueryDSL internals for non-String values in terms of how it performs type conversion and its relation to how value operators are designed for processing. I suspect you are running into that but good news is we have an experimental feature in the SDK to get past it.

    Please review Advance usage & considerations section in readme which can be located either here or here.

    There are two experimental features offered by the library and they both work pretty much to the same means. If your application is simple thread-per-request standard synchronous servlet design, then you can just use the filter or else you can go with advanced method of simply defining a bean post processor provided by this library in your Spring application context and it will automatically modify the default type conversion in QueryDSL integration such that it will start to support type conversion for non-String values as per your use-case.

    Please report back if it solves the issue.

    I am presuming you are using 2.0.0 version of this SDK library.

  2. Mike Samsel reporter

    I was able to query an integer field using experimental method (eq and gte). However, I am trying to perform a query against a timestamp field and also a date field, I get errors.

    Model: public class Airpt { private byte[] airptId; private Timestamp createDate;

    Repository: Under customize I added: bindings.bind(root.createDate) .all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));

    I try to use postman with the following: http://localhost:8080/airpts/search?createDate="12/26/2018 4:29:37 AM"

    I get the following error:

    { "timestamp": "2019-02-11T16:25:24.081+0000", "status": 500, "error": "Internal Server Error", "message": "CacheLoader returned null for key airpt.createDate.", "trace": "com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key airpt.createDate.\r\n\tat com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2350)\r\n\tat com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2320)\r\n\tat com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282)\r\n\tat com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197)\r\n\tat com.google.common.cache.LocalCache.get(LocalCache.java:3937)\r\n\tat com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)\r\n\tat com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)\r\n\tat com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4830)\r\n\tat org.bitbucket.gt_tech.spring.data.querydsl.value.operators.ExpressionProviderFactory.getPredicate(ExpressionProviderFactory.java:86)\r\n\tat com.aerotracx.opx.repository.AirptRepository.lambda$customize$4(AirptRepository.java:38)\r\n\tat org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.invokeBinding(QuerydslPredicateBuilder.java:136)\r\n\tat org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPredicate(QuerydslPredicateBuilder.java:115)\r\n\tat org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver.resolveArgument(QuerydslPredicateArgumentResolver.java:112)\r\n\tat org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver.resolveArgument(QuerydslPredicateArgumentResolver.java:51)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:166)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:634)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:741)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n\tat org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)\r\n\tat org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat com.aerotracx.opx.filter.CustomFilter.doFilter(CustomFilter.java:15)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n\tat org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n\tat org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n\tat org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)\r\n\tat org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\n", "path": "/airpts/search" }

    Can a date or timestamps be queried and if so could you kindly provide an example of what I would need to change in my repository customize class to allow for full query capability on a time stamp or dateTime field?

    Thanks.

  3. GT Tech repo owner

    DateTimePath support isn't added as of yet, I think you are looking for enhancement requested here Please vote for the issue. I'd try to release a milestone soon.

  4. Mike Samsel reporter

    Thanks. I will place the request. I think having datetime, timestamp, boolean, and string would cover 99% use cases.

  5. GT Tech repo owner

    BooleanPath is supported out of the box and doesn't need expression building from this library as the value for that field could be either true or false. you can just provide appropriate binding customization for that particular field in below method:

    @Override
        default void customize(QuerydslBindings bindings, QUser root) {
    .....
    

    I am beginning to look at DateTimePath this week.

  6. GT Tech repo owner

    Please see the resolution comment and details here. Resolving this issue. Hope that helps but I will be keeping a close watch if it doesn't or more changes are desired.

  7. Log in to comment