Я пытаюсь сохранить Kotlin (v1.3.61) встроенный класс в MongoDB, используя Spring Data MongoDB (2.2.3-RELEASE), но пока безуспешно. Это настройка:
inline class UserId(@NotBlank val id: String)
и
@Document(collection = "data")
class Data(
@Field("uid")
val userId: UserId
)
Spring создает следующее исключение при создании bean-компонентов:
Причина: java .lang.ArrayIndexOutOfBoundsException: 1 at org.springframework.data.mapping.model.PreferredConstructorDiscoverer $ Discoverers.buildPreferredConstructor (PreferredConstructorDiscoverer. java: 221) ~ [spring-data-commELE-2.2.3.jar-2.2.3j. 2.2.3j. 2.2.3j. 2.2.3j. 2.2.3 .RELEASE] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer $ Discoverers.access $ 200 (PreferredConstructorDiscoverer. java: 89) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE ] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer $ Discoverers $ 2.lambda $ Discover $ 0 (PreferredConstructorDiscoverer. java: 161) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3. RELEASE] в java .util.stream.ReferencePipeline $ 3 $ 1.accept (ReferencePipeline. java: 193) ~ [na: 1.8.0_171] в java .util.Spliterators $ ArraySpliterator.tryAdvance (Spliterators. * 1047) *: 958) ~ [na: 1.8.0_171] в java .util.stream.ReferencePipeline.forEachWithCancel (ReferencePipeline. java: 126) ~ [na: 1.8.0_171] в java .util.stream.AbstractPipeline.copyIntoWithCancel (AbstractPipeline. java: 498) ~ [na: 1.8.0_171] в java .util.stream.AbstractPipeline.copyInto (AbstractPipeline. java: 485) ~ [na: 1.8.0_171] в java .util.stream.AbstractPipeline.wrapAndCopyInto ( AbstractPipeline. java: 471) ~ [na: 1.8.0_171] в java .util.stream.FindOps $ FindOp.evaluateSequential (FindOps. java: 152) ~ [na: 1.8.0_171] в java .util.stream.AbstractPipeline.evaluate (AbstractPipeline. java: 234) ~ [na: 1.8.0_171] в java .util.stream.ReferencePipeline.findFirst (ReferencePipeline. java: 464) ~ [na : 1.8.0_171] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer $ Discoverers $ 2.discover (PreferredConstructorDiscoverer. java: 164) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3 .RELEASE] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer.discover (PreferredConstructorDiscoverer. java: 77) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE] в org.springframework.data.mapping.model.BasicPersistentEntity. (BasicPersistentEntity. java: 105) ~ [spring-data- commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE] в org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity. (BasicMongoPersistentEntity. java: 74) ~ [spring-data-mongodb-2.2. 3.RELEASE.jar: 2.2.3.RELEASE] at org.springframework.data.mongodb.core.mapping.MongoMappingContext.createPersistentEntity (MongoMappingContext. java: 91) ~ [spring-data-mongodb-2.2.3.RELEASE .jar: 2.2.3.RELEASE] at org.springframework.data.mongodb.core.mapping.MongoMappingContext.createPersistentEntity (MongoMappingContext. java: 39) ~ [spring-data-mongodb-2.2.3.RELEASE.jar: 2.2.3.RELEASE] at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity (AbstractMappingContext. java: 357) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE ] at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity (A bstractMappingContext. java: 323) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE] в java .lang.Iterable.forEach (Iterable. java: 75) ~ [na: 1.8.0_171] at org.springframework.data.mapping.context.AbstractMappingContext.initialize (AbstractMappingContext. java: 452) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3. RELEASE] at org.springframework.data.mapping.context.AbstractMappingContext.afterPropertiesSet (AbstractMappingContext. java: 444) ~ [spring-data-commons-2.2.3.RELEASE.jar: 2.2.3.RELEASE] в org. springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods (AbstractAutowireCapableBeanFactory. java: 1855) ~ [spring-beans-5.2.2.RELEASE. jar: 5.2.2.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean (AbstractAutowireCapableBeanFactory. java: 1792) ~ [spring-beans-5.2.2.RELEAS. ] ... 151 общие кадры опущены
Трассировка стека довольно неясна, но исключение происходит в PreferredConstructorDiscoverer
, а userId
является частью конструктора, поэтому проблема может быть там найдена .
Следующей проверкой был байтовый код класса Data
:
// ================net/test/Data.class
================= // class version 50.0 (50) // access flags 0x31
public final class net/test/Data {
@Lorg/springframework/data/mongodb/core/mapping/Document;(collection="data")
// access flags 0x12 private final Ljava/lang/String; userId @Lorg/springframework/data/mongodb/core/mapping/Field;(value="uid") @Lorg/jetbrains/annotations/NotNull;() // invisible
// access flags 0x11 public final getUserId()Ljava/lang/String; @Lorg/jetbrains/annotations/NotNull;() // invisible L0
LINENUMBER 10 L0
ALOAD 0
GETFIELD net/test/Data.userId : Ljava/lang/String;
ARETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x2 private <init>(Ljava/lang/String;)V L0
LINENUMBER 7 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
ALOAD 0
ALOAD 1
PUTFIELD net/test/Data.userId : Ljava/lang/String;
RETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
LOCALVARIABLE userId Ljava/lang/String; L0 L1 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1001 public synthetic <init>(Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
// annotable parameter count: 2 (visible)
// annotable parameter count: 2 (invisible) L0
LINENUMBER 7 L0
ALOAD 0
ALOAD 1
INVOKESPECIAL net/test/Data.<init> (Ljava/lang/String;)V
RETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
LOCALVARIABLE userId Ljava/lang/String; L0 L1 1
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 2
MAXSTACK = 2
MAXLOCALS = 3
@Lkotlin/Metadata;(mv={1, 1, 16}, bv={1, 0, 3}, k=1, d1={"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\u0008\u0005\u0008\u0007\u0018\u00002\u00020\u0001B\u0010\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u00f8\u0001\u0000\u00a2\u0006\u0002\u0010\u0004R\u001b\u0010\u0002\u001a\u00020\u00038\u0006X\u0087\u0004\u00f8\u0001\u0000\u00a2\u0006\n\n\u0002\u0010\u0007\u001a\u0004\u0008\u0005\u0010\u0006\u0082\u0002\u0004\n\u0002\u0008\u0019\u00a8\u0006\u0008"}, d2={"Lnet/test/Data;", "", "userId", "Lnet/test/UserId;", "(Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V", "getUserId", "()Ljava/lang/String;", "Ljava/lang/String;", "core"}) // compiled from: Data.kt }
// ================META-INF/core.kotlin_module =================
, и это соответствующая строка 221 PreferredConstructorDiscoverer
из источника Spring:
String name = parameterNames == null ? null : parameterNames[i];
Я полный нуб в понимаемом байт-коде, но тот или другой может сразу увидеть проблему.
Еще кое-что, что я пробовал, - реализация двух пользовательских преобразователей типа * 1029. * и наоборот. Однако создание экземпляра bean-компонента происходит до того, как может произойти какое-либо преобразование, поэтому это не имеет значения.
Я знаю, что встроенные классы все еще экспериментальны в Kotlin 1.3, но, возможно, реальная проблема лежит где-то еще. У кого-нибудь есть идея?
Кстати, при смене типа с UserId
на String
все работает нормально.