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