Skip to content

Commit

Permalink
Return XStreamSerializer default, but log warnings
Browse files Browse the repository at this point in the history
To not give a breaking change to users, we return the XStreamSerializer.
 Whenever the default is used though, we throw a warning stating the
 users should set the security context consciously.

#1917
  • Loading branch information
smcvb committed Oct 1, 2021
1 parent 00326c8 commit 4b042e9
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@
import org.axonframework.messaging.MetaData;
import org.axonframework.serialization.SerializedObject;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutionException;
Expand All @@ -57,6 +61,8 @@
*/
public class AxonServerEventScheduler implements EventScheduler {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final long requestTimeout;
private final Serializer serializer;
private final AxonServerConnectionManager axonServerConnectionManager;
Expand Down Expand Up @@ -301,7 +307,16 @@ public AxonServerEventScheduler build() {
}

protected void validate() throws AxonConfigurationException {
assertNonNull(serializer, "The Serializer is a hard requirement and should be provided");
if (serializer == null) {
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
serializer = XStreamSerializer::defaultSerializer;
}
assertNonNull(axonServerConnectionManager,
"The AxonServerConnectionManager is a hard requirement and should be provided");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,29 @@ public AxonServerEventStore build() {
}

private void buildStorageEngine() {
if (snapshotSerializer == null) {
logger.warn(
"The default XStreamSerializer is used for events, whereas it is strongly recommended to"
+ " configure the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used for events,"
+ " without specifying the security context"
)
);
snapshotSerializer = XStreamSerializer::defaultSerializer;
}
if (eventSerializer == null) {
logger.warn(
"The default XStreamSerializer is used for snapshots, whereas it is strongly recommended to "
+ "configure the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used for snapshots,"
+ " without specifying the security context"
)
);
eventSerializer = XStreamSerializer::defaultSerializer;
}

assertNonNull(configuration, "The AxonServerConfiguration is a hard requirement and should be provided");
assertNonNull(axonServerConnectionManager,
"The PlatformConnectionManager is a hard requirement and should be provided");
Expand Down
2 changes: 1 addition & 1 deletion axon-server-connector/src/test/resources/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ logger.axon.appenderRefs = stdout
logger.axon.appenderRef.stdout.ref = STDOUT

logger.axon-server-connector.name = org.axonframework.axonserver
logger.axon-server-connector.level = ERROR
logger.axon-server-connector.level = WARN

logger.asc-event-processor-service.name = org.axonframework.axonserver.connector.processor.EventProcessorControlService
logger.asc-event-processor-service.level = OFF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.upcasting.event.EventUpcaster;
import org.axonframework.serialization.upcasting.event.NoOpEventUpcaster;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
Expand All @@ -50,6 +54,8 @@
*/
public abstract class AbstractEventStorageEngine implements EventStorageEngine {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final Serializer snapshotSerializer;
protected final EventUpcaster upcasterChain;
private final PersistenceExceptionResolver persistenceExceptionResolver;
Expand Down Expand Up @@ -348,8 +354,28 @@ public Builder snapshotFilter(SnapshotFilter snapshotFilter) {
* specifications
*/
protected void validate() throws AxonConfigurationException {
assertNonNull(snapshotSerializer, "The snapshot Serializer is a hard requirement and should be provided");
assertNonNull(eventSerializer, "The event Serializer is a hard requirement and should be provided");
if (snapshotSerializer == null) {
logger.warn(
"The default XStreamSerializer is used for events, whereas it is strongly recommended to"
+ " configure the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used for events,"
+ " without specifying the security context"
)
);
snapshotSerializer = XStreamSerializer::defaultSerializer;
}
if (eventSerializer == null) {
logger.warn(
"The default XStreamSerializer is used for snapshots, whereas it is strongly recommended to "
+ "configure the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used for snapshots,"
+ " without specifying the security context"
)
);
eventSerializer = XStreamSerializer::defaultSerializer;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import org.axonframework.eventhandling.TrackingEventStream;
import org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngineTest;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.axonframework.eventsourcing.utils.TestSerializer;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.UnknownSerializedType;
import org.axonframework.serialization.upcasting.event.NoOpEventUpcaster;
Expand Down Expand Up @@ -212,7 +211,7 @@ void testUnknownSerializedTypeCausesException() {
@SuppressWarnings({"JpaQlInspection", "OptionalGetWithoutIsPresent"})
@DirtiesContext
void testStoreEventsWithCustomEntity() {
XStreamSerializer serializer = TestSerializer.xStreamSerializer();
XStreamSerializer serializer = xStreamSerializer();
JpaEventStorageEngine.Builder jpaEventStorageEngineBuilder =
JpaEventStorageEngine.builder()
.snapshotSerializer(serializer)
Expand Down
39 changes: 39 additions & 0 deletions eventsourcing/src/test/resources/log4j2.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Copyright (c) 2010-2020. Axon Framework
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

name=AxonTestConfiguration
appenders = console

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d [%t] %-5p %-30.30c{1} %x - %m%n

rootLogger.level = info
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT

logger.axon.name = org.axonframework
logger.axon.level = INFO
logger.axon.additivity = false
logger.axon.appenderRefs = stdout
logger.axon.appenderRef.stdout.ref = STDOUT

logger.chaining-converter.name = org.axonframework.serialization.ChainingConverter
logger.chaining-converter.level = OFF

logger.hibernate.name = org.hibernate
logger.hibernate.level = ERROR
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,4 @@ void testBuildWithoutScopeAwareProviderThrowsAxonConfigurationException() {

assertThrows(AxonConfigurationException.class, builderTestSubject::build);
}

@Test
void testBuildWithoutSerializerThrowsAxonConfigurationException() {
Scheduler scheduler = mock(Scheduler.class);
ScopeAwareProvider scopeAwareProvider = mock(ScopeAwareProvider.class);
QuartzDeadlineManager.Builder builderTestSubject =
QuartzDeadlineManager.builder()
.scheduler(scheduler)
.scopeAwareProvider(scopeAwareProvider);

assertThrows(AxonConfigurationException.class, builderTestSubject::build);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.axonframework.messaging.ScopeAwareProvider;
import org.axonframework.messaging.ScopeDescriptor;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
Expand Down Expand Up @@ -330,7 +331,16 @@ public QuartzDeadlineManager build() {
protected void validate() throws AxonConfigurationException {
assertNonNull(scheduler, "The Scheduler is a hard requirement and should be provided");
assertNonNull(scopeAwareProvider, "The ScopeAwareProvider is a hard requirement and should be provided");
assertNonNull(serializer, "The Serializer is a hard requirement and should be provided");
if (serializer == null) {
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
serializer = XStreamSerializer::defaultSerializer;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package org.axonframework.eventhandling.scheduling.quartz;

import com.thoughtworks.xstream.XStream;
import org.axonframework.common.Assert;
import org.axonframework.common.AxonConfigurationException;
import org.axonframework.common.transaction.NoTransactionManager;
Expand All @@ -32,7 +31,6 @@
import org.axonframework.serialization.SerializedObject;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.SimpleSerializedObject;
import org.axonframework.serialization.xml.CompactDriver;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
Expand Down Expand Up @@ -252,9 +250,14 @@ public static class DirectEventJobDataBinder implements EventJobDataBinder {
*/
@Deprecated
public DirectEventJobDataBinder() {
this(XStreamSerializer.builder()
.xStream(new XStream(new CompactDriver()))
.build());
this(XStreamSerializer.defaultSerializer());
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
}

/**
Expand Down Expand Up @@ -448,7 +451,16 @@ protected void validate() throws AxonConfigurationException {
assertNonNull(scheduler, "The Scheduler is a hard requirement and should be provided");
assertNonNull(eventBus, "The EventBus is a hard requirement and should be provided");
if (jobDataBinderSupplier == null) {
assertNonNull(serializer, "The Serializer is a hard requirement and should be provided");
if (serializer == null) {
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
serializer = XStreamSerializer::defaultSerializer;
}
jobDataBinderSupplier = () -> new DirectEventJobDataBinder(serializer.get());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,18 +221,6 @@ void testBuildWithoutEventBusThrowsAxonConfigurationException() {
assertThrows(AxonConfigurationException.class, builderTestSubject::build);
}

@Test
void testBuildWithoutSerializerThrowsAxonConfigurationExceptionForMissingEventJobDataBinder() {
EventBus eventBus = SimpleEventBus.builder().build();
Scheduler scheduler = mock(Scheduler.class);
QuartzEventScheduler.Builder builderTestSubject =
QuartzEventScheduler.builder()
.eventBus(eventBus)
.scheduler(scheduler);

assertThrows(AxonConfigurationException.class, builderTestSubject::build);
}

private EventMessage<Object> buildTestEvent() {
return new GenericEventMessage<>(new Object());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.axonframework.modelling.saga.repository.jpa.SagaEntry;
import org.axonframework.serialization.SerializedObject;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -391,7 +392,16 @@ public JdbcSagaStore build() {
*/
protected void validate() throws AxonConfigurationException {
assertNonNull(connectionProvider, "The ConnectionProvider is a hard requirement and should be provided");
assertNonNull(serializer, "The Serializer is a hard requirement and should be provided");
if (serializer == null) {
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
serializer = XStreamSerializer::defaultSerializer;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.axonframework.modelling.saga.repository.SagaStore;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.SimpleSerializedObject;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -403,7 +404,16 @@ public JpaSagaStore build() {
protected void validate() throws AxonConfigurationException {
assertNonNull(entityManagerProvider,
"The EntityManagerProvider is a hard requirement and should be provided");
assertNonNull(serializer, "The Serializer is a hard requirement and should be provided");
if (serializer == null) {
logger.warn(
"The default XStreamSerializer is used, whereas it is strongly recommended to configure"
+ " the security context of the XStream instance.",
new AxonConfigurationException(
"A default XStreamSerializer is used, without specifying the security context"
)
);
serializer = XStreamSerializer::defaultSerializer;
}
}
}

Expand Down

0 comments on commit 4b042e9

Please sign in to comment.