|
20 | 20 |
|
21 | 21 | import javax.xml.stream.XMLStreamException; |
22 | 22 |
|
| 23 | +import org.springframework.batch.core.Job; |
| 24 | +import org.springframework.batch.core.JobExecutionListener; |
| 25 | +import org.springframework.batch.core.JobParameters; |
| 26 | +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; |
| 27 | +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; |
| 28 | +import org.springframework.batch.core.job.builder.SimpleJobBuilder; |
| 29 | +import org.springframework.batch.core.launch.JobLauncher; |
| 30 | +import org.springframework.batch.core.launch.support.SimpleJobLauncher; |
| 31 | +import org.springframework.batch.core.repository.JobRepository; |
| 32 | +import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; |
| 33 | +import org.springframework.batch.core.step.tasklet.TaskletStep; |
| 34 | +import org.springframework.batch.item.ItemReader; |
| 35 | +import org.springframework.batch.item.ItemWriter; |
| 36 | +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; |
| 37 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
23 | 38 | import org.w3c.dom.Document; |
24 | 39 | import org.w3c.dom.Element; |
25 | 40 | import org.w3c.dom.Node; |
|
38 | 53 | import com.marklogic.hub.collector.ServerCollector; |
39 | 54 | import com.marklogic.hub.flow.Flow; |
40 | 55 | import com.marklogic.hub.flow.SimpleFlow; |
41 | | -import com.marklogic.hub.plugin.Plugin; |
42 | | -import com.marklogic.hub.plugin.ServerPlugin; |
43 | | -import com.marklogic.hub.writer.ServerWriter; |
44 | | -import com.marklogic.hub.writer.Writer; |
| 56 | +import com.marklogic.spring.batch.hub.CollectorReader; |
| 57 | +import com.marklogic.spring.batch.hub.FlowWriter; |
45 | 58 |
|
46 | 59 | public class FlowManager extends ResourceManager { |
47 | 60 | private static final String HUB_NS = "http://marklogic.com/hub-in-a-box"; |
48 | | - static final public String NAME = "flow"; |
| 61 | + private static final String NAME = "flow"; |
| 62 | + private static final int DEFAULT_THREAD_COUNT = 8; |
| 63 | + |
49 | 64 | private DatabaseClient client; |
50 | 65 |
|
| 66 | + private JobBuilderFactory jobBuilderFactory; |
| 67 | + private StepBuilderFactory stepBuilderFactory; |
| 68 | + private JobLauncher jobLauncher; |
| 69 | + private ThreadPoolTaskExecutor executor; |
| 70 | + private int threadCount = DEFAULT_THREAD_COUNT; |
| 71 | + |
51 | 72 | public FlowManager(DatabaseClient client) { |
52 | 73 | super(); |
53 | 74 | this.client = client; |
54 | 75 | this.client.init(NAME, this); |
| 76 | + initializeDefaultSpringBatchComponents(); |
| 77 | + } |
| 78 | + |
| 79 | + public void setThreadCount(int count) { |
| 80 | + threadCount = count; |
| 81 | + executor.setCorePoolSize(threadCount); |
| 82 | + executor.setMaxPoolSize(threadCount); |
| 83 | + } |
| 84 | + |
| 85 | + protected void initializeDefaultSpringBatchComponents() { |
| 86 | + ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager(); |
| 87 | + MapJobRepositoryFactoryBean f = new MapJobRepositoryFactoryBean(transactionManager); |
| 88 | + try { |
| 89 | + f.afterPropertiesSet(); |
| 90 | + JobRepository jobRepository = f.getObject(); |
| 91 | + this.jobBuilderFactory = new JobBuilderFactory(jobRepository); |
| 92 | + this.stepBuilderFactory = new StepBuilderFactory(jobRepository, transactionManager); |
| 93 | + SimpleJobLauncher jbl = new SimpleJobLauncher(); |
| 94 | + jbl.setJobRepository(jobRepository); |
| 95 | + |
| 96 | + this.executor = new ThreadPoolTaskExecutor(); |
| 97 | + executor.setCorePoolSize(threadCount); |
| 98 | + executor.setMaxPoolSize(threadCount); |
| 99 | + executor.initialize(); |
| 100 | + executor.setWaitForTasksToCompleteOnShutdown(true); |
| 101 | + jbl.setTaskExecutor(executor); |
| 102 | + |
| 103 | + jbl.afterPropertiesSet(); |
| 104 | + this.jobLauncher = jbl; |
| 105 | + } catch (Exception ex) { |
| 106 | + throw new RuntimeException("Unable to initialize SqlMigrator, cause: " + ex.getMessage(), ex); |
| 107 | + } |
55 | 108 | } |
56 | 109 |
|
57 | 110 | /** |
@@ -121,74 +174,43 @@ public void uninstallFlow(String flowName) { |
121 | 174 |
|
122 | 175 | } |
123 | 176 |
|
| 177 | + public void runFlow(Flow flow, int batchSize) { |
| 178 | + runFlow(flow, batchSize, null); |
| 179 | + } |
| 180 | + |
124 | 181 | // might want to add Job tracking support |
125 | 182 | // by returning a Job or some such. |
126 | 183 | // Depends a lot on if we go full in with spring batch or not |
127 | 184 | /** |
128 | 185 | * Runs a given flow |
129 | 186 | * @param flow - the flow to run |
130 | 187 | * @param batchSize - the size to use for batching transactions |
| 188 | + * @param listener - the JobExecutionListener to receive status updates about the job |
131 | 189 | */ |
132 | | - public void runFlow(Flow flow, int batchSize) { |
| 190 | + public void runFlow(Flow flow, int batchSize, JobExecutionListener listener) { |
133 | 191 | Collector c = flow.getCollector(); |
134 | 192 | if (c instanceof ServerCollector) { |
135 | 193 | ((ServerCollector)c).setClient(client); |
136 | 194 | } |
| 195 | + ItemReader<String> reader = new CollectorReader(c); |
| 196 | + ItemWriter<String> writer = new FlowWriter(client, flow); |
137 | 197 |
|
138 | | - boolean allServer = true; |
139 | | - for (Plugin t : flow.getPlugins()) { |
140 | | - if (t instanceof ServerPlugin) { |
141 | | - ((ServerPlugin)t).setClient(client); |
142 | | - } |
143 | | - else if (t != null) { |
144 | | - allServer = false; |
145 | | - } |
146 | | - } |
| 198 | + TaskletStep step = stepBuilderFactory.get("testStep") |
| 199 | + .<String, String> chunk(batchSize) |
| 200 | + .reader(reader).writer(writer).build(); |
147 | 201 |
|
148 | | - Writer w = flow.getWriter(); |
149 | | - if (w instanceof ServerWriter) { |
150 | | - ((ServerWriter)w).setClient(client); |
| 202 | + String jobName = flow.getDomainName() + ":" + flow.getType() + ":" + flow.getName() + "-" + System.currentTimeMillis(); |
| 203 | + SimpleJobBuilder builder = jobBuilderFactory.get(jobName).start(step); |
| 204 | + if (listener != null) { |
| 205 | + builder = builder.listener(listener); |
151 | 206 | } |
| 207 | + Job job = builder.build(); |
152 | 208 |
|
153 | | - FlowRunner runner = new FlowRunner(client); |
154 | | - List<String> ids = c.run(); |
155 | | - |
156 | | - Transaction transaction = null; |
157 | 209 | try { |
158 | | - for (int i = 0; i < ids.size(); i++) { |
159 | | - if (i % batchSize == 0) { |
160 | | - if (transaction != null) { |
161 | | - transaction.commit(); |
162 | | - } |
163 | | - transaction = client.openTransaction(); |
164 | | - } |
165 | | - String id = ids.get(i); |
166 | | - |
167 | | - // all of the Plugins need to be run in MarkLogic |
168 | | - if (allServer) { |
169 | | - runner.run(flow, id, transaction); |
170 | | - } |
171 | | - |
172 | | - // this path is for when java is in the mix |
173 | | - // TODO: make this work |
174 | | - else { |
175 | | -// for (Plugin t : flow.getPlugins()) { |
176 | | -// if (t != null) { |
177 | | -// t.run(id); |
178 | | -// } |
179 | | -// } |
180 | | - w.write(id); |
181 | | - } |
182 | | - |
183 | | - } |
184 | | - if (transaction != null) { |
185 | | - transaction.commit(); |
186 | | - } |
| 210 | + jobLauncher.run(job, new JobParameters()); |
187 | 211 | } |
188 | | - catch(Exception e) { |
189 | | - if (transaction != null) { |
190 | | - transaction.rollback(); |
191 | | - } |
| 212 | + catch (Exception e) { |
| 213 | + throw new RuntimeException(e); |
192 | 214 | } |
193 | 215 | } |
194 | 216 |
|
@@ -222,9 +244,9 @@ public static Flow flowFromXml(Element doc) { |
222 | 244 | * A class to run a flow |
223 | 245 | */ |
224 | 246 | class FlowRunner extends ResourceManager { |
225 | | - static final public String NAME = "flow"; |
| 247 | + private static final String NAME = "flow"; |
226 | 248 |
|
227 | | - public FlowRunner(DatabaseClient client) { |
| 249 | + public FlowRunner(DatabaseClient client, Flow flow, String identifier, Transaction transaction) { |
228 | 250 | super(); |
229 | 251 | client.init(NAME, this); |
230 | 252 | } |
|
0 commit comments