Skip to content

Commit

Permalink
978 dataentry aggregate snapshot failed to restore aggregateidentifier (
Browse files Browse the repository at this point in the history
#980)

* Add serialization test for data entry aggregate #978

* Allow serialization of private fields for data entry aggregate #978

* minor additions

---------

Co-authored-by: Simon Zambrovski <simon.zambrovski@holisticon.de>
  • Loading branch information
p-wunderlich and zambrovski authored Apr 26, 2024
1 parent 5ff3520 commit eaa3d63
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.holunda.polyflow.bus.jackson

import com.fasterxml.jackson.annotation.JsonAutoDetect

/**
* Allow serialization of all fields. (Also private fields!)
*/
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
class JsonAutoDetectAnyVisibility
3 changes: 1 addition & 2 deletions core/datapool/datapool-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@
<artifactId>dom4j</artifactId>
<version>2.1.4</version>
</dependency>

<dependency>
<groupId>io.holunda.polyflow</groupId>
<artifactId>polyflow-bus-jackson</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.holunda.polyflow.datapool.core

import com.fasterxml.jackson.databind.ObjectMapper
import io.holunda.polyflow.bus.jackson.JsonAutoDetectAnyVisibility
import io.holunda.polyflow.datapool.core.business.CreateOrUpdateCommandHandler
import io.holunda.polyflow.datapool.core.business.DataEntryAggregate
import io.holunda.polyflow.datapool.core.business.upcaster.DataEntryCreatedEventUpcaster
Expand All @@ -13,6 +15,7 @@ import org.axonframework.eventsourcing.SnapshotTriggerDefinition
import org.axonframework.eventsourcing.Snapshotter
import org.axonframework.eventsourcing.eventstore.EventStore
import org.axonframework.messaging.annotation.ParameterResolverFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Bean
Expand Down Expand Up @@ -98,5 +101,15 @@ class DataPoolCoreAxonConfiguration {
*/
@Bean(DATA_ENTRY_CACHE)
fun dataEntryCache(): Cache = WeakReferenceCache()

@Autowired
fun configureJackson(objectMapper: ObjectMapper) {
objectMapper.configurePolyflowJacksonObjectMapperForDatapool()
}
}

fun ObjectMapper.configurePolyflowJacksonObjectMapperForDatapool(): ObjectMapper {
addMixIn(DataEntryAggregate::class.java, JsonAutoDetectAnyVisibility::class.java)
return this
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package io.holunda.polyflow.datapool.core.business

import com.fasterxml.jackson.databind.ObjectMapper
import io.holunda.camunda.taskpool.api.business.*
import io.holunda.polyflow.bus.jackson.JsonAutoDetectAnyVisibility
import io.holunda.polyflow.bus.jackson.configurePolyflowJacksonObjectMapper
import io.holunda.polyflow.datapool.core.DeletionStrategy
import io.holunda.polyflow.datapool.core.configurePolyflowJacksonObjectMapperForDatapool
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.axonframework.eventsourcing.AggregateDeletedException
import org.axonframework.test.aggregate.AggregateTestFixture
import org.camunda.bpm.engine.variable.Variables
Expand Down Expand Up @@ -353,5 +359,53 @@ class DataEntryAggregateTest {
)
}

@Test
fun `should serialize and deserialize an empty aggregate`() {
// GIVEN an object mapper and an empty aggregate
val objectMapper = ObjectMapper().configurePolyflowJacksonObjectMapper()
val dataEntryAggregate = DataEntryAggregate()

// WHEN we serialize and deserialize it
val serializedObj = objectMapper.writeValueAsString(dataEntryAggregate)
objectMapper.readValue(serializedObj, DataEntryAggregate::class.java)

// THEN no problem should occur
}

@Test
fun `should serialize and deserialize an aggregate with data`() {
// GIVEN an object mapper and a filled aggregate
val objectMapper = ObjectMapper()
.configurePolyflowJacksonObjectMapper()
.configurePolyflowJacksonObjectMapperForDatapool()

val dataEntryAggregate = DataEntryAggregate().apply {
on(
DataEntryCreatedEvent(
entryId = UUID.randomUUID().toString(),
entryType = "io.holunda.My",
name = "Some name",
type = "Another",
applicationName = "Different application",
)
)
}
val dataIdentityValue = dataEntryAggregate.getDataIdentityValueForTest()

// WHEN we serialize and deserialize it
val serializedObj = objectMapper.writeValueAsString(dataEntryAggregate)
val deserializedObj = objectMapper.readValue(serializedObj, DataEntryAggregate::class.java)

// THEN no problem should occur
assertThat(deserializedObj.getDataIdentityValueForTest()).isEqualTo(dataIdentityValue)
}

}

