1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import org.apache.log4j.Logger;
19 import org.apache.ojb.broker.OptimisticLockException;
20 import org.kuali.rice.kew.api.KewApiConstants;
21 import org.kuali.rice.kew.api.exception.WorkflowException;
22 import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent;
23 import org.kuali.rice.kew.framework.postprocessor.AfterProcessEvent;
24 import org.kuali.rice.kew.framework.postprocessor.BeforeProcessEvent;
25 import org.kuali.rice.kew.framework.postprocessor.DeleteEvent;
26 import org.kuali.rice.kew.framework.postprocessor.DocumentLockingEvent;
27 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteLevelChange;
28 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
29 import org.kuali.rice.kew.framework.postprocessor.ProcessDocReport;
30 import org.kuali.rice.krad.UserSession;
31 import org.kuali.rice.krad.document.Document;
32 import org.kuali.rice.krad.service.DocumentService;
33 import org.kuali.rice.krad.service.PostProcessorService;
34 import org.kuali.rice.krad.util.GlobalVariables;
35 import org.kuali.rice.krad.util.KRADConstants;
36 import org.kuali.rice.krad.util.ObjectUtils;
37 import org.springframework.transaction.annotation.Transactional;
38
39 import java.util.List;
40
41
42
43
44
45
46
47 @Transactional
48 public class PostProcessorServiceImpl implements PostProcessorService {
49
50 private static Logger LOG = Logger.getLogger(PostProcessorServiceImpl.class);
51
52 private DocumentService documentService;
53
54
55
56
57 @Override
58 public ProcessDocReport doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) throws Exception {
59 try {
60 if ( LOG.isInfoEnabled() ) {
61 LOG.info(new StringBuffer("started handling route status change from ").append(statusChangeEvent.getOldRouteStatus()).append(" to ").append(statusChangeEvent.getNewRouteStatus()).append(" for document ").append(statusChangeEvent.getDocumentId()));
62 }
63 establishGlobalVariables();
64 Document document = documentService.getByDocumentHeaderId(statusChangeEvent.getDocumentId());
65 if (document == null) {
66 if (!KewApiConstants.ROUTE_HEADER_CANCEL_CD.equals(statusChangeEvent.getNewRouteStatus())) {
67 throw new RuntimeException("unable to load document " + statusChangeEvent.getDocumentId());
68 }
69 }
70 else {
71 document.doRouteStatusChange(statusChangeEvent);
72
73
74
75
76
77
78
79
80 if (!document.getDocumentHeader().getWorkflowDocument().isSaved()) {
81 documentService.updateDocument(document);
82 }
83 }
84 if ( LOG.isInfoEnabled() ) {
85 LOG.info(new StringBuffer("finished handling route status change from ").append(statusChangeEvent.getOldRouteStatus()).append(" to ").append(statusChangeEvent.getNewRouteStatus()).append(" for document ").append(statusChangeEvent.getDocumentId()));
86 }
87 }
88 catch (Exception e) {
89 logAndRethrow("route status", e);
90 }
91 return new ProcessDocReport(true, "");
92 }
93
94
95
96
97 public ProcessDocReport doRouteLevelChange(DocumentRouteLevelChange levelChangeEvent) throws Exception {
98
99
100
101 try {
102 if ( LOG.isDebugEnabled() ) {
103 LOG.debug(new StringBuffer("started handling route level change from ").append(levelChangeEvent.getOldNodeName()).append(" to ").append(levelChangeEvent.getNewNodeName()).append(" for document ").append(levelChangeEvent.getDocumentId()));
104 }
105 establishGlobalVariables();
106 Document document = documentService.getByDocumentHeaderId(levelChangeEvent.getDocumentId());
107 if (document == null) {
108 throw new RuntimeException("unable to load document " + levelChangeEvent.getDocumentId());
109 }
110 document.populateDocumentForRouting();
111 document.doRouteLevelChange(levelChangeEvent);
112 document.getDocumentHeader().getWorkflowDocument().saveDocumentData();
113 if ( LOG.isDebugEnabled() ) {
114 LOG.debug(new StringBuffer("finished handling route level change from ").append(levelChangeEvent.getOldNodeName()).append(" to ").append(levelChangeEvent.getNewNodeName()).append(" for document ").append(levelChangeEvent.getDocumentId()));
115 }
116 }
117 catch (Exception e) {
118 logAndRethrow("route level", e);
119 }
120 return new ProcessDocReport(true, "");
121 }
122
123
124
125
126 @Override
127 public ProcessDocReport doDeleteRouteHeader(DeleteEvent event) throws Exception {
128 return new ProcessDocReport(true, "");
129 }
130
131
132
133
134 @Override
135 public ProcessDocReport doActionTaken(ActionTakenEvent event) throws Exception {
136 try {
137 if ( LOG.isDebugEnabled() ) {
138 LOG.debug(new StringBuffer("started doing action taken for action taken code").append(event.getActionTaken().getActionTaken()).append(" for document ").append(event.getDocumentId()));
139 }
140 establishGlobalVariables();
141 Document document = documentService.getByDocumentHeaderId(event.getDocumentId());
142 if (ObjectUtils.isNull(document)) {
143
144 if (!KewApiConstants.ACTION_TAKEN_CANCELED.equals(event.getActionTaken())) {
145 LOG.warn("doActionTaken() Unable to load document with id " + event.getDocumentId() +
146 " using action taken code '" + KewApiConstants.ACTION_TAKEN_CD.get(event.getActionTaken().getActionTaken()));
147
148 }
149 } else {
150 document.doActionTaken(event);
151 if ( LOG.isDebugEnabled() ) {
152 LOG.debug(new StringBuffer("finished doing action taken for action taken code").append(event.getActionTaken().getActionTaken()).append(" for document ").append(event.getDocumentId()));
153 }
154 }
155 }
156 catch (Exception e) {
157 logAndRethrow("do action taken", e);
158 }
159 return new ProcessDocReport(true, "");
160 }
161
162
163
164
165
166
167
168 @Override
169 public ProcessDocReport afterProcess(AfterProcessEvent event) throws Exception {
170 try {
171 if ( LOG.isDebugEnabled() ) {
172 LOG.debug(new StringBuffer("started after process method for document ").append(event.getDocumentId()));
173 }
174 establishGlobalVariables();
175 Document document = documentService.getByDocumentHeaderId(event.getDocumentId());
176 if (ObjectUtils.isNull(document)) {
177
178 LOG.warn("afterProcess() Unable to load document with id " + event.getDocumentId() + "... ignoring post processing");
179 } else {
180 document.afterWorkflowEngineProcess(event.isSuccessfullyProcessed());
181 if ( LOG.isDebugEnabled() ) {
182 LOG.debug(new StringBuffer("finished after process method for document ").append(event.getDocumentId()));
183 }
184 }
185 }
186 catch (Exception e) {
187 logAndRethrow("after process", e);
188 }
189 return new ProcessDocReport(true, "");
190 }
191
192
193
194
195
196
197
198 @Override
199 public ProcessDocReport beforeProcess(BeforeProcessEvent event) throws Exception {
200 try {
201 if ( LOG.isDebugEnabled() ) {
202 LOG.debug(new StringBuffer("started before process method for document ").append(event.getDocumentId()));
203 }
204 establishGlobalVariables();
205 Document document = documentService.getByDocumentHeaderId(event.getDocumentId());
206 if (ObjectUtils.isNull(document)) {
207
208 LOG.warn("beforeProcess() Unable to load document with id " + event.getDocumentId() + "... ignoring post processing");
209 } else {
210 document.beforeWorkflowEngineProcess();
211 if ( LOG.isDebugEnabled() ) {
212 LOG.debug(new StringBuffer("finished before process method for document ").append(event.getDocumentId()));
213 }
214 }
215 }
216 catch (Exception e) {
217 logAndRethrow("before process", e);
218 }
219 return new ProcessDocReport(true, "");
220 }
221
222
223
224
225
226
227
228 public List<String> getDocumentIdsToLock(DocumentLockingEvent event) throws Exception {
229 try {
230 if ( LOG.isDebugEnabled() ) {
231 LOG.debug(new StringBuffer("started get document ids to lock method for document ").append(event.getDocumentId()));
232 }
233 establishGlobalVariables();
234 Document document = documentService.getByDocumentHeaderId(event.getDocumentId());
235 if (ObjectUtils.isNull(document)) {
236
237 LOG.warn("getDocumentIdsToLock() Unable to load document with id " + event.getDocumentId() + "... ignoring post processing");
238 } else {
239 List<String> documentIdsToLock = document.getWorkflowEngineDocumentIdsToLock();
240 if ( LOG.isDebugEnabled() ) {
241 LOG.debug(new StringBuffer("finished get document ids to lock method for document ").append(event.getDocumentId()));
242 }
243 if (documentIdsToLock == null) {
244 return null;
245 }
246 return documentIdsToLock;
247 }
248 }
249 catch (Exception e) {
250 logAndRethrow("before process", e);
251 }
252 return null;
253 }
254
255 private void logAndRethrow(String changeType, Exception e) throws RuntimeException {
256 LOG.error("caught exception while handling " + changeType + " change", e);
257 logOptimisticDetails(5, e);
258
259 throw new RuntimeException("post processor caught exception while handling " + changeType + " change: " + e.getMessage(), e);
260 }
261
262
263
264
265
266
267
268 private void logOptimisticDetails(int depth, Throwable t) {
269 if ((depth > 0) && (t != null)) {
270 if (t instanceof OptimisticLockException) {
271 OptimisticLockException o = (OptimisticLockException) t;
272
273 LOG.error("source of OptimisticLockException = " + o.getSourceObject().getClass().getName() + " ::= " + o.getSourceObject());
274 }
275 else {
276 Throwable cause = t.getCause();
277 if (cause != t) {
278 logOptimisticDetails(--depth, cause);
279 }
280 }
281 }
282 }
283
284
285
286
287
288 public final void setDocumentService(DocumentService documentService) {
289 this.documentService = documentService;
290 }
291
292
293
294
295 protected void establishGlobalVariables() throws WorkflowException {
296 if (GlobalVariables.getUserSession() == null) {
297 GlobalVariables.setUserSession(new UserSession(KRADConstants.SYSTEM_USER));
298 }
299 GlobalVariables.clear();
300 }
301
302 }