1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.batch.core.repository.dao;
18
19 import java.sql.PreparedStatement;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import org.springframework.batch.core.JobExecution;
28 import org.springframework.batch.core.StepExecution;
29 import org.springframework.batch.item.ExecutionContext;
30 import org.springframework.jdbc.core.PreparedStatementSetter;
31 import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
32 import org.springframework.jdbc.support.lob.DefaultLobHandler;
33 import org.springframework.jdbc.support.lob.LobHandler;
34 import org.springframework.util.Assert;
35
36
37
38
39
40
41
42
43
44
45
46 public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implements ExecutionContextDao {
47
48 private static final String FIND_JOB_EXECUTION_CONTEXT = "SELECT SHORT_CONTEXT, SERIALIZED_CONTEXT "
49 + "FROM %PREFIX%JOB_EXECUTION_CONTEXT WHERE JOB_EXECUTION_ID = ?";
50
51 private static final String INSERT_JOB_EXECUTION_CONTEXT = "INSERT INTO %PREFIX%JOB_EXECUTION_CONTEXT "
52 + "(SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) " + "VALUES(?, ?, ?)";
53
54 private static final String UPDATE_JOB_EXECUTION_CONTEXT = "UPDATE %PREFIX%JOB_EXECUTION_CONTEXT "
55 + "SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? " + "WHERE JOB_EXECUTION_ID = ?";
56
57 private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT SHORT_CONTEXT, SERIALIZED_CONTEXT "
58 + "FROM %PREFIX%STEP_EXECUTION_CONTEXT WHERE STEP_EXECUTION_ID = ?";
59
60 private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT INTO %PREFIX%STEP_EXECUTION_CONTEXT "
61 + "(SHORT_CONTEXT, SERIALIZED_CONTEXT, STEP_EXECUTION_ID) " + "VALUES(?, ?, ?)";
62
63 private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT "
64 + "SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? " + "WHERE STEP_EXECUTION_ID = ?";
65
66 private static final int DEFAULT_MAX_VARCHAR_LENGTH = 2500;
67
68 private int shortContextLength = DEFAULT_MAX_VARCHAR_LENGTH;
69
70 private LobHandler lobHandler = new DefaultLobHandler();
71
72 private ExecutionContextStringSerializer serializer;
73
74
75
76
77
78
79
80
81
82
83
84 public void setShortContextLength(int shortContextLength) {
85 this.shortContextLength = shortContextLength;
86 }
87
88 public ExecutionContext getExecutionContext(JobExecution jobExecution) {
89 Long executionId = jobExecution.getId();
90 Assert.notNull(executionId, "ExecutionId must not be null.");
91
92 List<ExecutionContext> results = getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTION_CONTEXT),
93 new ExecutionContextRowMapper(), executionId);
94 if (results.size() > 0) {
95 return results.get(0);
96 }
97 else {
98 return new ExecutionContext();
99 }
100 }
101
102 public ExecutionContext getExecutionContext(StepExecution stepExecution) {
103 Long executionId = stepExecution.getId();
104 Assert.notNull(executionId, "ExecutionId must not be null.");
105
106 List<ExecutionContext> results = getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT),
107 new ExecutionContextRowMapper(), executionId);
108 if (results.size() > 0) {
109 return results.get(0);
110 }
111 else {
112 return new ExecutionContext();
113 }
114 }
115
116 public void updateExecutionContext(final JobExecution jobExecution) {
117 Long executionId = jobExecution.getId();
118 ExecutionContext executionContext = jobExecution.getExecutionContext();
119 Assert.notNull(executionId, "ExecutionId must not be null.");
120 Assert.notNull(executionContext, "The ExecutionContext must not be null.");
121
122 String serializedContext = serializeContext(executionContext);
123
124 persistSerializedContext(executionId, serializedContext, UPDATE_JOB_EXECUTION_CONTEXT);
125 }
126
127 public void updateExecutionContext(final StepExecution stepExecution) {
128
129 Long executionId = stepExecution.getId();
130 ExecutionContext executionContext = stepExecution.getExecutionContext();
131 Assert.notNull(executionId, "ExecutionId must not be null.");
132 Assert.notNull(executionContext, "The ExecutionContext must not be null.");
133
134 String serializedContext = serializeContext(executionContext);
135
136 persistSerializedContext(executionId, serializedContext, UPDATE_STEP_EXECUTION_CONTEXT);
137 }
138
139 public void saveExecutionContext(JobExecution jobExecution) {
140
141 Long executionId = jobExecution.getId();
142 ExecutionContext executionContext = jobExecution.getExecutionContext();
143 Assert.notNull(executionId, "ExecutionId must not be null.");
144 Assert.notNull(executionContext, "The ExecutionContext must not be null.");
145
146 String serializedContext = serializeContext(executionContext);
147
148 persistSerializedContext(executionId, serializedContext, INSERT_JOB_EXECUTION_CONTEXT);
149 }
150
151 public void saveExecutionContext(StepExecution stepExecution) {
152 Long executionId = stepExecution.getId();
153 ExecutionContext executionContext = stepExecution.getExecutionContext();
154 Assert.notNull(executionId, "ExecutionId must not be null.");
155 Assert.notNull(executionContext, "The ExecutionContext must not be null.");
156
157 String serializedContext = serializeContext(executionContext);
158
159 persistSerializedContext(executionId, serializedContext, INSERT_STEP_EXECUTION_CONTEXT);
160 }
161
162 public void setLobHandler(LobHandler lobHandler) {
163 this.lobHandler = lobHandler;
164 }
165
166 @Override
167 public void afterPropertiesSet() throws Exception {
168 super.afterPropertiesSet();
169 serializer = new XStreamExecutionContextStringSerializer();
170 ((XStreamExecutionContextStringSerializer) serializer).afterPropertiesSet();
171 }
172
173
174
175
176
177
178 private void persistSerializedContext(final Long executionId, String serializedContext, String sql) {
179
180 final String shortContext;
181 final String longContext;
182 if (serializedContext.length() > shortContextLength) {
183
184
185 shortContext = serializedContext.substring(0, shortContextLength - 8) + " ...";
186 longContext = serializedContext;
187 }
188 else {
189 shortContext = serializedContext;
190 longContext = null;
191 }
192
193 getJdbcTemplate().getJdbcOperations().update(getQuery(sql), new PreparedStatementSetter() {
194 public void setValues(PreparedStatement ps) throws SQLException {
195 ps.setString(1, shortContext);
196 if (longContext != null) {
197 lobHandler.getLobCreator().setClobAsString(ps, 2, longContext);
198 }
199 else {
200 ps.setNull(2, getClobTypeToUse());
201 }
202 ps.setLong(3, executionId);
203 }
204 });
205 }
206
207 private String serializeContext(ExecutionContext ctx) {
208 Map<String, Object> m = new HashMap<String, Object>();
209 for (Entry<String, Object> me : ctx.entrySet()) {
210 m.put(me.getKey(), me.getValue());
211 }
212 return serializer.serialize(m);
213 }
214
215 private class ExecutionContextRowMapper implements ParameterizedRowMapper<ExecutionContext> {
216 public ExecutionContext mapRow(ResultSet rs, int i) throws SQLException {
217 ExecutionContext executionContext = new ExecutionContext();
218 String serializedContext = rs.getString("SERIALIZED_CONTEXT");
219 if (serializedContext == null) {
220 serializedContext = rs.getString("SHORT_CONTEXT");
221 }
222 Map<String, Object> map = serializer.deserialize(serializedContext);
223 for (Map.Entry<String, Object> entry : map.entrySet()) {
224 executionContext.put(entry.getKey(), entry.getValue());
225 }
226 return executionContext;
227 }
228 }
229
230 }