Пользовательский поиск сущности завершается неудачно при вызовах PUT с помощью ConversionFailedException - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть проблема, очень похожая на этот вопрос , но не совсем.Я хочу использовать внешний идентификатор на основе строки, поэтому настройте пользовательскую конфигурацию EntityLookup, как в документации .

. Это прекрасно работает для GET, POST иDELETE, но PUT завершается неудачно с ConversionFailedException.

Я могу воспроизвести ошибку со следующей минимальной конфигурацией, чтобы использовать username в качестве поля для поиска:

User.java

@Entity
public class User {
    @Id
    private Long id;
    private String username;
    private String fullName;
}

UserRepo.java

@RepositoryRestResource(exported = true)
public interface UserRepo extends PagingAndSortingRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

SpringDataRestCustomization.java

public class SpringDataRestCustomization implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.withEntityLookup()
        .forRepository(UserRepo.class, User::getUsername, UserRepo::findByUsername);
    }
}

Затем я могу POST новые записи и получать их через GET /users/username, но PUT для существующего ресурса выдает следующую ошибку:

o.s.d.r.w.RepositoryRestExceptionHandler : Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'username'; nested exception is java.lang.NumberFormatException: For input string: "username"

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'username'; nested exception is java.lang.NumberFormatException: For input string: "username"
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:46) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.data.mapping.model.ConvertingPropertyAccessor.convertIfNecessary(ConvertingPropertyAccessor.java:123) ~[spring-data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE]
    at org.springframework.data.mapping.model.ConvertingPropertyAccessor.setProperty(ConvertingPropertyAccessor.java:61) ~[spring-data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE]
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.lambda$resolveArgument$3(PersistentEntityResourceHandlerMethodArgumentResolver.java:149) ~[spring-data-rest-webmvc-3.1.4.RELEASE.jar:3.1.4.RELEASE]
    at java.base/java.util.Optional.ifPresent(Optional.java:183) ~[na:na]
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.resolveArgument(PersistentEntityResourceHandlerMethodArgumentResolver.java:146) ~[spring-data-rest-webmvc-3.1.4.RELEASE.jar:3.1.4.RELEASE]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]

1 Ответ

0 голосов
/ 22 февраля 2019

Это определенно ошибка.

Это происходит потому, что конечную точку PUT repository/{id} можно использовать также для создания новой сущности с заданным идентификатором.И по этой причине во время запроса PUT он пытается поместить идентификатор из URL в свойство id объекта.Но - поскольку у вас есть уникальный EntityLookup - фрагмент URL НЕ является id-свойством объекта ...

Кажется, автор просто забыл разобраться с этим случаем.И пока я искал источник, я не вижу никакого простого обходного пути.

Я думаю, что запросы PATCH будут по-прежнему работать, поэтому, если вы можете избежать использования запросов PUT, это может быть решением.

Мне лично не нравится вся эта функция EntityLookup.(И, как оказалось: звучит хорошо, не работает :)) Я думаю, что фрагмент идентификатора URL должен быть фактическим идентификатором объекта. Возможно, это не нарушает принципы REST, но я все еще не считаю это целесообразным.

Вместо этого вы можете использовать конечную точку users / search / findByUsername в любое время, если хотите извлечьпользователь по имени пользователя, и после этого у вас будет ссылка _self в ответе, если вы позже захотите изменить объект с помощью запроса PUT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...