[Axon 3.3.2] Working example for the DeadlineManager API with Quartz ?

Hi,

Would you have some working example for the DeadlineManager with Quartz and Spring Boot 2 ? It seems the documentation is not up to date yet.

What I managed to do so far is to configure the Deadline manager as following :

@Bean public DeadlineManager deadlineManager(Scheduler scheduler, AxonConfiguration configuration, SpringTransactionManager transactionManager, ObjectMapper objectMapper) { return new QuartzDeadlineManager(scheduler, new ConfigurationScopeAwareProvider(configuration), transactionManager, eventSerializer(objectMapper)); }

At that point, I’m able to inject it in a Saga for example. The scheduling part seems to work as well, but troubles come when the DeadlineManager tries to deserialize the GenericDeadlineMessage.
I tested with the default serializer and also with Jackson.

This is how I try to schedule and listen to the deadline message :

`
@Saga
public class TestDeadlineManagerSaga {

@Inject
private transient CommandGateway commandGateway;

@Inject
private transient DeadlineManager deadlineManager;

@StartSaga
@SagaEventHandler(associationProperty = “testId”)
public void on(TestEvent event) {

deadlineManager.schedule(Duration.ofSeconds(20), “test-deadline”);
}

@DeadlineHandler(deadlineName = “test-deadline”)
public void onDeadline() {
System.out.println(“deadline reached !”);
}

}
`

The stack trace I got after 20 seconds :

With Jackson : https://gist.github.com/faulomi/95dc06b12e0c4d738758f63610b80fe2
With XStream : https://gist.github.com/faulomi/191f9ed385db4f78f3e410f9bbd2842a

FYI, I’m using Axon 3.3.2 with Spring 2.0.3, and I included the spring boot Quartz starter.

This is my Quartz configuration, with Postgres :

`
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

`

Am I missing something obvious ?

Thank you for your help,

Jerome

Hi Jérôme,

We have been noticing gaps in our documentation since release 3.1. As such we are hard at work to update our documentation accordingly, but that of course starts with getting it up to date for Axon Framework 3.1. As you likely know the DeadlineManager is a feature of 3.3, at which we’ve not arrived yet from a reference-guide-update perspective. So example code will follow, it’ll just need a little more time.

The snippets you are sharing show of the correct creation and usage of the DeadlineManager. We (me to be exact) however made a shortcut when serializing the deadline message in the manager, which is now causing deserialization issues when using the JacksonSerializer. I have created this tracking the work to be done to solve this. Working on it ASAP, so you can expect a fix soon.

I have introduced some tests to test the serialization of a DeadlineMessage with Java, XStream and Jackson serialization. Only Jackson de-/serialization is failing in my scenario for some reason. Investigating the XStream strack trace snippet you’ve shared suggests it has something to do with the MetaData entries. Thus I expanded my tests to test a null, empty and filled metadata scenario when serializing the metadata of a DeadlineMessage with the XStreamSerializer. This still worked in my scenario however, so I am not sure why it is failing in your scenario.

Concluding, I understand why the DeadlineManager set up doesn’t work when using the JacksonSerializer. Working on a fix as we speak. Why the XStreamSerializer doesn’t cut it isn’t entirely clear to me though. Have you checked what metadata entries are being serialized during the deadlineManager.schedule() call? Maybe we can find something obvious in there.

I’ll keep you posted on the fix Jérôme!

Cheers,
Steven

Hi Steven,

Thank you again for the fast feedback ! No problem for the documentation, I understand that it represents a lot of work, especially with all the new features brought in by the two latest releases :wink: !

As suggested, I added a breakpoint at DeadlineJob line 170 to check the XML representation of the serialized deadline message. Here is what I get :

<org.axonframework.deadline.GenericDeadlineMessage><delegate class="org.axonframework.messaging.GenericMessage"><identifier>93ad55eb-a002-486a-81d8-c04aaa7c117b</identifier><metaData><entry><string>traceId</string><string>a3c6f2ad-ac50-48a5-80cf-8b2e939df036</string></entry><entry><string>correlationId</string><string>d4c43b0b-b9a4-4236-8206-58d83da3b29e</string></entry></metaData><payloadType>java.lang.Void</payloadType></delegate><timestampSupplier class="org.axonframework.serialization.CachingSupplier" serialization="custom"><org.axonframework.serialization.CachingSupplier><default><value><value class="instant">2018-07-23T14:11:14.511Z</value></value></default></org.axonframework.serialization.CachingSupplier></timestampSupplier><deadlineName>test</deadlineName></org.axonframework.deadline.GenericDeadlineMessage>

So as far as I can see, I have the default metadata (correlationId and traceId) but I still don’t get why XStream is not able to deserialize this correctly.

Hope it helps you to identify the root cause !

Best Regards,
Jerome

Hi Steven,

Just to confirm, did you try to reproduce the XStream issue with Spring Boot 1.5 or Spring Boot 2.0 ? And also, what’s your version of XStream (1.4.10 in my case) ?

Cheers,
Jerome

Hi Steven,

I found the issue. When declaring the QuartzDeadlineManager, one has to pass the default serializer configured by Axon :

@Bean public DeadlineManager deadlineManager(Scheduler scheduler, AxonConfiguration configuration, SpringTransactionManager transactionManager, Serializer serializer) { return new QuartzDeadlineManager(scheduler, new ConfigurationScopeAwareProvider(configuration), transactionManager, serializer); }

So I think the implementation of the constructor without the serializer should be modified to get this default serializer instead of instantiating a fresh XStreamSerializer() (with which you get the aforementioned exception).

Cheers,
Jerome

Hi Jérôme,

I have made the necessary adjustments in the QuartzDeadlineManager to de-/serialize the DeadlineMessage in a more sustainable method then we were initially doing. The work for that can be found here.

This fix is slated for 3.3.3, so from that point in your should be able to use the JacksonSerializer for the QuartzDeadlineManager.

To answer the testing question: I tested with the versions present in the Axon Framework project at the moment.

So for Spring Boot that’s 1.5.7.RELEASE and for XStream that is 1.4.10.

Additionally, I did not manage to reproduce the issue you encountered whilst deserializing the DeadlineMessage with XStream.
I focused on fixing the JacksonSerializer usage in the ticket shared.

For your last reply, I understand that providing the default Spring bean in the QuartzDeadlineManager sounds more than reasonable.

However, Axon Framework is intended to be usable without the use of Spring as well, so enforcing the default XStreamSerializer from the Spring Boot configuration to be used everywhere isn’t that easily achieved.

Additionally, the provision of a new XStreamSerializer() like is done at this point is how we are doing things in a multitude of areas.
Thus, on face value I would expect things to break more often because of this.

Checking what the ‘default XStreamSerializer’ is when using the axon-spring-boot-autoconfigure we can see the following:

XStreamSerializer xStreamSerializer = new XStreamSerializer(revisionResolver);
xStreamSerializer.getXStream().setClassLoader(beanClassLoader);
return xStreamSerializer;

Would you mind testing whether your QuartzDeadlineManager works as expected if you provide it an serializer like I just described?

I am wondering whether I should pursue this bit further, hence why I am requesting this of you.

Concluding, Jackson serialization will be fixed, so stay tuned for that.

And, if you could provide the requested test result, that would be very much appreciated!

Cheers,
Steven