1 | /* |
2 | * Copyright 2006-2007 the original author or authors. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | package org.springframework.batch.retry.callback; |
18 | |
19 | import org.springframework.batch.item.FailedItemIdentifier; |
20 | import org.springframework.batch.item.ItemKeyGenerator; |
21 | import org.springframework.batch.item.ItemRecoverer; |
22 | import org.springframework.batch.item.ItemWriter; |
23 | import org.springframework.batch.retry.RetryCallback; |
24 | import org.springframework.batch.retry.RetryContext; |
25 | import org.springframework.batch.retry.RetryException; |
26 | import org.springframework.batch.retry.RetryPolicy; |
27 | import org.springframework.batch.retry.policy.ItemWriterRetryPolicy; |
28 | |
29 | /** |
30 | * A {@link RetryCallback} that knows about and caches an item, and attempts to |
31 | * process it using an {@link ItemWriter}. Used by the |
32 | * {@link ItemWriterRetryPolicy} to enable external retry of the item |
33 | * processing. |
34 | * |
35 | * @author Dave Syer |
36 | * |
37 | * @see ItemWriterRetryPolicy |
38 | * @see RetryPolicy#handleRetryExhausted(RetryContext) |
39 | * |
40 | */ |
41 | public class ItemWriterRetryCallback implements RetryCallback { |
42 | |
43 | private Object item; |
44 | |
45 | private ItemWriter writer; |
46 | |
47 | private ItemRecoverer recoverer; |
48 | |
49 | private ItemKeyGenerator keyGenerator; |
50 | |
51 | private FailedItemIdentifier failedItemIdentifier; |
52 | |
53 | private ItemKeyGenerator defaultKeyGenerator = new ItemKeyGenerator() { |
54 | public Object getKey(Object item) { |
55 | return item; |
56 | } |
57 | }; |
58 | |
59 | /** |
60 | * Constructor with mandatory properties. |
61 | * |
62 | * @param item the item to process |
63 | * @param writer the writer to use to process it |
64 | */ |
65 | public ItemWriterRetryCallback(Object item, ItemWriter writer) { |
66 | super(); |
67 | this.item = item; |
68 | this.writer = writer; |
69 | } |
70 | |
71 | /** |
72 | * Setter for injecting optional recovery handler. If it is not injected but |
73 | * the reader or writer implement {@link ItemRecoverer}, one of those will |
74 | * be used instead (preferring the reader to the writer if both would be |
75 | * appropriate). |
76 | * |
77 | * @param recoverer |
78 | */ |
79 | public void setRecoverer(ItemRecoverer recoverer) { |
80 | this.recoverer = recoverer; |
81 | } |
82 | |
83 | /** |
84 | * Public setter for the {@link ItemKeyGenerator}. If it is not injected |
85 | * but the reader or writer implement {@link ItemKeyGenerator}, one of |
86 | * those will be used instead (preferring the reader to the writer if both |
87 | * would be appropriate). |
88 | * @param keyGenerator the keyGenerator to set |
89 | */ |
90 | public void setKeyGenerator(ItemKeyGenerator keyGenerator) { |
91 | this.keyGenerator = keyGenerator; |
92 | } |
93 | |
94 | /** |
95 | * Public setter for the {@link FailedItemIdentifier}. If it is not |
96 | * injected but the reader or writer implement {@link FailedItemIdentifier}, |
97 | * one of those will be used instead (preferring the reader to the writer if |
98 | * both would be appropriate). |
99 | * @param failedItemIdentifier the {@link FailedItemIdentifier} to set |
100 | */ |
101 | public void setFailedItemIdentifier(FailedItemIdentifier failedItemIdentifier) { |
102 | this.failedItemIdentifier = failedItemIdentifier; |
103 | } |
104 | |
105 | public Object doWithRetry(RetryContext context) throws Throwable { |
106 | // This requires a collaboration with the RetryPolicy... |
107 | if (!context.isExhaustedOnly()) { |
108 | if (item != null) { |
109 | writer.write(item); |
110 | } |
111 | return null; |
112 | } |
113 | throw new RetryException("Recovery path requested in retry callback."); |
114 | } |
115 | |
116 | public Object getItem() { |
117 | return item; |
118 | } |
119 | |
120 | /** |
121 | * Accessor for the {@link ItemRecoverer}. If the handler is null but the |
122 | * {@link ItemWriter} is an instance of {@link ItemRecoverer}, then it will |
123 | * be returned instead. If none of those strategies works then a default |
124 | * implementation of {@link ItemKeyGenerator} will be used that just returns |
125 | * the item. |
126 | * |
127 | * @return the {@link ItemRecoverer}. |
128 | */ |
129 | public ItemKeyGenerator getKeyGenerator() { |
130 | if (keyGenerator != null) { |
131 | return keyGenerator; |
132 | } |
133 | if (writer instanceof ItemKeyGenerator) { |
134 | return (ItemKeyGenerator) writer; |
135 | } |
136 | return defaultKeyGenerator; |
137 | } |
138 | |
139 | /** |
140 | * Accessor for the {@link FailedItemIdentifier}. If the handler is null |
141 | * but the {@link ItemWriter} or {@link ItemWriter} is an instance of |
142 | * {@link FailedItemIdentifier}, then it will be returned instead. If none |
143 | * of those strategies works returns null. |
144 | * |
145 | * @return the {@link FailedItemIdentifier}. |
146 | */ |
147 | public FailedItemIdentifier getFailedItemIdentifier() { |
148 | if (failedItemIdentifier != null) { |
149 | return failedItemIdentifier; |
150 | } |
151 | if (writer instanceof FailedItemIdentifier) { |
152 | return (FailedItemIdentifier) writer; |
153 | } |
154 | return null; |
155 | } |
156 | |
157 | /** |
158 | * Accessor for the {@link ItemRecoverer}. If the handler is null but the |
159 | * {@link ItemWriter} is an instance of {@link ItemRecoverer}, then it will |
160 | * be returned instead. |
161 | * |
162 | * @return the {@link ItemRecoverer}. |
163 | */ |
164 | public ItemRecoverer getRecoverer() { |
165 | if (recoverer != null) { |
166 | return recoverer; |
167 | } |
168 | if (writer instanceof ItemRecoverer) { |
169 | return (ItemRecoverer) writer; |
170 | } |
171 | return null; |
172 | } |
173 | |
174 | } |