Исключение с использованием Spring данных JPA и QueryDsl через REST-контроллер

Я пытаюсь реализовать метод контроллера, подобный тому, который описан в последнем выпуске Гослинга Spring Data, который поддерживает QueryDsl. Я реализовал контроллер, как показано в примере в документации по адресу http://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type- безопасно Все компилируется и когда я запускаю приложение (используя Spring Boot 1.2.5.RELEASE), все запускается нормально.

Однако, когда я пытаюсь вызвать мою конечную точку отдыха, я всегда получаю следующее исключение:

org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mysema.query.types.Predicate]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)

Я думаю, что QuerydslPredicateArgumentResolver не применяется к запросу, и, следовательно, исключение. Но я вижу, что QuerydslPredicateArgumentResolver регистрируется как bean-компонент, когда я запрашиваю конечную точку /manage/beans Spring Boot. Я также гарантировал, что @EnableSpringDataWebSupport в моем классе @Configuration.

У меня есть контроллер, аннотированный @BasePathAwareController, так как я использую его с Spring Data REST и хочу, чтобы методы находились в пути, аналогичном тем, которые предоставляет Spring Data REST. Я также пытался использовать @RepositoryRestController, но это не имело значения. Однако при использовании @RestController и размещении его по пути, отличному от базового пути, который использует Spring Data REST, все работало. Итак, вопрос в том, должно ли это работать?

Весь контроллер прямо сейчас:

@RestController
@RequestMapping(value = "/query")
public class AvailController
{
    private final AvailRepository repo;

    @Autowired
    public AvailController(AvailRepository repository)
    {
        this.repo = repository;
    }

    @RequestMapping(value = "/avails", method = GET)
    public @ResponseBody Page<Avail> getAvails(Model model, 
               @QuerydslPredicate(root = Avail.class) Predicate predicate,
               Pageable pageable, 
               @RequestParam MultiValueMap<String, String> parameters)
    {
        return repo.findAll(predicate, pageable);
    }
}

Ответ 1

У меня была та же проблема с созданием Predicate. В примере:

@Controller
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
class UserController {

private final UserRepository repository;

@RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model, //
        @QuerydslPredicate(root = User.class) Predicate predicate, //
        @PageableDefault(sort = { "lastname", "firstname" }) Pageable pageable, //
        @RequestParam MultiValueMap<String, String> parameters) {
(...)

(https://github.com/spring-projects/spring-data-examples/blob/master/web/querydsl/src/main/java/example/users/web/UserController.java#L42) использует только @Controller, и я использовал @RepositoryRestController, это, по-видимому, причина. @RestController также работает для меня.

Я создал https://jira.spring.io/browse/DATAREST-838

Ответ 2

У меня также возникла эта проблема при попытке реализовать пользовательский контроллер, который имитирует возвращаемое значение как Spring Data REST. Я хотел ввести QuerydslPredicate в метод контроллера и получил раздражающее "BeanInstantiationException".

Я нашел для этого работу, добавив в приложение следующий файл конфигурации:

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE   )
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    @Qualifier("repositoryExporterHandlerAdapter")
    RequestMappingHandlerAdapter repositoryExporterHandlerAdapter;

    @Override
    public void addArgumentResolvers(
            List<HandlerMethodArgumentResolver> argumentResolvers) {
        List<HandlerMethodArgumentResolver> customArgumentResolvers = repositoryExporterHandlerAdapter.getCustomArgumentResolvers();
        argumentResolvers.addAll(customArgumentResolvers);
    }
}

См. здесь для справки: https://jira.spring.io/browse/DATAREST-657