1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.ksb.messaging.config;
17
18 import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
19 import org.apache.commons.httpclient.protocol.Protocol;
20 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
21 import org.kuali.rice.core.api.config.CoreConfigHelper;
22 import org.kuali.rice.core.api.config.module.RunMode;
23 import org.kuali.rice.core.api.config.property.Config;
24 import org.kuali.rice.core.api.config.property.ConfigContext;
25 import org.kuali.rice.core.api.exception.RiceRuntimeException;
26 import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
27 import org.kuali.rice.core.api.lifecycle.Lifecycle;
28 import org.kuali.rice.core.api.resourceloader.ResourceLoader;
29 import org.kuali.rice.core.api.util.ClassLoaderUtils;
30 import org.kuali.rice.core.api.util.RiceConstants;
31 import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
32 import org.kuali.rice.core.impl.config.module.ModuleConfigurer;
33 import org.kuali.rice.core.impl.lifecycle.ServiceDelegatingLifecycle;
34 import org.kuali.rice.ksb.api.KsbApiConstants;
35 import org.kuali.rice.ksb.api.KsbApiServiceLocator;
36 import org.kuali.rice.ksb.api.bus.ServiceDefinition;
37 import org.kuali.rice.ksb.messaging.AlternateEndpoint;
38 import org.kuali.rice.ksb.messaging.AlternateEndpointLocation;
39 import org.kuali.rice.ksb.messaging.MessageFetcher;
40 import org.kuali.rice.ksb.messaging.resourceloader.KSBResourceLoaderFactory;
41 import org.kuali.rice.ksb.messaging.serviceconnectors.HttpInvokerConnector;
42 import org.kuali.rice.ksb.service.KSBServiceLocator;
43 import org.kuali.rice.ksb.util.KSBConstants;
44 import org.quartz.Scheduler;
45 import org.springframework.transaction.PlatformTransactionManager;
46
47 import javax.sql.DataSource;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.LinkedList;
53 import java.util.List;
54
55
56
57
58
59
60
61
62
63
64 public class KSBConfigurer extends ModuleConfigurer {
65
66 private static final String SERVICE_BUS_CLIENT_SPRING = "classpath:org/kuali/rice/ksb/config/KsbServiceBusClientSpringBeans.xml";
67 private static final String MESSAGE_CLIENT_SPRING = "classpath:org/kuali/rice/ksb/config/KsbMessageClientSpringBeans.xml";
68 private static final String OJB_MESSAGE_CLIENT_SPRING = "classpath:org/kuali/rice/ksb/config/KsbOjbMessageClientSpringBeans.xml";
69 private static final String BAM_SPRING = "classpath:org/kuali/rice/ksb/config/KsbBamSpringBeans.xml";
70 private static final String OJB_BAM_SPRING = "classpath:org/kuali/rice/ksb/config/KsbOjbBamSpringBeans.xml";
71 private static final String MODULE_SPRING = "classpath:org/kuali/rice/ksb/config/KsbModuleConfigurationSpringBeans.xml";
72 private static final String REGISTRY_SERVER_SPRING = "classpath:org/kuali/rice/ksb/config/KsbRegistryServerSpringBeans.xml";
73 private static final String OJB_REGISTRY_SPRING = "classpath:org/kuali/rice/ksb/config/KsbOjbRegistrySpringBeans.xml";
74 private static final String WEB_SPRING = "classpath:org/kuali/rice/ksb/config/KsbWebSpringBeans.xml";
75
76 private List<ServiceDefinition> services = new ArrayList<ServiceDefinition>();
77
78 private List<AlternateEndpointLocation> alternateEndpointLocations = new ArrayList<AlternateEndpointLocation>();
79
80 private List<AlternateEndpoint> alternateEndpoints = new ArrayList<AlternateEndpoint>();
81
82 private DataSource registryDataSource;
83
84 private DataSource messageDataSource;
85
86 private DataSource nonTransactionalMessageDataSource;
87
88 private DataSource bamDataSource;
89
90 private Scheduler exceptionMessagingScheduler;
91
92 private PlatformTransactionManager platformTransactionManager;
93
94 private List<Lifecycle> internalLifecycles;
95
96 public KSBConfigurer() {
97 super(KsbApiConstants.KSB_MODULE_NAME);
98 setValidRunModes(Arrays.asList(RunMode.REMOTE, RunMode.LOCAL));
99 this.internalLifecycles = new ArrayList<Lifecycle>();
100 }
101
102 @Override
103 public void addAdditonalToConfig() {
104 configureDataSource();
105 configureScheduler();
106 configurePlatformTransactionManager();
107 configureAlternateEndpoints();
108 }
109
110 @Override
111 public List<String> getPrimarySpringFiles(){
112 final List<String> springFileLocations = new ArrayList<String>();
113
114 boolean isJpa = OrmUtils.isJpaEnabled("rice.ksb");
115 if (isJpa) {
116
117
118 throw new UnsupportedOperationException("JPA not currently supported for KSB");
119 }
120
121 springFileLocations.add(SERVICE_BUS_CLIENT_SPRING);
122
123 if (isMessagePersistenceEnabled()) {
124 springFileLocations.add(MESSAGE_CLIENT_SPRING);
125 springFileLocations.add(OJB_MESSAGE_CLIENT_SPRING);
126 }
127
128 if (isBamEnabled()) {
129 springFileLocations.add(BAM_SPRING);
130 springFileLocations.add(OJB_BAM_SPRING);
131 }
132
133 if (getRunMode().equals( RunMode.LOCAL )) {
134
135 springFileLocations.add("classpath:org/kuali/rice/krad/config/KRADSpringBeans.xml");
136 springFileLocations.add("classpath:org/kuali/rice/kns/config/KNSSpringBeans.xml");
137 springFileLocations.add(REGISTRY_SERVER_SPRING);
138 springFileLocations.add(OJB_REGISTRY_SPRING);
139 if (ConfigContext.getCurrentContextConfig().getBooleanProperty(KSBConstants.Config.LOAD_KRAD_MODULE_CONFIGURATION, false)) {
140 springFileLocations.add(MODULE_SPRING);
141 springFileLocations.add(WEB_SPRING);
142 }
143 }
144
145 return springFileLocations;
146 }
147
148
149
150
151
152
153 @Override
154 public boolean shouldRenderWebInterface() {
155 return true;
156 }
157
158 @Override
159 public Collection<ResourceLoader> getResourceLoadersToRegister() throws Exception{
160 ResourceLoader ksbRemoteResourceLoader = KSBResourceLoaderFactory.createRootKSBRemoteResourceLoader();
161 ksbRemoteResourceLoader.start();
162 return Collections.singletonList(ksbRemoteResourceLoader);
163 }
164
165 @Override
166 public List<Lifecycle> loadLifecycles() throws Exception {
167 List<Lifecycle> lifecycles = new LinkedList<Lifecycle>();
168
169
170 lifecycles.add(new BaseLifecycle() {
171
172 @Override
173 public void start() throws Exception {
174
175 if (Boolean.valueOf(ConfigContext.getCurrentContextConfig().getProperty(KSBConstants.Config.KSB_ALLOW_SELF_SIGNED_SSL)).booleanValue()) {
176 Protocol.registerProtocol("https", new Protocol("https",
177 (ProtocolSocketFactory) new EasySSLProtocolSocketFactory(), 443));
178 }
179 super.start();
180 }
181 });
182 lifecycles.add(new ServiceDelegatingLifecycle(KSBConstants.ServiceNames.BUS_ADMIN_SERVICE));
183 return lifecycles;
184 }
185
186
187
188 @Override
189 public void doAdditonalConfigurerValidations() {
190 for (final ServiceDefinition serviceDef : KSBConfigurer.this.services) {
191 serviceDef.validate();
192 }
193 }
194
195 @Override
196 public void doAdditionalContextStartedLogic() {
197 ServicePublisher servicePublisher = new ServicePublisher(getServices());
198 Lifecycle serviceBus = new ServiceDelegatingLifecycle(KsbApiServiceLocator.SERVICE_BUS);
199 Lifecycle threadPool = new ServiceDelegatingLifecycle(KSBConstants.ServiceNames.THREAD_POOL_SERVICE);
200 Lifecycle scheduledThreadPool = new ServiceDelegatingLifecycle(KSBConstants.ServiceNames.SCHEDULED_THREAD_POOL_SERVICE);
201
202 try {
203 servicePublisher.start();
204 internalLifecycles.add(servicePublisher);
205 serviceBus.start();
206 internalLifecycles.add(serviceBus);
207 threadPool.start();
208 internalLifecycles.add(threadPool);
209 scheduledThreadPool.start();
210 internalLifecycles.add(scheduledThreadPool);
211 } catch (Exception e) {
212 if (e instanceof RuntimeException) {
213 throw (RuntimeException)e;
214 }
215 throw new RiceRuntimeException("Failed to initialize KSB on context startup");
216 }
217
218 requeueMessages();
219 }
220
221 @Override
222 protected void doAdditionalModuleStopLogic() throws Exception {
223 for (int index = internalLifecycles.size() - 1; index >= 0; index--) {
224 try {
225 internalLifecycles.get(index).stop();
226 } catch (Exception e) {
227 LOG.error("Failed to properly execute shutdown logic.", e);
228 }
229 }
230 }
231
232
233
234
235
236 private void requeueMessages() {
237 LOG.info("Refreshing Service Registry to export services to the bus.");
238 KsbApiServiceLocator.getServiceBus().synchronize();
239
240
241 MessageFetcher messageFetcher = new MessageFetcher((Integer) null);
242 KSBServiceLocator.getThreadPool().execute(messageFetcher);
243 }
244
245 protected boolean isMessagePersistenceEnabled() {
246 return ConfigContext.getCurrentContextConfig().getBooleanProperty(KSBConstants.Config.MESSAGE_PERSISTENCE, true);
247 }
248
249 protected boolean isBamEnabled() {
250 return ConfigContext.getCurrentContextConfig().getBooleanProperty(Config.BAM_ENABLED, false);
251 }
252
253 protected void configureScheduler() {
254 if (this.getExceptionMessagingScheduler() != null) {
255 LOG.info("Configuring injected exception messaging Scheduler");
256 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.INJECTED_EXCEPTION_MESSAGE_SCHEDULER_KEY, this.getExceptionMessagingScheduler());
257 }
258 }
259
260 protected void configureDataSource() {
261 if (isMessagePersistenceEnabled()) {
262 if (getMessageDataSource() != null) {
263 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_MESSAGE_DATASOURCE, getMessageDataSource());
264 }
265 if (getNonTransactionalMessageDataSource() != null) {
266 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_MESSAGE_NON_TRANSACTIONAL_DATASOURCE, getNonTransactionalMessageDataSource());
267 }
268 }
269 if (getRunMode().equals(RunMode.LOCAL)) {
270 if (getRegistryDataSource() != null) {
271 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_REGISTRY_DATASOURCE, getRegistryDataSource());
272 }
273 }
274 if (isBamEnabled()) {
275 if (getBamDataSource() != null) {
276 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_BAM_DATASOURCE, getBamDataSource());
277 }
278 }
279 }
280
281 protected void configurePlatformTransactionManager() {
282 if (getPlatformTransactionManager() == null) {
283 return;
284 }
285 ConfigContext.getCurrentContextConfig().putObject(RiceConstants.SPRING_TRANSACTION_MANAGER, getPlatformTransactionManager());
286 }
287
288 protected void configureAlternateEndpoints() {
289 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_ALTERNATE_ENDPOINT_LOCATIONS, getAlternateEndpointLocations());
290 ConfigContext.getCurrentContextConfig().putObject(KSBConstants.Config.KSB_ALTERNATE_ENDPOINTS, getAlternateEndpoints());
291 }
292
293 @Override
294 public void doAdditionalContextStoppedLogic() {
295 try {
296 HttpInvokerConnector.shutdownIdleConnectionTimeout();
297 } catch (Exception e) {
298 LOG.error("Failed to shutdown idle connection timeout evictor thread.", e);
299 }
300 cleanUpConfiguration();
301 }
302
303
304
305
306
307
308
309
310 protected void cleanUpConfiguration() {
311 ConfigContext.getCurrentContextConfig().removeObject(KSBConstants.Config.KSB_ALTERNATE_ENDPOINTS);
312 }
313
314 public List<ServiceDefinition> getServices() {
315 return this.services;
316 }
317
318 public void setServices(List<ServiceDefinition> javaServices) {
319 this.services = javaServices;
320 }
321
322 public DataSource getMessageDataSource() {
323 return this.messageDataSource;
324 }
325
326 public void setMessageDataSource(DataSource messageDataSource) {
327 this.messageDataSource = messageDataSource;
328 }
329
330 public DataSource getNonTransactionalMessageDataSource() {
331 return this.nonTransactionalMessageDataSource;
332 }
333
334 public void setNonTransactionalMessageDataSource(DataSource nonTransactionalMessageDataSource) {
335 this.nonTransactionalMessageDataSource = nonTransactionalMessageDataSource;
336 }
337
338 public DataSource getRegistryDataSource() {
339 return this.registryDataSource;
340 }
341
342 public void setRegistryDataSource(DataSource registryDataSource) {
343 this.registryDataSource = registryDataSource;
344 }
345
346 public DataSource getBamDataSource() {
347 return this.bamDataSource;
348 }
349
350 public void setBamDataSource(DataSource bamDataSource) {
351 this.bamDataSource = bamDataSource;
352 }
353
354 public Scheduler getExceptionMessagingScheduler() {
355 return this.exceptionMessagingScheduler;
356 }
357
358 public void setExceptionMessagingScheduler(Scheduler exceptionMessagingScheduler) {
359 this.exceptionMessagingScheduler = exceptionMessagingScheduler;
360 }
361
362 public PlatformTransactionManager getPlatformTransactionManager() {
363 return platformTransactionManager;
364 }
365
366 public void setPlatformTransactionManager(PlatformTransactionManager springTransactionManager) {
367 this.platformTransactionManager = springTransactionManager;
368 }
369
370 public List<AlternateEndpointLocation> getAlternateEndpointLocations() {
371 return this.alternateEndpointLocations;
372 }
373
374 public void setAlternateEndpointLocations(List<AlternateEndpointLocation> alternateEndpointLocations) {
375 this.alternateEndpointLocations = alternateEndpointLocations;
376 }
377
378 public List<AlternateEndpoint> getAlternateEndpoints() {
379 return this.alternateEndpoints;
380 }
381
382 public void setAlternateEndpoints(List<AlternateEndpoint> alternateEndpoints) {
383 this.alternateEndpoints = alternateEndpoints;
384 }
385
386 private final class ServicePublisher extends BaseLifecycle {
387
388 private final List<ServiceDefinition> serviceDefinitions;
389
390 ServicePublisher(List<ServiceDefinition> serviceDefinitions) {
391 this.serviceDefinitions = serviceDefinitions;
392 }
393
394 @Override
395 public void start() throws Exception {
396 if (serviceDefinitions != null && !serviceDefinitions.isEmpty()) {
397 LOG.debug("Configuring " + serviceDefinitions.size() + " services for application id " + CoreConfigHelper.getApplicationId() + " using config for classloader " + ClassLoaderUtils.getDefaultClassLoader());
398 KsbApiServiceLocator.getServiceBus().publishServices(serviceDefinitions, true);
399 super.start();
400 }
401 }
402
403 }
404
405 }