Rename StepContext#getJobId to StepContext#getJobInstanceId
There is no such concept of job Id. A job has a name but not an Id. A job instance however has an Id. The goal of the getter suggested in BATCH-2769 is to access the JobInstance Id. This commit renames the newly added StepContext#getJobId to StepContext#getJobInstanceId which is more explicit. Resolves BATCH-2769
This commit is contained in:
@@ -1,310 +1,310 @@
|
||||
/*
|
||||
* Copyright 2006-2018 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.
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.UnexpectedJobExecutionException;
|
||||
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
|
||||
import org.springframework.batch.core.scope.StepScope;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A context object that can be used to interrogate the current
|
||||
* {@link StepExecution} and some of its associated properties using expressions
|
||||
* based on bean paths. Has public getters for the step execution and
|
||||
* convenience methods for accessing commonly used properties like the
|
||||
* {@link ExecutionContext} associated with the step or its enclosing job
|
||||
* execution.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @author Nicolas Widart
|
||||
*
|
||||
*/
|
||||
public class StepContext extends SynchronizedAttributeAccessor {
|
||||
|
||||
private StepExecution stepExecution;
|
||||
|
||||
private Map<String, Set<Runnable>> callbacks = new HashMap<>();
|
||||
|
||||
private BatchPropertyContext propertyContext = null;
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link StepContext} for this
|
||||
* {@link StepExecution}.
|
||||
*
|
||||
* @param stepExecution a step execution
|
||||
*/
|
||||
public StepContext(StepExecution stepExecution) {
|
||||
super();
|
||||
Assert.notNull(stepExecution, "A StepContext must have a non-null StepExecution");
|
||||
this.stepExecution = stepExecution;
|
||||
}
|
||||
|
||||
public StepContext(StepExecution stepExecution, BatchPropertyContext propertyContext) {
|
||||
super();
|
||||
Assert.notNull(stepExecution, "A StepContext must have a non-null StepExecution");
|
||||
this.stepExecution = stepExecution;
|
||||
this.propertyContext = propertyContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current step name identifier. Usually this is the
|
||||
* same as the bean name of the step that is executing (but might not be
|
||||
* e.g. in a partition).
|
||||
*
|
||||
* @return the step name identifier of the current {@link StepExecution}
|
||||
*/
|
||||
public String getStepName() {
|
||||
return stepExecution.getStepName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current job name identifier.
|
||||
*
|
||||
* @return the job name identifier of the enclosing {@link JobInstance}
|
||||
* associated with the current {@link StepExecution}
|
||||
*/
|
||||
public String getJobName() {
|
||||
Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution");
|
||||
Assert.state(stepExecution.getJobExecution().getJobInstance() != null,
|
||||
"StepExecution does not have a JobInstance");
|
||||
return stepExecution.getJobExecution().getJobInstance().getJobName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current job identifier.
|
||||
*
|
||||
* @return the job identifier of the enclosing {@link JobInstance}
|
||||
* associated with the current {@link StepExecution}
|
||||
*/
|
||||
public Long getJobId() {
|
||||
Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution");
|
||||
Assert.state(stepExecution.getJobExecution().getJobInstance() != null,
|
||||
"StepExecution does not have a JobInstance");
|
||||
return stepExecution.getJobExecution().getJobInstance().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for System properties to make it easy to access them
|
||||
* from placeholder expressions.
|
||||
*
|
||||
* @return the current System properties
|
||||
*/
|
||||
public Properties getSystemProperties() {
|
||||
return System.getProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the step {@link ExecutionContext}
|
||||
*/
|
||||
public Map<String, Object> getStepExecutionContext() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, Object> entry : stepExecution.getExecutionContext().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the job {@link ExecutionContext}
|
||||
*/
|
||||
public Map<String, Object> getJobExecutionContext() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, Object> entry : stepExecution.getJobExecution().getExecutionContext().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the {@link JobParameters}
|
||||
*/
|
||||
public Map<String, Object> getJobParameters() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, JobParameter> entry : stepExecution.getJobParameters().getParameters().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public Map<String, Object> getPartitionPlan() {
|
||||
Map<String, Object> partitionPlanProperties = new HashMap<>();
|
||||
|
||||
if(propertyContext != null) {
|
||||
Map partitionProperties = propertyContext.getStepProperties(getStepName());
|
||||
partitionPlanProperties = partitionProperties;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(partitionPlanProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow clients to register callbacks for clean up on close.
|
||||
*
|
||||
* @param name the callback id (unique attribute key in this context)
|
||||
* @param callback a callback to execute on close
|
||||
*/
|
||||
public void registerDestructionCallback(String name, Runnable callback) {
|
||||
synchronized (callbacks) {
|
||||
Set<Runnable> set = callbacks.get(name);
|
||||
if (set == null) {
|
||||
set = new HashSet<>();
|
||||
callbacks.put(name, set);
|
||||
}
|
||||
set.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterDestructionCallbacks(String name) {
|
||||
synchronized (callbacks) {
|
||||
callbacks.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override base class behaviour to ensure destruction callbacks are
|
||||
* unregistered as well as the default behaviour.
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#removeAttribute(String)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Object removeAttribute(String name) {
|
||||
unregisterDestructionCallbacks(name);
|
||||
return super.removeAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the context at the end of a step execution. Must be called once
|
||||
* at the end of a step execution to honour the destruction callback
|
||||
* contract from the {@link StepScope}.
|
||||
*/
|
||||
public void close() {
|
||||
|
||||
List<Exception> errors = new ArrayList<>();
|
||||
|
||||
Map<String, Set<Runnable>> copy = Collections.unmodifiableMap(callbacks);
|
||||
|
||||
for (Entry<String, Set<Runnable>> entry : copy.entrySet()) {
|
||||
Set<Runnable> set = entry.getValue();
|
||||
for (Runnable callback : set) {
|
||||
if (callback != null) {
|
||||
/*
|
||||
* The documentation of the interface says that these
|
||||
* callbacks must not throw exceptions, but we don't trust
|
||||
* them necessarily...
|
||||
*/
|
||||
try {
|
||||
callback.run();
|
||||
}
|
||||
catch (RuntimeException t) {
|
||||
errors.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Exception error = errors.get(0);
|
||||
if (error instanceof RuntimeException) {
|
||||
throw (RuntimeException) error;
|
||||
}
|
||||
else {
|
||||
throw new UnexpectedJobExecutionException("Could not close step context, rethrowing first of "
|
||||
+ errors.size() + " exceptions.", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current {@link StepExecution} that is active in this context.
|
||||
*
|
||||
* @return the current {@link StepExecution}
|
||||
*/
|
||||
public StepExecution getStepExecution() {
|
||||
return stepExecution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unique identifier for this context based on the step execution
|
||||
*/
|
||||
public String getId() {
|
||||
Assert.state(stepExecution.getId() != null, "StepExecution has no id. "
|
||||
+ "It must be saved before it can be used in step scope.");
|
||||
return "execution#" + stepExecution.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the base class method to include the step execution itself as a
|
||||
* key (i.e. two contexts are only equal if their step executions are the
|
||||
* same).
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof StepContext)) {
|
||||
return false;
|
||||
}
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
StepContext context = (StepContext) other;
|
||||
if (context.stepExecution == stepExecution) {
|
||||
return true;
|
||||
}
|
||||
return stepExecution.equals(context.stepExecution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default behaviour to provide a hash code based only on the
|
||||
* step execution.
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return stepExecution.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ", stepExecutionContext=" + getStepExecutionContext() + ", jobExecutionContext="
|
||||
+ getJobExecutionContext() + ", jobParameters=" + getJobParameters();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2006-2019 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.
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.UnexpectedJobExecutionException;
|
||||
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
|
||||
import org.springframework.batch.core.scope.StepScope;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A context object that can be used to interrogate the current
|
||||
* {@link StepExecution} and some of its associated properties using expressions
|
||||
* based on bean paths. Has public getters for the step execution and
|
||||
* convenience methods for accessing commonly used properties like the
|
||||
* {@link ExecutionContext} associated with the step or its enclosing job
|
||||
* execution.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @author Nicolas Widart
|
||||
*
|
||||
*/
|
||||
public class StepContext extends SynchronizedAttributeAccessor {
|
||||
|
||||
private StepExecution stepExecution;
|
||||
|
||||
private Map<String, Set<Runnable>> callbacks = new HashMap<>();
|
||||
|
||||
private BatchPropertyContext propertyContext = null;
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link StepContext} for this
|
||||
* {@link StepExecution}.
|
||||
*
|
||||
* @param stepExecution a step execution
|
||||
*/
|
||||
public StepContext(StepExecution stepExecution) {
|
||||
super();
|
||||
Assert.notNull(stepExecution, "A StepContext must have a non-null StepExecution");
|
||||
this.stepExecution = stepExecution;
|
||||
}
|
||||
|
||||
public StepContext(StepExecution stepExecution, BatchPropertyContext propertyContext) {
|
||||
super();
|
||||
Assert.notNull(stepExecution, "A StepContext must have a non-null StepExecution");
|
||||
this.stepExecution = stepExecution;
|
||||
this.propertyContext = propertyContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current step name identifier. Usually this is the
|
||||
* same as the bean name of the step that is executing (but might not be
|
||||
* e.g. in a partition).
|
||||
*
|
||||
* @return the step name identifier of the current {@link StepExecution}
|
||||
*/
|
||||
public String getStepName() {
|
||||
return stepExecution.getStepName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current job name identifier.
|
||||
*
|
||||
* @return the job name identifier of the enclosing {@link JobInstance}
|
||||
* associated with the current {@link StepExecution}
|
||||
*/
|
||||
public String getJobName() {
|
||||
Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution");
|
||||
Assert.state(stepExecution.getJobExecution().getJobInstance() != null,
|
||||
"StepExecution does not have a JobInstance");
|
||||
return stepExecution.getJobExecution().getJobInstance().getJobName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for current {@link JobInstance} identifier.
|
||||
*
|
||||
* @return the identifier of the enclosing {@link JobInstance}
|
||||
* associated with the current {@link StepExecution}
|
||||
*/
|
||||
public Long getJobInstanceId() {
|
||||
Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution");
|
||||
Assert.state(stepExecution.getJobExecution().getJobInstance() != null,
|
||||
"StepExecution does not have a JobInstance");
|
||||
return stepExecution.getJobExecution().getJobInstance().getInstanceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient accessor for System properties to make it easy to access them
|
||||
* from placeholder expressions.
|
||||
*
|
||||
* @return the current System properties
|
||||
*/
|
||||
public Properties getSystemProperties() {
|
||||
return System.getProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the step {@link ExecutionContext}
|
||||
*/
|
||||
public Map<String, Object> getStepExecutionContext() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, Object> entry : stepExecution.getExecutionContext().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the job {@link ExecutionContext}
|
||||
*/
|
||||
public Map<String, Object> getJobExecutionContext() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, Object> entry : stepExecution.getJobExecution().getExecutionContext().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map containing the items from the {@link JobParameters}
|
||||
*/
|
||||
public Map<String, Object> getJobParameters() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, JobParameter> entry : stepExecution.getJobParameters().getParameters().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public Map<String, Object> getPartitionPlan() {
|
||||
Map<String, Object> partitionPlanProperties = new HashMap<>();
|
||||
|
||||
if(propertyContext != null) {
|
||||
Map partitionProperties = propertyContext.getStepProperties(getStepName());
|
||||
partitionPlanProperties = partitionProperties;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(partitionPlanProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow clients to register callbacks for clean up on close.
|
||||
*
|
||||
* @param name the callback id (unique attribute key in this context)
|
||||
* @param callback a callback to execute on close
|
||||
*/
|
||||
public void registerDestructionCallback(String name, Runnable callback) {
|
||||
synchronized (callbacks) {
|
||||
Set<Runnable> set = callbacks.get(name);
|
||||
if (set == null) {
|
||||
set = new HashSet<>();
|
||||
callbacks.put(name, set);
|
||||
}
|
||||
set.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterDestructionCallbacks(String name) {
|
||||
synchronized (callbacks) {
|
||||
callbacks.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override base class behaviour to ensure destruction callbacks are
|
||||
* unregistered as well as the default behaviour.
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#removeAttribute(String)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Object removeAttribute(String name) {
|
||||
unregisterDestructionCallbacks(name);
|
||||
return super.removeAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the context at the end of a step execution. Must be called once
|
||||
* at the end of a step execution to honour the destruction callback
|
||||
* contract from the {@link StepScope}.
|
||||
*/
|
||||
public void close() {
|
||||
|
||||
List<Exception> errors = new ArrayList<>();
|
||||
|
||||
Map<String, Set<Runnable>> copy = Collections.unmodifiableMap(callbacks);
|
||||
|
||||
for (Entry<String, Set<Runnable>> entry : copy.entrySet()) {
|
||||
Set<Runnable> set = entry.getValue();
|
||||
for (Runnable callback : set) {
|
||||
if (callback != null) {
|
||||
/*
|
||||
* The documentation of the interface says that these
|
||||
* callbacks must not throw exceptions, but we don't trust
|
||||
* them necessarily...
|
||||
*/
|
||||
try {
|
||||
callback.run();
|
||||
}
|
||||
catch (RuntimeException t) {
|
||||
errors.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Exception error = errors.get(0);
|
||||
if (error instanceof RuntimeException) {
|
||||
throw (RuntimeException) error;
|
||||
}
|
||||
else {
|
||||
throw new UnexpectedJobExecutionException("Could not close step context, rethrowing first of "
|
||||
+ errors.size() + " exceptions.", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current {@link StepExecution} that is active in this context.
|
||||
*
|
||||
* @return the current {@link StepExecution}
|
||||
*/
|
||||
public StepExecution getStepExecution() {
|
||||
return stepExecution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unique identifier for this context based on the step execution
|
||||
*/
|
||||
public String getId() {
|
||||
Assert.state(stepExecution.getId() != null, "StepExecution has no id. "
|
||||
+ "It must be saved before it can be used in step scope.");
|
||||
return "execution#" + stepExecution.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the base class method to include the step execution itself as a
|
||||
* key (i.e. two contexts are only equal if their step executions are the
|
||||
* same).
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof StepContext)) {
|
||||
return false;
|
||||
}
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
StepContext context = (StepContext) other;
|
||||
if (context.stepExecution == stepExecution) {
|
||||
return true;
|
||||
}
|
||||
return stepExecution.equals(context.stepExecution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default behaviour to provide a hash code based only on the
|
||||
* step execution.
|
||||
*
|
||||
* @see SynchronizedAttributeAccessor#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return stepExecution.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ", stepExecutionContext=" + getStepExecutionContext() + ", jobExecutionContext="
|
||||
+ getJobExecutionContext() + ", jobParameters=" + getJobParameters();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,213 +1,214 @@
|
||||
/*
|
||||
* Copyright 2006-2018 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.
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Nicolas Widart
|
||||
*
|
||||
*/
|
||||
public class StepContextTests {
|
||||
|
||||
private List<String> list = new ArrayList<>();
|
||||
|
||||
private StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(2L, "job"), 0L, null, null), 1L);
|
||||
|
||||
private StepContext context = new StepContext(stepExecution);
|
||||
|
||||
private BatchPropertyContext propertyContext = new BatchPropertyContext();
|
||||
|
||||
@Test
|
||||
public void testGetStepExecution() {
|
||||
context = new StepContext(stepExecution);
|
||||
assertNotNull(context.getStepExecution());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullStepExecution() {
|
||||
try {
|
||||
context = new StepContext(null);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPartitionPlan() {
|
||||
Properties partitionPropertyValues = new Properties();
|
||||
partitionPropertyValues.put("key1", "value1");
|
||||
|
||||
propertyContext.setStepProperties(stepExecution.getStepName(), partitionPropertyValues);
|
||||
|
||||
context = new StepContext(stepExecution, propertyContext);
|
||||
|
||||
Map<String, Object> plan = context.getPartitionPlan();
|
||||
assertEquals("value1", plan.get("key1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsSelf() {
|
||||
assertEquals(context, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotEqualsNull() {
|
||||
assertFalse(context.equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsContextWithSameStepExecution() {
|
||||
assertEquals(new StepContext(stepExecution), context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackSunnyDay() throws Exception {
|
||||
context.setAttribute("foo", "FOO");
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
}
|
||||
});
|
||||
context.close();
|
||||
assertEquals(1, list.size());
|
||||
assertEquals("bar", list.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackMissingAttribute() throws Exception {
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
}
|
||||
});
|
||||
context.close();
|
||||
// Yes the callback should be called even if the attribute is missing -
|
||||
// for inner beans
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackWithException() throws Exception {
|
||||
context.setAttribute("foo", "FOO");
|
||||
context.setAttribute("bar", "BAR");
|
||||
context.registerDestructionCallback("bar", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("spam");
|
||||
throw new RuntimeException("fail!");
|
||||
}
|
||||
});
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
throw new RuntimeException("fail!");
|
||||
}
|
||||
});
|
||||
try {
|
||||
context.close();
|
||||
fail("Expected RuntimeException");
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// We don't care which one was thrown...
|
||||
assertEquals("fail!", e.getMessage());
|
||||
}
|
||||
// ...but we do care that both were executed:
|
||||
assertEquals(2, list.size());
|
||||
assertTrue(list.contains("bar"));
|
||||
assertTrue(list.contains("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepName() throws Exception {
|
||||
assertEquals("step", context.getStepName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobName() throws Exception {
|
||||
assertEquals("job", context.getJobName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobId() throws Exception {
|
||||
assertEquals(2L, (long)context.getJobId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepExecutionContext() throws Exception {
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
executionContext.put("foo", "bar");
|
||||
assertEquals("bar", context.getStepExecutionContext().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemProperties() throws Exception {
|
||||
System.setProperty("foo", "bar");
|
||||
assertEquals("bar", context.getSystemProperties().getProperty("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobExecutionContext() throws Exception {
|
||||
ExecutionContext executionContext = stepExecution.getJobExecution().getExecutionContext();
|
||||
executionContext.put("foo", "bar");
|
||||
assertEquals("bar", context.getJobExecutionContext().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobParameters() throws Exception {
|
||||
JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters();
|
||||
JobInstance instance = stepExecution.getJobExecution().getJobInstance();
|
||||
stepExecution = new StepExecution("step", new JobExecution(instance, jobParameters));
|
||||
context = new StepContext(stepExecution);
|
||||
assertEquals("bar", context.getJobParameters().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextId() throws Exception {
|
||||
assertEquals("execution#1", context.getId());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testIllegalContextId() throws Exception {
|
||||
context = new StepContext(new StepExecution("foo", new JobExecution(0L)));
|
||||
context.getId();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2006-2019 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.
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Nicolas Widart
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
public class StepContextTests {
|
||||
|
||||
private List<String> list = new ArrayList<>();
|
||||
|
||||
private StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(2L, "job"), 0L, null, null), 1L);
|
||||
|
||||
private StepContext context = new StepContext(stepExecution);
|
||||
|
||||
private BatchPropertyContext propertyContext = new BatchPropertyContext();
|
||||
|
||||
@Test
|
||||
public void testGetStepExecution() {
|
||||
context = new StepContext(stepExecution);
|
||||
assertNotNull(context.getStepExecution());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullStepExecution() {
|
||||
try {
|
||||
context = new StepContext(null);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPartitionPlan() {
|
||||
Properties partitionPropertyValues = new Properties();
|
||||
partitionPropertyValues.put("key1", "value1");
|
||||
|
||||
propertyContext.setStepProperties(stepExecution.getStepName(), partitionPropertyValues);
|
||||
|
||||
context = new StepContext(stepExecution, propertyContext);
|
||||
|
||||
Map<String, Object> plan = context.getPartitionPlan();
|
||||
assertEquals("value1", plan.get("key1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsSelf() {
|
||||
assertEquals(context, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotEqualsNull() {
|
||||
assertFalse(context.equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsContextWithSameStepExecution() {
|
||||
assertEquals(new StepContext(stepExecution), context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackSunnyDay() throws Exception {
|
||||
context.setAttribute("foo", "FOO");
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
}
|
||||
});
|
||||
context.close();
|
||||
assertEquals(1, list.size());
|
||||
assertEquals("bar", list.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackMissingAttribute() throws Exception {
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
}
|
||||
});
|
||||
context.close();
|
||||
// Yes the callback should be called even if the attribute is missing -
|
||||
// for inner beans
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestructionCallbackWithException() throws Exception {
|
||||
context.setAttribute("foo", "FOO");
|
||||
context.setAttribute("bar", "BAR");
|
||||
context.registerDestructionCallback("bar", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("spam");
|
||||
throw new RuntimeException("fail!");
|
||||
}
|
||||
});
|
||||
context.registerDestructionCallback("foo", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add("bar");
|
||||
throw new RuntimeException("fail!");
|
||||
}
|
||||
});
|
||||
try {
|
||||
context.close();
|
||||
fail("Expected RuntimeException");
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// We don't care which one was thrown...
|
||||
assertEquals("fail!", e.getMessage());
|
||||
}
|
||||
// ...but we do care that both were executed:
|
||||
assertEquals(2, list.size());
|
||||
assertTrue(list.contains("bar"));
|
||||
assertTrue(list.contains("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepName() throws Exception {
|
||||
assertEquals("step", context.getStepName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobName() throws Exception {
|
||||
assertEquals("job", context.getJobName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobInstanceId() throws Exception {
|
||||
assertEquals(2L, (long)context.getJobInstanceId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepExecutionContext() throws Exception {
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
executionContext.put("foo", "bar");
|
||||
assertEquals("bar", context.getStepExecutionContext().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemProperties() throws Exception {
|
||||
System.setProperty("foo", "bar");
|
||||
assertEquals("bar", context.getSystemProperties().getProperty("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobExecutionContext() throws Exception {
|
||||
ExecutionContext executionContext = stepExecution.getJobExecution().getExecutionContext();
|
||||
executionContext.put("foo", "bar");
|
||||
assertEquals("bar", context.getJobExecutionContext().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJobParameters() throws Exception {
|
||||
JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters();
|
||||
JobInstance instance = stepExecution.getJobExecution().getJobInstance();
|
||||
stepExecution = new StepExecution("step", new JobExecution(instance, jobParameters));
|
||||
context = new StepContext(stepExecution);
|
||||
assertEquals("bar", context.getJobParameters().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextId() throws Exception {
|
||||
assertEquals("execution#1", context.getId());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testIllegalContextId() throws Exception {
|
||||
context = new StepContext(new StepExecution("foo", new JobExecution(0L)));
|
||||
context.getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user