В приложении SpringBoot у меня следующая конфигурация:
axon:
axonserver:
servers: "${AXON_SERVER:localhost}"
serializer:
general: jackson
messages: jackson
events: jackson
logging.level:
org.axonframework.modelling.saga: debug
Уменьшение размера сценария до минимума, соответствующая часть класса Saga:
@Slf4j
@Saga
@ProcessingGroup("AuctionEventManager")
public class AuctionEventManagerSaga {
@Autowired
private transient EventScheduler eventScheduler;
private ScheduleToken scheduleToken;
private Instant auctionTimerStart;
@StartSaga
@SagaEventHandler(associationProperty = "auctionEventId")
protected void on(final AuctionEventScheduled event) {
this.auctionTimerStart = event.getTimerStart();
// Cancel any pre-existing previous job, since the scheduling thread might be lost upon a crash/restart of JVM.
if (this.scheduleToken != null) {
this.eventScheduler.cancelSchedule(this.scheduleToken);
}
this.scheduleToken = this.eventScheduler.schedule(
this.auctionTimerStart,
AuctionEventStarted.builder()
.auctionEventId(event.getAuctionEventId())
.build()
);
}
@EndSaga
@SagaEventHandler(associationProperty = "auctionEventId")
protected void on(final AuctionEventStarted event) {
log.info(
"[AuctionEventManagerSaga] Current state: {scheduleToken={}, auctionTimerStart={}}",
this.scheduleToken,
this.auctionTimerStart
);
}
}
В конечном скомпилированном классе у нас будет 4 свойства: log
(из @Slf4j
), eventScheduler
(переходный, @Autowired
), scheduleToken
и auctionTimerStart
.
Для справочной информации вот пример общего подхода, который я использовал для классов Command и Event:
@Value
@Builder
@JsonDeserialize(builder = AuctionEventStarted.AuctionEventStartedBuilder.class)
public class AuctionEventStarted {
AuctionEventId auctionEventId;
@JsonPOJOBuilder(withPrefix = "")
public static final class AuctionEventStartedBuilder {}
}
При выполнении кода вы получите следующий результат:
2020-05-12 15:40:01.180 DEBUG 1 --- [mandProcessor-4] o.a.m.saga.repository.jpa.JpaSagaStore : Updating saga id c8aff7f7-d47f-4616-8a96-a40044cb7e3b as {}
Как только общий сериализатор изменяется на xstream
, содержимое сериализуется правильно, но я сталкиваюсь с другой проблемой во время десериализации, поскольку у меня есть классы private static final class
Builder, использующие Lombok.
Итак, есть ли у Axon способ справиться с этими сценариями:
1- Axon для безопасного управления Джексоном, чтобы игнорировать @Autowired
, переходные и статические свойства из @Saga
классов? Я попытался вручную определить @JsonIgnore
в негосударственных свойствах, но это все равно не сработало.
2- Axon для безопасной настройки XStream для игнорирования внутренних классов (в основном классов Builder, реализованных как частный статический финал)?
Заранее спасибо,
РЕДАКТИРОВАТЬ: Я ищу решение, используя предпочитаемый мной сериализатор: JSON. Я попытался изменить класс саги и расширить JsonSerializer<AuctionEventManagerSaga>
. Для этого я реализовал методы:
@Override
public Class<AuctionEventManagerSaga> handledType() {
return AuctionEventManagerSaga.class;
}
@Override
public void serialize(
final AuctionEventManagerSaga value,
final JsonGenerator gen,
final SerializerProvider serializers
) throws IOException {
gen.writeStartObject();
gen.writeObjectField("scheduleToken", value.eventScheduler);
gen.writeObjectField("auctionTimerStart", value.auctionTimerStart);
gen.writeEndObject();
}
Прямо сейчас у меня что-то сериализуется, но это не имеет ничего общего с определенными мною свойствами:
2020-05-12 16:20:01.322 DEBUG 1 --- [mandProcessor-0] o.a.m.saga.repository.jpa.JpaSagaStore : Storing saga id c4b5d94c-7251-40a5-accf-332768b1cacd as {"delegatee":null,"unwrappingSerializer":false}
РЕДАКТИРОВАТЬ 2. Решил подробнее рассказать о проблеме, с которой я сталкиваюсь, когда переключаю общий режим на использование XStream (хотя это несколько не связано с основной проблемой, описанной в заголовке).
Вот проблема, на которую он мне жалуется:
2020-05-12 17:08:06.495 DEBUG 1 --- [ault-executor-0] o.a.a.c.command.AxonServerCommandBus : Received command response [message_identifier: "79631ffb-9a87-4224-bed3-a957730dced7"
error_code: "AXONIQ-4002"
error_message {
message: "No converter available\n---- Debugging information ----\nmessage : No converter available\ntype : jdk.internal.misc.InnocuousThread\nconverter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter\nmessage[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not \"opens jdk.internal.misc\" to unnamed module @7728643a\n-------------------------------"
location: "1@600b5b87a922"
details: "No converter available\n---- Debugging information ----\nmessage : No converter available\ntype : jdk.internal.misc.InnocuousThread\nconverter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter\nmessage[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not \"opens jdk.internal.misc\" to unnamed module @7728643a\n-------------------------------"
}
request_identifier: "2f7020b1-f655-4649-bbe0-d6f458b3c2f3"
]
2020-05-12 17:08:06.505 WARN 1 --- [ault-executor-0] o.a.c.gateway.DefaultCommandGateway : Command 'ACommandClassDispatchedFromSaga' resulted in org.axonframework.commandhandling.CommandExecutionException(No converter available
---- Debugging information ----
message : No converter available
type : jdk.internal.misc.InnocuousThread
converter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
message[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not "opens jdk.internal.misc" to unnamed module @7728643a
-------------------------------)
Все еще не повезло с решением этой проблемы ...