From 4ad00166f84eb6df1e0a3bf1a3900ed70e09858d Mon Sep 17 00:00:00 2001 From: Michael Minella Date: Wed, 22 Mar 2017 15:25:14 -0500 Subject: [PATCH] Changed default ExecutionContext serialization mechanism The current default for serializing the ExecutionContext is via XStream using Jettison's driver. However, recent updates to Jettison make it incompatible with XStream with no progress on a fix. Because of this, and to encourage the use of well supported library combinations, the default ExecutionContext serialization mechanism for Spring Batch has been switched to Jackson (via the Jackson2ExecutionContextStringSerializer). This commit also depricates the XStreamExecutionContextStringSerializer for removal at a later date. However, it is still available for users that require that during a migration. Resolves BATCH-2575 --- .../explore/support/JobExplorerFactoryBean.java | 10 ++++------ .../core/jsr/partition/JsrPartitionHandler.java | 14 +++++++++++++- .../XStreamExecutionContextStringSerializer.java | 15 +++++++++------ .../support/JobRepositoryFactoryBean.java | 7 +++---- .../support/JobRepositoryFactoryBeanTests.java | 4 ++-- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java index 84521cbcd..4f24f8648 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java @@ -16,10 +16,13 @@ package org.springframework.batch.core.explore.support; +import javax.sql.DataSource; + import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.repository.ExecutionContextSerializer; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; import org.springframework.batch.core.repository.dao.ExecutionContextDao; +import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer; import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao; import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao; import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao; @@ -38,8 +41,6 @@ import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.util.Assert; -import javax.sql.DataSource; - /** * A {@link FactoryBean} that automates the creation of a * {@link SimpleJobExplorer} using JDBC DAO implementations. Requires the user @@ -127,10 +128,7 @@ implements InitializingBean { } if(serializer == null) { - XStreamExecutionContextStringSerializer defaultSerializer = new XStreamExecutionContextStringSerializer(); - defaultSerializer.afterPropertiesSet(); - - serializer = defaultSerializer; + serializer = new Jackson2ExecutionContextStringSerializer(); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/partition/JsrPartitionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/partition/JsrPartitionHandler.java index f3712dc6a..0179eb969 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/partition/JsrPartitionHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/partition/JsrPartitionHandler.java @@ -303,7 +303,10 @@ public class JsrPartitionHandler implements PartitionHandler, InitializingBean { throw new IllegalArgumentException("Either a number of threads or partitions are required"); } - stepExecution.getExecutionContext().put("partitionPlanState", new PartitionPlanState(plan)); + PartitionPlanState partitionPlanState = new PartitionPlanState(); + partitionPlanState.setPartitionPlan(plan); + + stepExecution.getExecutionContext().put("partitionPlanState", partitionPlanState); stepSplitter = new JsrStepExecutionSplitter(jobRepository, allowStartIfComplete, stepExecution.getStepName(), restoreState); partitionStepExecutions = stepSplitter.split(stepExecution, plan.getPartitions()); @@ -416,6 +419,15 @@ public class JsrPartitionHandler implements PartitionHandler, InitializingBean { threads = plan.getThreads(); } + public PartitionPlanState() { + } + + public void setPartitionPlan(PartitionPlan plan) { + this.partitionProperties = plan.getPartitionProperties(); + this.partitions = plan.getPartitions(); + this.threads = plan.getThreads(); + } + /* (non-Javadoc) * @see javax.batch.api.partition.PartitionPlan#getPartitionProperties() */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializer.java index fc48a1b2a..b5b21dc03 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013 the original author or authors. + * Copyright 2006-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,17 +23,17 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Map; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; +import com.thoughtworks.xstream.io.HierarchicalStreamDriver; +import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; + import org.springframework.batch.core.repository.ExecutionContextSerializer; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.serializer.Deserializer; import org.springframework.core.serializer.Serializer; import org.springframework.util.Assert; -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; -import com.thoughtworks.xstream.io.HierarchicalStreamDriver; -import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; - /** * Implementation that uses XStream and Jettison to provide serialization. * @@ -41,6 +41,9 @@ import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; * @author Michael Minella * @since 2.0 * @see ExecutionContextSerializer + * @deprecated Due to the incompattabilities between current Jettison versions and XStream + * versions, this serializer is depricated in favor of + * {@link Jackson2ExecutionContextStringSerializer} */ public class XStreamExecutionContextStringSerializer implements ExecutionContextSerializer, InitializingBean { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java index 7ce6b905e..af07939c3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java @@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.repository.ExecutionContextSerializer; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; import org.springframework.batch.core.repository.dao.ExecutionContextDao; +import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer; import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao; import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao; import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao; @@ -33,7 +34,6 @@ import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao; import org.springframework.batch.core.repository.dao.JobExecutionDao; import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.core.repository.dao.StepExecutionDao; -import org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer; import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory; import org.springframework.batch.support.DatabaseType; @@ -90,7 +90,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i /** * A custom implementation of the {@link ExecutionContextSerializer}. - * The default, if not injected, is the {@link XStreamExecutionContextStringSerializer}. + * The default, if not injected, is the {@link Jackson2ExecutionContextStringSerializer}. * * @param serializer used to serialize/deserialize {@link org.springframework.batch.item.ExecutionContext} * @see ExecutionContextSerializer @@ -189,8 +189,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i } if(serializer == null) { - XStreamExecutionContextStringSerializer defaultSerializer = new XStreamExecutionContextStringSerializer(); - defaultSerializer.afterPropertiesSet(); + Jackson2ExecutionContextStringSerializer defaultSerializer = new Jackson2ExecutionContextStringSerializer(); serializer = defaultSerializer; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java index 1a540deec..2e2e59f76 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java @@ -29,7 +29,7 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.repository.ExecutionContextSerializer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.dao.DefaultExecutionContextSerializer; -import org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer; +import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer; import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; import org.springframework.core.serializer.Serializer; import org.springframework.dao.DataAccessException; @@ -153,7 +153,7 @@ public class JobRepositoryFactoryBeanTests { factory.afterPropertiesSet(); Serializer> serializer = (Serializer>) ReflectionTestUtils.getField(factory, "serializer"); - assertTrue(serializer instanceof XStreamExecutionContextStringSerializer); + assertTrue(serializer instanceof Jackson2ExecutionContextStringSerializer); } @Test