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