【问题标题】:Custom entity lookup fails on PUT calls with ConversionFailedException自定义实体查找在 PUT 调用中失败并出现 ConversionFailedException
【发布时间】:2019-02-12 13:59:16
【问题描述】:

我有一个与this question 非常相似的问题,但不完全一样。我想使用基于字符串的外部 id,所以设置自定义 EntityLookup 配置,如 the documentation

这对GETPOSTDELETE 非常有效,但PUT 失败并显示ConversionFailedException

我可以使用以下最小配置重现错误,以使用 username 作为要查找的字段:

用户.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]

【问题讨论】:

    标签: spring spring-data spring-data-rest


    【解决方案1】:

    这绝对是一个错误。

    这是因为PUT repository/{id} 端点也可用于创建具有给定 ID 的新实体。 因此,在 PUT 请求期间,它会尝试将 URL 中的 id 放入对象的 id 属性中。但是 - 因为你有一个唯一的 EntityLookup - URL 片段不是实体的 id 属性......

    看来作者只是忘记处理这个案子了。当我在寻找源代码时,我看不到任何简单的解决方法。

    我认为 PATCH 请求仍然有效,因此如果您可以避免使用 PUT 请求,那么这可能是一个解决方案。

    我个人不喜欢整个 EntityLookup 功能。 (事实证明:听起来不错,但不起作用:))我认为 URL 的 id 片段应该是实体的实际 id。 也许它不违反 REST 原则,但我仍然觉得它不合适。

    相反,如果您想通过用户名获取用户,您可以随时使用 users/search/findByUsername 端点,之后如果您想通过 PUT 请求修改对象,您将在响应中包含 _self 链接稍后。

    【讨论】:

    • 事实上,我确实解决了这个问题,不再使用自定义实体查找。我还提交了一个还没有活动的错误,但如果有人想关注它,这里是:jira.spring.io/browse/DATAREST-1343
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    相关资源
    最近更新 更多