Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in saving an entity that has a HashSet field when the @EnableReactiveMongoAuditing annotation is active. #39820

Closed
mahdibohloul opened this issue Mar 2, 2024 · 1 comment
Labels
for: external-project For an external project and not something we can fix

Comments

@mahdibohloul
Copy link

I have defined a Kotlin class that contains a field such as Map<Enum, HashSet<Something>> and I can save it in the database. Now when I use the @EnableReactiveMongoAuditing annotation, I encounter the following error:

java.lang.reflect.InaccessibleObjectException: Unable to make field private transient java.util.HashMap java.util.HashSet.map accessible: module java.base does not "opens java.util" to unnamed module @661972b0
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na]
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na]
	at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178) ~[na:na]
	at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) ~[na:na]
	at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:804) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:540) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:728) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity(AbstractMappingContext.java:426) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:383) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:279) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:293) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mongodb.core.mapping.MongoMappingContext.getPersistentEntity(MongoMappingContext.java:132) ~[spring-data-mongodb-4.2.3.jar:4.2.3]
	at org.springframework.data.mongodb.core.mapping.MongoMappingContext.getPersistentEntity(MongoMappingContext.java:41) ~[spring-data-mongodb-4.2.3.jar:4.2.3]
	at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:147) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.lambda$from$2(PersistentPropertyPathFactory.java:259) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:298) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:264) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.lambda$from$2(PersistentPropertyPathFactory.java:260) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:298) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:264) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:235) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:166) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.AbstractMappingContext.doFindPersistentPropertyPaths(AbstractMappingContext.java:333) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.AbstractMappingContext.findPersistentPropertyPaths(AbstractMappingContext.java:317) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingAuditingMetadata.findPropertyPaths(MappingAuditableBeanWrapperFactory.java:150) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingAuditingMetadata.<init>(MappingAuditableBeanWrapperFactory.java:124) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$getBeanWrapperFor$0(MappingAuditableBeanWrapperFactory.java:85) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$getBeanWrapperFor$1(MappingAuditableBeanWrapperFactory.java:84) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.context.PersistentEntities.lambda$mapOnContext$2(PersistentEntities.java:144) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
	at java.base/java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:1002) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647) ~[na:na]
	at org.springframework.data.mapping.context.PersistentEntities.mapOnContext(PersistentEntities.java:145) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$getBeanWrapperFor$3(MappingAuditableBeanWrapperFactory.java:82) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at java.base/java.util.Optional.flatMap(Optional.java:289) ~[na:na]
	at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.getBeanWrapperFor(MappingAuditableBeanWrapperFactory.java:76) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.AuditingHandlerSupport.isAuditable(AuditingHandlerSupport.java:101) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler.markAudited(ReactiveIsNewAwareAuditingHandler.java:71) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback.onBeforeConvert(ReactiveAuditingEntityCallback.java:52) ~[spring-data-mongodb-4.2.3.jar:4.2.3]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:281) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.data.mapping.callback.EntityCallbackDiscoverer.lambda$computeCallbackInvokerFunction$1(EntityCallbackDiscoverer.java:258) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.callback.DefaultReactiveEntityCallbacks$DefaultReactiveEntityCallbackInvoker.invokeCallback(DefaultReactiveEntityCallbacks.java:110) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at org.springframework.data.mapping.callback.DefaultReactiveEntityCallbacks.lambda$callback$1(DefaultReactiveEntityCallbacks.java:91) ~[spring-data-commons-3.2.3.jar:3.2.3]
	at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:153) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:63) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:165) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:210) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2571) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.request(MonoFlatMap.java:194) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:171) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.request(MonoFlatMap.java:194) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.request(MonoFlatMap.java:194) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.request(FluxUsingWhen.java:322) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.request(FluxPeekFuseable.java:783) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.BlockingSingleSubscriber.onSubscribe(BlockingSingleSubscriber.java:53) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onSubscribe(FluxPeekFuseable.java:816) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onSubscribe(FluxUsingWhen.java:411) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:117) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:117) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:117) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.MonoUsingWhen.subscribe(MonoUsingWhen.java:87) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4563) ~[reactor-core-3.6.3.jar:3.6.3]
	at reactor.core.publisher.Mono.block(Mono.java:1778) ~[reactor-core-3.6.3.jar:3.6.3]
	at cab.tapsi.springmongotest.ApplicationRunner.run(ApplicationRunner.kt:44) ~[main/:na]
	at org.springframework.boot.SpringApplication.lambda$callRunner$5(SpringApplication.java:790) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88) ~[spring-core-6.1.4.jar:6.1.4]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:789) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774) ~[spring-boot-3.2.3.jar:3.2.3]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.3.jar:3.2.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.3.jar:3.2.3]
	at cab.tapsi.springmongotest.SpringMongoTestApplicationKt.main(SpringMongoTestApplication.kt:15) ~[main/:an]

The classes are defined as follows:

@Document(collection = "stores")
data class Store(
  @Id val id: String? = null,
  @Indexed(unique = true) val slug: String,
  @Indexed(unique = true) val ownerId: String,
  val name: String,
  val preferences: StorePreferences,
  @CreatedDate val createdTimestamp: Timestamp? = null,
  @LastModifiedDate val updatedTimestamp: Timestamp? = null,
)


data class StorePreferences(
  val workingTimeslots: Map<DayOfWeek, HashSet<TimeslotOffset>> = emptyMap(),
  val processingDurationInSeconds: Long = 0,
)

data class TimeslotOffset(
  val startOffset: Long,
  val endOffset: Long,
)

Also, in this link, I have created a project where you can reproduce the error. Also, you can see the correct way of working by removing the @EnableReactiveMongoAuditing annotation.

This problem arose after upgrading Spring Boot from version 2.5.X to version 3.2.3.
Java version:

openjdk version "17.0.9" 2023-10-17
OpenJDK Runtime Environment (build 17.0.9+9-Ubuntu-122.04)
OpenJDK 64-Bit Server VM (build 17.0.9+9-Ubuntu-122.04, mixed mode, sharing)
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 2, 2024
@scottfrederick
Copy link
Contributor

@mahdibohloul It does not appear that Spring Boot is involved in this error, but that it is an issue for Spring Data MongoDB. There is a similar issue in the Spring Data MongoDB repository that was closed due to inactivity. A work-around suggested there is to provide an --add-opens option to the JVM, and that suggestion does allow your sample to get past the error. To test this, run your sample with:

java --add-opens java.base/java.util=ALL-UNNAMED -jar build/libs/spring-mongo-test-0.0.1-SNAPSHOT.jar

For additional help, please comment on the Spring Data MongoDB issue or open a new issue in that project's repository.

@scottfrederick scottfrederick closed this as not planned Won't fix, can't repro, duplicate, stale Mar 26, 2024
@scottfrederick scottfrederick added for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

3 participants