private fun DataEntryAggregate.getDataIdentityValueForTest(): String? {
return javaClass.getDeclaredField("dataIdentity").let {
it.isAccessible = true
val value = it.get(this) as String?
return@let value
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package io.holunda.polyflow.taskpool.core

import com.fasterxml.jackson.databind.ObjectMapper
import io.holunda.polyflow.bus.jackson.JsonAutoDetectAnyVisibility
import io.holunda.polyflow.taskpool.core.process.ProcessDefinitionAggregate
import io.holunda.polyflow.taskpool.core.process.ProcessInstanceAggregate
import io.holunda.polyflow.taskpool.core.task.TaskAggregate
import org.axonframework.common.caching.Cache
import org.axonframework.common.caching.WeakReferenceCache
import org.axonframework.eventsourcing.EventSourcingRepository
import org.axonframework.eventsourcing.eventstore.EventStore
import org.axonframework.messaging.annotation.ParameterResolverFactory
import org.axonframework.modelling.command.Aggregate
import org.axonframework.modelling.command.AggregateNotFoundException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
Expand All @@ -22,6 +27,7 @@ class TaskPoolCoreConfiguration {

companion object {
const val TASK_AGGREGATE_REPOSITORY = "taskAggregateRepository"
const val TASK_CACHE = "taskCache"
const val PROCESS_DEFINITION_AGGREGATE_REPOSITORY = "processDefinitionAggregateRepository"
const val PROCESS_INSTANCE_AGGREGATE_REPOSITORY = "processInstanceAggregateRepository"
}
Expand Down Expand Up @@ -62,6 +68,16 @@ class TaskPoolCoreConfiguration {
.build()
}

@Autowired
fun configureJackson(objectMapper: ObjectMapper) {
objectMapper.configurePolyflowJacksonObjectMapperForTaskPool()
}

/**
* Use weak reference cache.
*/
@Bean(TASK_CACHE)
fun taskCache(): Cache = WeakReferenceCache()
}

/**
Expand Down Expand Up @@ -89,3 +105,8 @@ fun <T> Optional<T>.ifPresentOrElse(presentConsumer: (T) -> Unit, missingCallbac
}
}

fun ObjectMapper.configurePolyflowJacksonObjectMapperForTaskPool(): ObjectMapper {
addMixIn(TaskAggregate::class.java, JsonAutoDetectAnyVisibility::class.java)
return this
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Component

/**
* This handler makes sure that an update of variables can be send without a create of the process instance..
* This handler makes sure that an update of variables can be sent without a create of the process instance.
*/
@Component
class ProcessInstanceVariablesChangeHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import org.axonframework.spring.stereotype.Aggregate
/**
* Main representation of the tasks available in the system.
*/
@Aggregate(repository = TaskPoolCoreConfiguration.TASK_AGGREGATE_REPOSITORY)
@Aggregate(
repository = TaskPoolCoreConfiguration.TASK_AGGREGATE_REPOSITORY,
cache = TaskPoolCoreConfiguration.TASK_CACHE,
)
class TaskAggregate() {

companion object : KLogging()
Expand Down

0 comments on commit eaa3d63

Please sign in to comment.