Issue #2726: Edex graceful shutdown.

Refactored to use inheritance and separate logic where possible.
             Addressed comments.

Change-Id: I9e62414cd83121575bdf99a3b47466a7585bedb6

Former-commit-id: 6e015b3f61c20635077d6e8271e9b763e5a32fe1
This commit is contained in:
Richard Peter 2014-03-19 14:23:52 -05:00
parent 7e8e756798
commit dbba727f3d
206 changed files with 3562 additions and 2865 deletions

View file

@ -31,6 +31,7 @@ import org.eclipse.ui.statushandlers.StatusManager;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.message.WsId; import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.util.SystemUtil;
import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.core.localization.LocalizationManager;
/** /**
@ -49,7 +50,7 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
* Aug 27, 2013 2295 bkowal Removed the jms server property; added * Aug 27, 2013 2295 bkowal Removed the jms server property; added
* jms connection string * jms connection string
* Feb 17, 2014 2812 njensen getHostName() now uses getWsId()'s hostname * Feb 17, 2014 2812 njensen getHostName() now uses getWsId()'s hostname
* * Mar 20, 2014 2726 rjpeter Moved host processing to SystemUtil.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -252,21 +253,13 @@ public final class VizApp {
private static String host = null; private static String host = null;
/** /**
* Gets the host name from the WsId of the host machine calling the function * Gets the host name of the machine calling the function
* *
* @return * @return
*/ */
public static synchronized String getHostName() { public static synchronized String getHostName() {
if (host == null) { if (host == null) {
host = getWsId().getHostName(); host = SystemUtil.getHostName();
if (host == null) {
String hostname = System.getenv("HOSTNAME");
if (hostname != null && hostname.trim().length() > 0) {
host = hostname;
} else {
host = "localhost";
}
}
} }
return host; return host;
} }

View file

@ -233,7 +233,6 @@
<UTILITYDIR>utilityDir</UTILITYDIR> <UTILITYDIR>utilityDir</UTILITYDIR>
<STATICDIR>staticDir</STATICDIR> <STATICDIR>staticDir</STATICDIR>
<SITENAME>sitename</SITENAME> <SITENAME>sitename</SITENAME>
<GFESMARTINIT>gfeSmartInitEnable</GFESMARTINIT>
<LOGDIR>logDir</LOGDIR> <LOGDIR>logDir</LOGDIR>
<FXADEBUGSAVEBADTEXTFILES>fxaDebugSaveBadTextFiles</FXADEBUGSAVEBADTEXTFILES> <FXADEBUGSAVEBADTEXTFILES>fxaDebugSaveBadTextFiles</FXADEBUGSAVEBADTEXTFILES>
<ARCHIVEDIR>archiveDir</ARCHIVEDIR> <ARCHIVEDIR>archiveDir</ARCHIVEDIR>

View file

@ -48,7 +48,6 @@
<shareDir>${env:edex.home}/data/share</shareDir> <shareDir>${env:edex.home}/data/share</shareDir>
<utilityDir>${env:edex.home}/data/utility</utilityDir> <utilityDir>${env:edex.home}/data/utility</utilityDir>
<staticDir>${env:edex.home}/data/static</staticDir> <staticDir>${env:edex.home}/data/static</staticDir>
<gfeSmartInitEnable>true</gfeSmartInitEnable>
<fxaDebugSaveBadTextFiles>false</fxaDebugSaveBadTextFiles> <fxaDebugSaveBadTextFiles>false</fxaDebugSaveBadTextFiles>
<svcBackupDir>${env:edex.home}/../GFESuite/</svcBackupDir> <svcBackupDir>${env:edex.home}/../GFESuite/</svcBackupDir>
<mhsData>/data/fxa/mhs</mhsData> <mhsData>/data/fxa/mhs</mhsData>

View file

@ -1,7 +0,0 @@
# The following properties are used to define the EDEX system configuration.
# Modifying these values will affect system performance.
smartinit.threadpoolsize=3
# smartinit.threads should be 2 less than smartinit.threadpoolszie
# to account for reading from the notify topic and the manual queue
smartinit.threads=1

View file

@ -1,7 +0,0 @@
# The following properties are used to define the EDEX system configuration.
# Modifying these values will affect system performance.
smartinit.threadpoolsize=4
# smartinit.threads should be 2 less than smartinit.threadpoolszie
# to account for reading from the notify topic and the manual queue
smartinit.threads=2

View file

@ -8,7 +8,7 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd"> http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<!-- Separated out database specific beans to seperate file so they can be loaded by themselves if necessary --> <!-- Separated out database specific beans to separate file so they can be loaded by themselves if necessary -->
<import resource="file:///${edex.home}/conf/spring/edex-db.xml"/> <import resource="file:///${edex.home}/conf/spring/edex-db.xml"/>
<!-- specify the connection to the broker (qpid) --> <!-- specify the connection to the broker (qpid) -->
@ -65,11 +65,13 @@
<property name="cacheLevelName" value="CACHE_NONE"/> <property name="cacheLevelName" value="CACHE_NONE"/>
<property name="recoveryInterval" value="10000"/> <property name="recoveryInterval" value="10000"/>
<property name="requestTimeout" value="5000"/> <property name="requestTimeout" value="5000"/>
<!-- If this is false, while stopping we will reject messages that have already been pulled from qpid, essentially losing the message -->
<property name="acceptMessagesWhileStopping" value="true"/>
<!-- receiveTimeout is amount of time thread waits to receive a message before recycling --> <!-- receiveTimeout is amount of time thread waits to receive a message before recycling -->
<!-- receiveTimeout also affects how fast a JMSConsumer will shut down, because the <!-- receiveTimeout also affects how fast a JMSConsumer will shut down, because the
thread may be stuck polling for the duration of receiveTimeout before shutting down --> thread may be stuck polling for the duration of receiveTimeout before shutting down -->
<property name="receiveTimeout" value="10000"/> <property name="receiveTimeout" value="5000"/>
<property name="transacted" value="false"/> <property name="transacted" value="false"/>
<!-- force maxMessagesPerTask so that the threads don't keep disconnecting and reconnecting. <!-- force maxMessagesPerTask so that the threads don't keep disconnecting and reconnecting.
@ -110,7 +112,7 @@
<bean id="pypiesStoreProps" class="com.raytheon.uf.common.pypies.PypiesProperties"> <bean id="pypiesStoreProps" class="com.raytheon.uf.common.pypies.PypiesProperties">
<property name="address" value="${PYPIES_SERVER}" /> <property name="address" value="${PYPIES_SERVER}" />
</bean> </bean>
<bean id="pypiesDataStoreFactory" class="com.raytheon.uf.common.pypies.PyPiesDataStoreFactory"> <bean id="pypiesDataStoreFactory" class="com.raytheon.uf.common.pypies.PyPiesDataStoreFactory" depends-on="httpClient">
<constructor-arg ref="pypiesStoreProps" /> <constructor-arg ref="pypiesStoreProps" />
</bean> </bean>
@ -119,7 +121,6 @@
<property name="underlyingFactory" ref="pypiesDataStoreFactory"/> <property name="underlyingFactory" ref="pypiesDataStoreFactory"/>
</bean> </bean>
<bean id="initialcorePropertyConfigurer" <bean id="initialcorePropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName"> <property name="systemPropertiesModeName">
@ -136,21 +137,55 @@
<bean id="processUtil" class="com.raytheon.uf.edex.esb.camel.ProcessUtil"/> <bean id="processUtil" class="com.raytheon.uf.edex.esb.camel.ProcessUtil"/>
<bean id="setIngestHeaderFields" class="com.raytheon.uf.edex.esb.camel.SetIngestHeaderFields"/> <bean id="setIngestHeaderFields" class="com.raytheon.uf.edex.esb.camel.SetIngestHeaderFields"/>
<bean id="uuidGenerator" class="com.raytheon.uf.edex.esb.camel.UUIDGenerator"/> <bean id="uuidGenerator" class="com.raytheon.uf.edex.esb.camel.UUIDGenerator"/>
<bean id="messageUtil" class="com.raytheon.uf.edex.esb.camel.MessageProducer" /> <bean id="messageProducer" class="com.raytheon.uf.edex.esb.camel.MessageProducer" />
<bean id="camelContextAdmin" class="com.raytheon.uf.edex.esb.camel.CamelContextAdmin" /> <bean id="camelContextAdmin" class="com.raytheon.uf.edex.esb.camel.CamelContextAdmin" />
<!-- ContextManager to manage dependencies so routes startup in right order.
Clustered routes will start on a box if there has not been a lock for that route in the last 60 seconds.
Anyone using the clustered routes should ensure that timeToLive on jms messages are at least 1 minute-->
<bean id="contextManager"
class="com.raytheon.uf.edex.esb.camel.context.ContextManager"
factory-method="getInstance">
<property name="timeOutMillis" value="60000"/>
</bean>
<bean id="util" class="com.raytheon.uf.edex.core.EDEXUtil"> <bean id="util" class="com.raytheon.uf.edex.core.EDEXUtil">
<property name="messageProducer" ref="messageUtil" /> <property name="messageProducer" ref="messageProducer" />
<property name="contextAdmin" ref="camelContextAdmin" /> <property name="contextAdmin" ref="camelContextAdmin" />
</bean> </bean>
<bean id="initSystem" class="com.raytheon.edex.plugin.InitializerBean" />
<bean id="defaultPathProvider" class="com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider"/> <bean id="defaultPathProvider" class="com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider"/>
<bean id="commonDbPluginProperties" class="com.raytheon.uf.edex.database.DatabasePluginProperties">
<property name="pluginFQN" value="com.raytheon.uf.edex.database" />
<property name="database" value="metadata" />
<property name="forceCheck" value="true" />
</bean>
<bean
id="dbPluginRegistry"
class="com.raytheon.uf.edex.database.DatabasePluginRegistry"
factory-method="getInstance"
init-method="init"
depends-on="metadataTxManager">
<property name="initialListeners">
<list>
<!-- This causes database tables to be initialized when a db plugin is registered -->
<bean class="com.raytheon.uf.edex.database.schema.SchemaManager" factory-method="getInstance"/>
</list>
</property>
<property name="initialProperties">
<list>
<!-- Creates the initial tables so other plugins can be loaded -->
<ref bean="commonDbPluginProperties"/>
</list>
</property>
</bean>
<!-- The pluginDefaults are the values that a data plugin will use for <!-- The pluginDefaults are the values that a data plugin will use for
some plugin properties if they are not specified in the individual some plugin properties if they are not specified in the individual
plugin's Spring XML configuration --> plugin's Spring XML configuration -->
<bean id="pluginDefaults" class="com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults"> <bean id="pluginDefaults" class="com.raytheon.uf.common.dataplugin.PluginProperties">
<property name="database" value="metadata" /> <property name="database" value="metadata" />
<property name="initializer" value="com.raytheon.edex.plugin.DefaultPluginInitializer" /> <property name="initializer" value="com.raytheon.edex.plugin.DefaultPluginInitializer" />
<property name="dao" value="com.raytheon.edex.db.dao.DefaultPluginDao" /> <property name="dao" value="com.raytheon.edex.db.dao.DefaultPluginDao" />
@ -158,24 +193,21 @@
<property name="pathProvider" ref="defaultPathProvider"/> <property name="pathProvider" ref="defaultPathProvider"/>
</bean> </bean>
<!-- This causes database tables to be initialized when a db plugin is registered --> <bean
<bean id="schemaManager" class="com.raytheon.uf.edex.database.schema.SchemaManager" id="pluginRegistry"
factory-method="getInstance" /> class="com.raytheon.uf.edex.core.dataplugin.PluginRegistry"
factory-method="getInstance"
<bean factory-bean="dbPluginRegistry" factory-method="addListener"> depends-on="util, dataStoreFactory">
<constructor-arg><ref bean="schemaManager"/></constructor-arg> <property name="defaultPluginProperties" ref="pluginDefaults"/>
</bean> <property name="initialListeners">
<list>
<!-- This causes the data plugin's database tables to be created when a plugin is registered --> <!-- This causes the data plugin's database tables to be created when a plugin is registered -->
<bean id="dbPluginRegistryListenerAdded" factory-bean="pluginRegistry" factory-method="addListener"> <ref bean="dbPluginRegistry"/>
<constructor-arg><ref bean="dbPluginRegistry"/></constructor-arg> <!-- This causes the data plugin's initializer to get called when a plugin is registered -->
<bean class="com.raytheon.edex.plugin.PluginInitialSetup"/>
</list>
</property>
</bean> </bean>
<!-- This causes the data plugin's initializer to get called when a plugin
is registered -->
<bean id="pluginSetup" class="com.raytheon.edex.plugin.PluginInitialSetup" />
<bean factory-bean="pluginRegistry" factory-method="addListener" depends-on="dbPluginRegistryListenerAdded">
<constructor-arg><ref bean="pluginSetup"/></constructor-arg>
</bean>
<bean id="stringToFile" class="com.raytheon.uf.edex.esb.camel.StringToFile"/> <bean id="stringToFile" class="com.raytheon.uf.edex.esb.camel.StringToFile"/>
<bean id="extractWMOHeader" class="com.raytheon.uf.common.util.header.WMOHeaderRemover"/> <bean id="extractWMOHeader" class="com.raytheon.uf.common.util.header.WMOHeaderRemover"/>
@ -195,37 +227,9 @@
<bean id="serializationUtil" class="com.raytheon.uf.common.serialization.SerializationUtil" /> <bean id="serializationUtil" class="com.raytheon.uf.common.serialization.SerializationUtil" />
<bean id="pluginRegistry" class="com.raytheon.uf.edex.core.dataplugin.PluginRegistry" factory-method="getInstance"/>
<bean id="dbPluginRegistry" class="com.raytheon.uf.edex.database.DatabasePluginRegistry" factory-method="getInstance"/>
<bean id="commonDbPluginProperties" class="com.raytheon.uf.edex.database.DatabasePluginProperties">
<property name="pluginFQN" value="com.raytheon.uf.edex.database" />
<property name="database" value="metadata" />
<property name="forceCheck" value="true" />
</bean>
<bean id="commonDbRegistered" factory-bean="dbPluginRegistry" factory-method="register"
depends-on="metadataTxManager">
<constructor-arg value="com.raytheon.uf.edex.database"/>
<constructor-arg ref="commonDbPluginProperties"/>
</bean>
<bean id="CamelBeanParameterMappingStrategy" <bean id="CamelBeanParameterMappingStrategy"
class="com.raytheon.uf.edex.esb.camel.EDEXParameterMappingStrategy" /> class="com.raytheon.uf.edex.esb.camel.EDEXParameterMappingStrategy" />
<!-- ContextManager to start camel context last. Ensures items such as distribution aren't started before all the listening routes are up -->
<bean id="contextManager"
class="com.raytheon.uf.edex.esb.camel.context.ContextManager"
factory-method="getInstance">
</bean>
<!-- Clustered routes will start on a box if there has not been a lock for that route in the last 60 seconds.
Anyone using the clustered routes should ensure that timeToLive on jms messages are at least 1 minute -->
<bean id="clusteredCamelContextMgr"
class="com.raytheon.uf.edex.esb.camel.context.ClusteredContextManager"
factory-method="getInstance">
<property name="timeOutMillis" value="60000"/>
</bean>
<!-- Serialization Pool --> <!-- Serialization Pool -->
<bean id="baosPool" class="com.raytheon.uf.common.util.ByteArrayOutputStreamPool" factory-method="getInstance"> <bean id="baosPool" class="com.raytheon.uf.common.util.ByteArrayOutputStreamPool" factory-method="getInstance">
<property name="maxPoolSize" value="${SERIALIZE_POOL_MAX_SIZE}"/> <property name="maxPoolSize" value="${SERIALIZE_POOL_MAX_SIZE}"/>
@ -263,13 +267,6 @@
<to uri="jms-generic:topic:edex.alarms.msg" /> <to uri="jms-generic:topic:edex.alarms.msg" />
</route> </route>
<!-- Route to send geospatial data update notification -->
<route id="geospatialUpdateNotify">
<from uri="vm:edex.geospatialUpdateNotification" />
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.geospatialUpdate.msg" />
</route>
<!-- Route to periodically close any unused jms resources that have been pooled --> <!-- Route to periodically close any unused jms resources that have been pooled -->
<route id="jmsPooledResourceChecker"> <route id="jmsPooledResourceChecker">
<from uri="timer://jmsPooledResourceCheck?period=60s" /> <from uri="timer://jmsPooledResourceCheck?period=60s" />
@ -285,12 +282,11 @@
<camelContext <camelContext
id="clusteredCamel" id="clusteredCamel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="monitorClusteredContexts"> <route id="monitorClusteredContexts">
<from uri="timer://monitorClusterContexts?fixedRate=true&amp;period=20000"/> <from uri="timer://monitorClusterContexts?fixedRate=true&amp;period=20000"/>
<doTry> <doTry>
<bean ref="clusteredCamelContextMgr" method="checkClusteredContexts" /> <bean ref="contextManager" method="checkClusteredContexts" />
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
<to uri="log:monitorClusteredContexts?level=ERROR"/> <to uri="log:monitorClusteredContexts?level=ERROR"/>
@ -298,10 +294,6 @@
</doTry> </doTry>
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="clusteredCamel"/>
</bean>
<!-- Redirect geotools log --> <!-- Redirect geotools log -->
<bean class="com.raytheon.uf.common.geospatial.LogRedirector" factory-method="setGeotoolsLogFactory"> <bean class="com.raytheon.uf.common.geospatial.LogRedirector" factory-method="setGeotoolsLogFactory">
@ -314,7 +306,6 @@
<property name="locations"> <property name="locations">
<list> <list>
<value>file:${edex.home}/conf/spring/cron.properties</value> <value>file:${edex.home}/conf/spring/cron.properties</value>
<value>file:${edex.home}/conf/spring/${edex.arch}/architecture.properties</value>
</list> </list>
</property> </property>
</bean> </bean>
@ -353,14 +344,10 @@
<constructor-arg ref="requestServiceRouter" /> <constructor-arg ref="requestServiceRouter" />
</bean> </bean>
<!-- needed for camel quartz component workaround when JMX is disabled -->
<bean id="managementNameLifecycleStrategy"
class="com.raytheon.uf.edex.esb.camel.quartz.ManagementNameLifecycleStrategy" />
<!-- quartz component configuration. <!-- quartz component configuration.
Single scheduler used by all endpoints so there is only one threadpool. Single scheduler used by all endpoints so there is only one threadpool.
Thread pool configured in edex/config/resources/quartz.properties --> Thread pool configured in edex/config/resources/quartz.properties.
Requires work around in ContextManager.postProcessBeanFactory when JMX is disabled -->
<bean id="quartzSchedulerFactory" class="org.quartz.impl.StdSchedulerFactory"> <bean id="quartzSchedulerFactory" class="org.quartz.impl.StdSchedulerFactory">
<constructor-arg value="quartz.properties" /> <constructor-arg value="quartz.properties" />
</bean> </bean>
@ -376,5 +363,4 @@
class="com.raytheon.uf.edex.esb.camel.cluster.quartz.ClusteredQuartzComponent"> class="com.raytheon.uf.edex.esb.camel.cluster.quartz.ClusteredQuartzComponent">
<property name="scheduler" ref="quartzScheduler" /> <property name="scheduler" ref="quartzScheduler" />
</bean> </bean>
</beans> </beans>

View file

@ -160,6 +160,10 @@ wrapper.app.parameter.2=start
wrapper.ping.timeout=300 wrapper.ping.timeout=300
# jvm will be hard killed after 5 minutes of trying to shutdown
wrapper.jvm_exit.timeout=0
wrapper.shutdown.timeout=300
#******************************************************************** #********************************************************************
# Monitor the Application # Monitor the Application
#******************************************************************** #********************************************************************

View file

@ -23,8 +23,6 @@ export MAX_MEM=1300 # in Meg
export MAX_PERM_SIZE=128m export MAX_PERM_SIZE=128m
export EDEX_JMX_PORT=1616 export EDEX_JMX_PORT=1616
export EDEX_DEBUG_PORT=5005 export EDEX_DEBUG_PORT=5005
export JMS_POOL_MIN=64
export JMS_POOL_MAX=128
export METADATA_POOL_MIN=5 export METADATA_POOL_MIN=5
export METADATA_POOL_MAX=50 export METADATA_POOL_MAX=50
export METADATA_POOL_TIMEOUT=300 export METADATA_POOL_TIMEOUT=300

View file

@ -21,8 +21,6 @@
export INIT_MEM=256 # in Meg export INIT_MEM=256 # in Meg
export MAX_MEM=1792 # in Meg export MAX_MEM=1792 # in Meg
export JMS_POOL_MIN=16
export JMS_POOL_MAX=32
export METADATA_POOL_MIN=15 export METADATA_POOL_MIN=15
export METADATA_POOL_MAX=30 export METADATA_POOL_MAX=30
export EDEX_DEBUG_PORT=5008 export EDEX_DEBUG_PORT=5008

View file

@ -21,8 +21,6 @@
export INIT_MEM=128 # in Meg export INIT_MEM=128 # in Meg
export MAX_MEM=512 # in Meg export MAX_MEM=512 # in Meg
export JMS_POOL_MIN=4
export JMS_POOL_MAX=16
export METADATA_POOL_MIN=4 export METADATA_POOL_MIN=4
export METADATA_POOL_MAX=10 export METADATA_POOL_MAX=10
export EDEX_DEBUG_PORT=5007 export EDEX_DEBUG_PORT=5007

View file

@ -29,8 +29,6 @@ export SERIALIZE_STREAM_INIT_SIZE_MB=2
export SERIALIZE_STREAM_MAX_SIZE_MB=8 export SERIALIZE_STREAM_MAX_SIZE_MB=8
export JMS_POOL_MIN=16
export JMS_POOL_MAX=32
export EDEX_DEBUG_PORT=5005 export EDEX_DEBUG_PORT=5005
export EDEX_JMX_PORT=1616 export EDEX_JMX_PORT=1616
export MGMT_PORT=9601 export MGMT_PORT=9601

View file

@ -29,8 +29,6 @@ export SERIALIZE_STREAM_INIT_SIZE_MB=2
export SERIALIZE_STREAM_MAX_SIZE_MB=8 export SERIALIZE_STREAM_MAX_SIZE_MB=8
export JMS_POOL_MIN=8
export JMS_POOL_MAX=24
export EDEX_DEBUG_PORT=5005 export EDEX_DEBUG_PORT=5005
export EDEX_JMX_PORT=1616 export EDEX_JMX_PORT=1616
export MGMT_PORT=9601 export MGMT_PORT=9601

View file

@ -1,72 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This class is instantiated on startup by the ESB spring container context
* before any other beans. Therefore, any system level initialization activities
* may be placed here.
* <p>
* The basic functionality of this class will initialize all the plugins
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 02/06/09 1990 bphillip Initial creation
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class InitializerBean {
/** The logger */
protected transient Log logger = LogFactory.getLog(getClass());
/**
* Creates a new Initializer bean
* <p>
* This bean should never be explicitly instantiated
*/
public InitializerBean() {
// Check to see if the plugin version table exists. If not, the schema
// needs to be exported to the database
/*
* pvd = new PluginVersionDao(); if (!pvd.isDbInitialized()) {
* logger.warn("Databases have not been initialized...");
* logger.info("Initializing Databases...");
* logger.info("Exporting common table ddls...");
* SchemaManager.getInstance().createCommonTables();
* logger.info("Running setup scripts..."); try {
* SchemaManager.getInstance().runCommonScripts(); } catch
* (PluginException e) { logger.fatal("ERROR RUNNING COMMON SCRIPTS!",
* e); }
*
* }
*/
logger.info("Database initialization complete!");
}
}

View file

@ -12,15 +12,13 @@
<constructor-arg value="jms-durable:queue:Ingest.binlightning" /> <constructor-arg value="jms-durable:queue:Ingest.binlightning" />
</bean> </bean>
<bean id="binlightningCamelRegistered" factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="clusteredBinLightningRoutes" /> <constructor-arg ref="clusteredBinLightningRoutes" />
</bean> </bean>
<camelContext id="clusteredBinLightningRoutes" <camelContext id="clusteredBinLightningRoutes"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="binlightningFileEndpoint" <endpoint id="binlightningFileEndpoint"
uri="file:${edex.home}/data/sbn/binlightning?noop=true&amp;idempotent=false" /> uri="file:${edex.home}/data/sbn/binlightning?noop=true&amp;idempotent=false" />

View file

@ -11,15 +11,9 @@
<constructor-arg value="jms-durable:queue:Ingest.bufrmos" /> <constructor-arg value="jms-durable:queue:Ingest.bufrmos" />
</bean> </bean>
<bean id="bufrmosCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="bufrmos-camel"/>
</bean>
<camelContext id="bufrmos-camel" <camelContext id="bufrmos-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="bufrmosFileEndpoint" <endpoint id="bufrmosFileEndpoint"
uri="file:${edex.home}/data/sbn/bufrmos?noop=true&amp;idempotent=false" /> uri="file:${edex.home}/data/sbn/bufrmos?noop=true&amp;idempotent=false" />

View file

@ -14,11 +14,6 @@
<constructor-arg value="jms-durable:queue:Ingest.bufrua" /> <constructor-arg value="jms-durable:queue:Ingest.bufrua" />
</bean> </bean>
<bean id="bufruaCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="bufrua-camel"/>
</bean>
<bean id="raobListener" class="com.raytheon.edex.plugin.bufrua.ingest.RAOBSubscriber" /> <bean id="raobListener" class="com.raytheon.edex.plugin.bufrua.ingest.RAOBSubscriber" />
<bean factory-bean="ndmProc" factory-method="registerListener"> <bean factory-bean="ndmProc" factory-method="registerListener">
@ -36,8 +31,7 @@
<camelContext id="bufrua-camel" <camelContext id="bufrua-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="bufruaFileEndpoint" uri="file:${edex.home}/data/sbn/bufrua?noop=true&amp;idempotent=false"/> <endpoint id="bufruaFileEndpoint" uri="file:${edex.home}/data/sbn/bufrua?noop=true&amp;idempotent=false"/>

View file

@ -12,14 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ccfp" /> <constructor-arg value="jms-durable:queue:Ingest.ccfp" />
</bean> </bean>
<bean id="ccfpCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ccfp-camel"/>
</bean>
<camelContext id="ccfp-camel" <camelContext id="ccfp-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- <!--
<endpoint id="ccfpFileEndpoint" uri="file:${edex.home}/data/sbn/ccfp?noop=true&amp;idempotent=false" /> <endpoint id="ccfpFileEndpoint" uri="file:${edex.home}/data/sbn/ccfp?noop=true&amp;idempotent=false" />

View file

@ -2,4 +2,5 @@ source.. = src/
output.. = bin/ output.. = bin/
bin.includes = META-INF/,\ bin.includes = META-INF/,\
.,\ .,\
res/ res/,\
resources/

View file

@ -28,7 +28,7 @@
</bean> </bean>
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation" factory-method="getInstance" <bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation" factory-method="getInstance"
depends-on="commonTimeRegistered, gfeRegistered"> depends-on="commonTimeRegistered, gfeDbRegistered">
</bean> </bean>
<bean id="gfeNotifyFilter" class="com.raytheon.edex.plugin.gfe.server.notify.GfeNotificationFilter"/> <bean id="gfeNotifyFilter" class="com.raytheon.edex.plugin.gfe.server.notify.GfeNotificationFilter"/>
@ -36,7 +36,6 @@
<bean id="ifpServer" class="com.raytheon.edex.plugin.gfe.server.IFPServer.Wrapper"/> <bean id="ifpServer" class="com.raytheon.edex.plugin.gfe.server.IFPServer.Wrapper"/>
<camelContext id="gfe-common-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> <camelContext id="gfe-common-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<route id="gfeNotify"> <route id="gfeNotify">
<from uri="vm:edex.gfeNotification?size=5000"/> <from uri="vm:edex.gfeNotification?size=5000"/>
<doTry> <doTry>

View file

@ -344,19 +344,14 @@
<!-- ISC Send Beans --> <!-- ISC Send Beans -->
<bean id="iscSendQueue" class="com.raytheon.edex.plugin.gfe.isc.IscSendQueue" factory-method="getInstance"/> <bean id="iscSendQueue" class="com.raytheon.edex.plugin.gfe.isc.IscSendQueue" factory-method="getInstance"/>
<bean id="iscSendThreadPool" class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor"> <bean id="sendIscSrv" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrv" depends-on="gfeDbRegistered, gfeSitesActiveRequest">
<property name="corePoolSize" value="1" />
<property name="maxPoolSize" value="1" />
</bean>
<bean id="iscSendSrvCfg" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrvConfig">
<property name="executor" ref="iscSendThreadPool"/>
<!-- Threads should be same size as the iscSendThreadPool -->
<property name="threads" value="1"/>
<property name="runningTimeOutMillis" value="300000"/> <property name="runningTimeOutMillis" value="300000"/>
<property name="threadSleepInterval" value="5000"/> <property name="threadSleepInterval" value="5000"/>
</bean> </bean>
<bean depends-on="gfeDbRegistered, gfeSitesActiveRequest" id="sendIscSrv" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrv">
<constructor-arg ref="iscSendSrvCfg"/> <bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
<constructor-arg ref="gfe-request-camel"/>
<constructor-arg ref="sendIscSrv"/>
</bean> </bean>
<!-- End ISC Send Beans --> <!-- End ISC Send Beans -->
@ -420,6 +415,7 @@
<endpoint id="exportDigitalDataCron" uri="clusteredquartz://gfe/exportDigitalData/?cron=${gfe.cron}"/> <endpoint id="exportDigitalDataCron" uri="clusteredquartz://gfe/exportDigitalData/?cron=${gfe.cron}"/>
<endpoint id="gfeLogPurgeCron" uri="clusteredquartz://gfe/purgeGfeLogs/?cron=${purge.logs.cron}"/> <endpoint id="gfeLogPurgeCron" uri="clusteredquartz://gfe/purgeGfeLogs/?cron=${purge.logs.cron}"/>
<endpoint id="svcbuLogPurgeCron" uri="clusteredquartz://gfe/purgeSvcbuLogs/?cron=${purge.svcbu.logs.cron}"/> <endpoint id="svcbuLogPurgeCron" uri="clusteredquartz://gfe/purgeSvcbuLogs/?cron=${purge.svcbu.logs.cron}"/>
<endpoint id="iscSendLauncher" uri="timer://iscSendThread?repeatCount=1"/>
<route id="exportDigitalData"> <route id="exportDigitalData">
<from uri="exportDigitalDataCron"/> <from uri="exportDigitalDataCron"/>
@ -488,11 +484,16 @@
</doCatch> </doCatch>
</doTry> </doTry>
</route> </route>
<!-- Thread runs for life of context -->
<route id="iscSendThread">
<from ref="iscSendLauncher"/>
<bean ref="sendIscSrv" method="run"/>
</route>
</camelContext> </camelContext>
<!-- ISC Send Routes --> <!-- ISC Send Routes -->
<camelContext id="clusteredGfeIscRoutes" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler" <camelContext id="clusteredGfeIscRoutes" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="iscSendJobQueueAggr"> <route id="iscSendJobQueueAggr">
<from uri="jms-durable:queue:iscSendNotification" /> <from uri="jms-durable:queue:iscSendNotification" />
@ -512,7 +513,7 @@
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" factory-method="register"> <bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredGfeIscRoutes"/> <constructor-arg ref="clusteredGfeIscRoutes"/>
</bean> </bean>
</beans> </beans>

View file

@ -4,24 +4,20 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="smartInitQueue" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitQueue" factory-method="createQueue"/> <bean id="smartInitQueue" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitQueue" factory-method="createQueue"/>
<bean id="smartInitThreadPool" class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor">
<property name="corePoolSize" value="${smartinit.threads}" /> <bean id="gfeSitesActiveIngest" factory-bean="siteAwareRegistry" factory-method="register" depends-on="smartInitQueue">
<property name="maxPoolSize" value="${smartinit.threads}" /> <constructor-arg ref="gfeSiteActivation"/>
</bean> </bean>
<bean id="smartInitSrvCfg" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrvConfig">
<property name="executor" ref="smartInitThreadPool"/> <bean id="smartInitSrv" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrv" depends-on="gfeDbRegistered, gfeSitesActiveIngest">
<property name="threads" value="${smartinit.threads}"/>
<property name="pendingInitMinTimeMillis" value="120000"/> <property name="pendingInitMinTimeMillis" value="120000"/>
<property name="runningInitTimeOutMillis" value="600000"/> <property name="runningInitTimeOutMillis" value="600000"/>
<property name="threadSleepInterval" value="30000"/> <property name="threadSleepInterval" value="30000"/>
</bean> </bean>
<bean depends-on="smartInitQueue" id="gfeSitesActiveIngest" factory-bean="siteAwareRegistry" factory-method="register"> <bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
<constructor-arg ref="gfeSiteActivation"/> <constructor-arg ref="gfe-camel-spring"/>
</bean> <constructor-arg ref="smartInitSrv"/>
<bean depends-on="gfeDbRegistered, gfeSitesActiveIngest" id="smartInitSrv" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrv">
<constructor-arg ref="smartInitSrvCfg"/>
</bean> </bean>
<bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.spc.SPCWatchSrv"/> <bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.spc.SPCWatchSrv"/>
@ -31,6 +27,8 @@
<bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/> <bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/>
<camelContext id="gfe-camel-spring" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> <camelContext id="gfe-camel-spring" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="smartInitLauncher" uri="timer://smartInitThread?repeatCount=${smartinit.threads}"/>
<route id="SPCWatch"> <route id="SPCWatch">
<from uri="vm:gfe.spcWatch"/> <from uri="vm:gfe.spcWatch"/>
<doTry> <doTry>
@ -72,6 +70,12 @@
<bean ref="smartInitQueue" method="fireSmartInit"/> <bean ref="smartInitQueue" method="fireSmartInit"/>
</route> </route>
<!-- Thread runs for life of context -->
<route id="smartInitThread">
<from ref="smartInitLauncher"/>
<bean ref="smartInitSrv" method="run"/>
</route>
<route id="gfeIngestNotification"> <route id="gfeIngestNotification">
<!-- Data from plugin notification --> <!-- Data from plugin notification -->
<from <from
@ -103,7 +107,7 @@
</camelContext> </camelContext>
<camelContext id="clusteredGfeIngestRoutes" xmlns="http://camel.apache.org/schema/spring" <camelContext id="clusteredGfeIngestRoutes" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- Smart Init Routes --> <!-- Smart Init Routes -->
<!-- main route now handled through the gfeIngestNotification --> <!-- main route now handled through the gfeIngestNotification -->
@ -134,7 +138,7 @@
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" factory-method="register"> <bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredGfeIngestRoutes"/> <constructor-arg ref="clusteredGfeIngestRoutes"/>
</bean> </bean>
</beans> </beans>

View file

@ -0,0 +1,2 @@
# The number of smart init threads to use
smartinit.threads=2

View file

@ -73,6 +73,7 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications;
* May 02, 2013 #1969 randerso Moved updateDbs method into IFPGridDatabase * May 02, 2013 #1969 randerso Moved updateDbs method into IFPGridDatabase
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer * Jun 13, 2013 #2044 randerso Refactored to use IFPServer
* Oct 16, 2013 #2475 dgilling Better error handling for IRT activation. * Oct 16, 2013 #2475 dgilling Better error handling for IRT activation.
* Mar 21, 2014 2726 rjpeter Updated wait for running loop.
* </pre> * </pre>
* *
* @author njensen * @author njensen
@ -87,14 +88,8 @@ public class GFESiteActivation implements ISiteActivationListener {
private static final String INIT_TASK_DETAILS = "Initialization:"; private static final String INIT_TASK_DETAILS = "Initialization:";
private static final String SMART_INIT_TASK_DETAILS = "SmartInit:";
private static final int LOCK_TASK_TIMEOUT = 180000; private static final int LOCK_TASK_TIMEOUT = 180000;
// don't rerun the smart init fire if they have been run in the last 30
// minutes
private static final int SMART_INIT_TIMEOUT = 1800000;
private static GFESiteActivation instance = new GFESiteActivation(); private static GFESiteActivation instance = new GFESiteActivation();
private boolean intialized = false; private boolean intialized = false;
@ -297,7 +292,7 @@ public class GFESiteActivation implements ISiteActivationListener {
statusHandler.info("IFPServerConfigManager initializing..."); statusHandler.info("IFPServerConfigManager initializing...");
config = IFPServerConfigManager.initializeSite(siteID); config = IFPServerConfigManager.initializeSite(siteID);
statusHandler.info("Activating IFPServer..."); statusHandler.info("Activating IFPServer...");
IFPServer ifpServer = IFPServer.activateServer(siteID, config); IFPServer.activateServer(siteID, config);
} finally { } finally {
statusHandler statusHandler
.handle(Priority.INFO, .handle(Priority.INFO,
@ -345,16 +340,7 @@ public class GFESiteActivation implements ISiteActivationListener {
@Override @Override
public void run() { public void run() {
long startTime = System.currentTimeMillis(); EDEXUtil.waitForRunning();
// wait for system startup or at least 3 minutes
while (!EDEXUtil.isRunning()
|| (System.currentTimeMillis() > (startTime + 180000))) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
}
}
Map<String, Object> fetchATConfig = new HashMap<String, Object>(); Map<String, Object> fetchATConfig = new HashMap<String, Object>();
fetchATConfig.put("siteId", configRef.getSiteID().get(0)); fetchATConfig.put("siteId", configRef.getSiteID().get(0));

View file

@ -1,267 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.isc;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.edex.plugin.gfe.server.database.GridDatabase;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridHistoryUpdateNotification;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.core.EDEXUtil;
/**
* Class to for running the isc scripts
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/06/09 1995 bphillip Initial release
* 04/06/12 #457 dgilling Move call to delete records
* from queue into run().
* 04/23/13 #1949 rjpeter Move setting of lastSentTime to dao
* and removed initial delay.
* 06/13/13 2044 randerso Refactored to use IFPServer
* </pre>
*
* @author bphillip
* @version 1
*/
public class IscSendJob implements Runnable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(IscSendJob.class);
/** Date format for formatting dates for use with iscExtract script */
private static final SimpleDateFormat ISC_EXTRACT_DATE = new SimpleDateFormat(
"yyyyMMdd_HHmm");
private final Map<String, IscSendScript> scripts;
private int runningTimeOutMillis;
private int threadSleepInterval;
/**
* Constructs a new IscSendJob
*
* @param siteID
* the site ID
*
* @param cmdQueue
*/
public IscSendJob() {
scripts = new HashMap<String, IscSendScript>();
runningTimeOutMillis = 300000;
threadSleepInterval = 30000;
}
@Override
public void run() {
while (!EDEXUtil.isRunning()) {
try {
Thread.sleep(threadSleepInterval);
} catch (Throwable t) {
// ignore
}
}
try {
// run forever
while (true) {
IscSendRecord record = SendIscTransactions
.getNextSendJob(runningTimeOutMillis);
if (record != null) {
runIscSend(record);
SendIscTransactions.removeSendJob(record);
} else {
try {
Thread.sleep(threadSleepInterval);
} catch (Exception e) {
// ignore
}
}
}
} finally {
// Make sure OS resources are released at thread death
for (IscSendScript script : scripts.values()) {
script.dispose();
}
}
}
private void runIscSend(IscSendRecord request) {
try {
ParmID id = request.getParmID();
TimeRange tr = request.getTimeRange();
String xmlDest = request.getXmlDest();
String siteId = id.getDbId().getSiteId();
if (!GFESiteActivation.getInstance().getActiveSites()
.contains(siteId)) {
statusHandler.warn("Attempted to send " + id
+ " for deactivated site " + siteId + ".");
return;
}
statusHandler.info("Starting isc for " + id.toString() + " "
+ tr.toString() + " " + xmlDest);
Map<String, Object> cmd = new HashMap<String, Object>();
cmd.put("parmNames", Arrays.asList(id.getParmName()));
cmd.put("databaseName", id.getDbId().getModelId());
cmd.put("startTime", ISC_EXTRACT_DATE.format(tr.getStart()));
cmd.put("endTime", ISC_EXTRACT_DATE.format(tr.getEnd()));
// destination server XML, might be empty
// the -D switch is a file location containing the xml
// information
if (!xmlDest.isEmpty()) {
cmd.put("destinations", xmlDest);
}
try {
IFPServerConfig config = IFPServerConfigManager
.getServerConfig(siteId);
// IRT table address
cmd.put("irtTableAddressA", config.iscRoutingTableAddress()
.get("ANCF"));
cmd.put("irtTableAddressB", config.iscRoutingTableAddress()
.get("BNCF"));
// xmt script
cmd.put("transmitScript", config.transmitScript());
// our server host, port, protocol, our mhs id, and our site id
cmd.put("ourServerHost", config.getServerHost());
cmd.put("ourServerPort", String.valueOf(config.getRpcPort()));
cmd.put("ourServerProtocol",
String.valueOf(config.getProtocolVersion()));
cmd.put("ourMHSid", config.getMhsid());
cmd.put("ourSiteID", config.getSiteID().get(0));
} catch (GfeConfigurationException e) {
statusHandler.error(
"Unable to retrieve site configuration for site "
+ siteId, e);
return;
}
try {
IscSendScript script = scripts.get(siteId);
if (script == null) {
script = IscSendScriptFactory
.constructIscSendScript(siteId);
scripts.put(siteId, script);
}
script.execute(cmd);
} catch (JepException e) {
statusHandler.error("Error executing iscExtract.", e);
return;
}
try {
DatabaseID dbId = id.getDbId();
IFPServer ifpServer = IFPServer.getActiveServer(dbId
.getSiteId());
if (ifpServer != null) {
GridDatabase gridDb = ifpServer.getGridParmMgr()
.getDatabase(dbId);
if (gridDb != null) {
ServerResponse<Map<TimeRange, List<GridDataHistory>>> sr = gridDb
.updateSentTime(id, tr, new Date());
if (sr.isOkay()) {
WsId wsId = new WsId(InetAddress.getLocalHost(),
"ISC", "ISC");
List<GridHistoryUpdateNotification> notifications = new ArrayList<GridHistoryUpdateNotification>(
1);
Map<TimeRange, List<GridDataHistory>> histories = sr
.getPayload();
notifications
.add(new GridHistoryUpdateNotification(id,
histories, wsId, siteId));
SendNotifications.send(notifications);
} else {
statusHandler
.error("Error updating last sent times in GFERecords: "
+ sr.getMessages());
}
} else {
// no such database exists
statusHandler
.error("Error processing ISC send request for :"
+ dbId
+ ", the database does not exist.");
}
} else {
// no active server for request
statusHandler
.error("Error processing ISC send request for :"
+ dbId + ", no active IFPServer for site.");
}
} catch (Exception e) {
statusHandler.error(
"Error updating last sent times in GFERecords.", e);
}
} catch (Throwable t) {
statusHandler.error("Exception in ISCSendJob: ", t);
}
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -19,7 +19,33 @@
**/ **/
package com.raytheon.edex.plugin.gfe.isc; package com.raytheon.edex.plugin.gfe.isc;
import java.util.concurrent.Executor; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.edex.plugin.gfe.server.database.GridDatabase;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridHistoryUpdateNotification;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.core.EdexTimerBasedThread;
/** /**
* Service that runs ISC send jobs. Along with IscSendQueue, this class roughly * Service that runs ISC send jobs. Along with IscSendQueue, this class roughly
@ -32,27 +58,182 @@ import java.util.concurrent.Executor;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Oct 20, 2011 dgilling Initial creation * Oct 20, 2011 dgilling Initial creation
* * May 19, 2014 2726 rjpeter Integrate IscSendJob for graceful shutdown.
* </pre> * </pre>
* *
* @author dgilling * @author dgilling
* @version 1.0 * @version 1.0
*/ */
public class SendIscSrv { public class SendIscSrv extends EdexTimerBasedThread {
private final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SendIscSrv.class);
private final SendIscSrvConfig cfg; protected int runningTimeOutMillis;
private final Executor executor; /** Date format for formatting dates for use with iscExtract script */
protected static final SimpleDateFormat ISC_EXTRACT_DATE = new SimpleDateFormat(
"yyyyMMdd_HHmm");
public SendIscSrv(SendIscSrvConfig config) { protected final ThreadLocal<Map<String, IscSendScript>> scripts = new ThreadLocal<Map<String, IscSendScript>>() {
this.cfg = config;
this.executor = config.getExecutor(); @Override
for (int i = 0; i < cfg.getThreads(); i++) { protected Map<String, IscSendScript> initialValue() {
IscSendJob thread = new IscSendJob(); return new HashMap<String, IscSendScript>();
thread.setRunningTimeOutMillis(cfg.getRunningTimeOutMillis()); }
thread.setThreadSleepInterval(cfg.getThreadSleepInterval());
executor.execute(thread); };
public SendIscSrv() {
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
@Override
public String getThreadGroupName() {
return "iscSendThreadPool";
}
@Override
public void process() throws Exception {
IscSendRecord record = null;
do {
record = SendIscTransactions.getNextSendJob(runningTimeOutMillis);
if (record != null) {
runIscSend(record);
SendIscTransactions.removeSendJob(record);
}
} while (record != null);
}
@Override
public void dispose() {
super.dispose();
// Make sure OS resources are released at thread death
for (IscSendScript script : scripts.get().values()) {
script.dispose();
}
}
private void runIscSend(IscSendRecord request) {
try {
ParmID id = request.getParmID();
TimeRange tr = request.getTimeRange();
String xmlDest = request.getXmlDest();
String siteId = id.getDbId().getSiteId();
if (!GFESiteActivation.getInstance().getActiveSites()
.contains(siteId)) {
statusHandler.warn("Attempted to send " + id
+ " for deactivated site " + siteId + ".");
return;
}
statusHandler.info("Starting isc for " + id.toString() + " "
+ tr.toString() + " " + xmlDest);
Map<String, Object> cmd = new HashMap<String, Object>();
cmd.put("parmNames", Arrays.asList(id.getParmName()));
cmd.put("databaseName", id.getDbId().getModelId());
cmd.put("startTime", ISC_EXTRACT_DATE.format(tr.getStart()));
cmd.put("endTime", ISC_EXTRACT_DATE.format(tr.getEnd()));
// destination server XML, might be empty
// the -D switch is a file location containing the xml
// information
if (!xmlDest.isEmpty()) {
cmd.put("destinations", xmlDest);
}
try {
IFPServerConfig config = IFPServerConfigManager
.getServerConfig(siteId);
// IRT table address
cmd.put("irtTableAddressA", config.iscRoutingTableAddress()
.get("ANCF"));
cmd.put("irtTableAddressB", config.iscRoutingTableAddress()
.get("BNCF"));
// xmt script
cmd.put("transmitScript", config.transmitScript());
// our server host, port, protocol, our mhs id, and our site id
cmd.put("ourServerHost", config.getServerHost());
cmd.put("ourServerPort", String.valueOf(config.getRpcPort()));
cmd.put("ourServerProtocol",
String.valueOf(config.getProtocolVersion()));
cmd.put("ourMHSid", config.getMhsid());
cmd.put("ourSiteID", config.getSiteID().get(0));
} catch (GfeConfigurationException e) {
statusHandler.error(
"Unable to retrieve site configuration for site "
+ siteId, e);
return;
}
try {
IscSendScript script = scripts.get().get(siteId);
if (script == null) {
script = IscSendScriptFactory
.constructIscSendScript(siteId);
scripts.get().put(siteId, script);
}
script.execute(cmd);
} catch (JepException e) {
statusHandler.error("Error executing iscExtract.", e);
return;
}
try {
DatabaseID dbId = id.getDbId();
IFPServer ifpServer = IFPServer.getActiveServer(dbId
.getSiteId());
if (ifpServer != null) {
GridDatabase gridDb = ifpServer.getGridParmMgr()
.getDatabase(dbId);
if (gridDb != null) {
ServerResponse<Map<TimeRange, List<GridDataHistory>>> sr = gridDb
.updateSentTime(id, tr, new Date());
if (sr.isOkay()) {
WsId wsId = new WsId(null, "ISC", "ISC");
List<GridHistoryUpdateNotification> notifications = new ArrayList<GridHistoryUpdateNotification>(
1);
Map<TimeRange, List<GridDataHistory>> histories = sr
.getPayload();
notifications
.add(new GridHistoryUpdateNotification(id,
histories, wsId, siteId));
SendNotifications.send(notifications);
} else {
statusHandler
.error("Error updating last sent times in GFERecords: "
+ sr.getMessages());
}
} else {
// no such database exists
statusHandler
.error("Error processing ISC send request for :"
+ dbId
+ ", the database does not exist.");
}
} else {
// no active server for request
statusHandler
.error("Error processing ISC send request for :"
+ dbId + ", no active IFPServer for site.");
}
} catch (Exception e) {
statusHandler.error(
"Error updating last sent times in GFERecords.", e);
}
} catch (Throwable t) {
statusHandler.error("Exception in SendIscSrv: ", t);
} }
} }
} }

View file

@ -1,82 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.isc;
import java.util.concurrent.Executor;
/**
* Send ISC service configuration.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 20, 2011 dgilling Initial creation
* Apr 30, 2013 1949 rjpeter Removed initial delay.
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class SendIscSrvConfig {
protected int threads;
protected Executor executor;
protected int runningTimeOutMillis;
protected int threadSleepInterval;
public int getThreads() {
return threads;
}
public void setThreads(int threads) {
this.threads = threads;
}
public Executor getExecutor() {
return executor;
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -25,13 +25,9 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor;
import jep.JepException; import jep.JepException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.plugin.gfe.server.IFPServer; import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
@ -39,10 +35,10 @@ import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EdexTimerBasedThread;
import com.raytheon.uf.edex.core.props.EnvProperties;
import com.raytheon.uf.edex.core.props.PropertiesFactory;
/** /**
* Service that runs smart inits * Service that runs smart inits
@ -58,86 +54,56 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory;
* Aug 24, 2013 #1949 rjpeter Updated start up logic * Aug 24, 2013 #1949 rjpeter Updated start up logic
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer, * Jun 13, 2013 #2044 randerso Refactored to use IFPServer,
* added support to run init for all valid times * added support to run init for all valid times
* Mar 14, 2014 2726 rjpeter Implement graceful shutdown.
* </pre> * </pre>
* *
* @author njensen * @author njensen
* @version 1.0 * @version 1.0
*/ */
public class SmartInitSrv { public class SmartInitSrv extends EdexTimerBasedThread {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SmartInitSrv.class);
private final Map<Long, SmartInitScript> cachedInterpreters = new HashMap<Long, SmartInitScript>(); private final Map<Long, SmartInitScript> cachedInterpreters = new HashMap<Long, SmartInitScript>();
private static boolean enabled = true; protected int pendingInitMinTimeMillis = 120000;
protected final SmartInitSrvConfig cfg; protected int runningInitTimeOutMillis = 600000;
protected final Executor executor; public SmartInitSrv() {
static {
EnvProperties env = PropertiesFactory.getInstance().getEnvProperties();
enabled = Boolean.parseBoolean(env.getEnvValue("GFESMARTINIT"));
} }
public SmartInitSrv(SmartInitSrvConfig config) {
cfg = config;
this.executor = config.getExecutor();
for (int i = 0; i < cfg.getThreads(); i++) {
SmartInitThread thread = new SmartInitThread();
thread.pendingInitMinTimeMillis = cfg.getPendingInitMinTimeMillis();
thread.runningInitTimeOutMillis = cfg.getRunningInitTimeOutMillis();
thread.threadSleepInterval = cfg.getThreadSleepInterval();
executor.execute(thread);
}
}
protected class SmartInitThread implements Runnable {
// default of 2 minutes
private int pendingInitMinTimeMillis = 120000;
private int runningInitTimeOutMillis = 600000;
private int threadSleepInterval = 30000;
private final transient Log logger = LogFactory.getLog(getClass());
@Override @Override
public void run() { public String getThreadGroupName() {
try { return "smartInitThreadPool";
// Wait for server to come fully up due to route dependencies
while (!EDEXUtil.isRunning()) {
try {
Thread.sleep(threadSleepInterval);
} catch (InterruptedException e) {
// ignore
}
} }
// run forever @Override
while (true) { public void process() throws Exception {
SmartInitRecord record = SmartInitTransactions SmartInitRecord record = null;
.getSmartInitToRun(pendingInitMinTimeMillis, do {
runningInitTimeOutMillis); record = SmartInitTransactions.getSmartInitToRun(
pendingInitMinTimeMillis, runningInitTimeOutMillis);
if (record != null) { if (record != null) {
runSmartInit(record); runSmartInit(record);
} else {
try {
Thread.sleep(threadSleepInterval);
} catch (Exception e) {
// ignore
} }
} while (record != null);
} }
}
} finally { @Override
public void dispose() {
super.dispose();
// Make sure OS resources are released at thread death // Make sure OS resources are released at thread death
SmartInitScript script = cachedInterpreters.remove(Thread SmartInitScript script = cachedInterpreters.remove(Thread
.currentThread().getId()); .currentThread().getId());
if (script != null) {
script.dispose(); script.dispose();
} }
} }
public void runSmartInit(SmartInitRecord record) { public void runSmartInit(SmartInitRecord record) {
if (enabled) {
try { try {
SmartInitScript initScript = null; SmartInitScript initScript = null;
List<String> sitePathsAdded = new ArrayList<String>(2); List<String> sitePathsAdded = new ArrayList<String>(2);
@ -161,25 +127,22 @@ public class SmartInitSrv {
cachedInterpreters.put(id, initScript); cachedInterpreters.put(id, initScript);
} }
IPathManager pathMgr = PathManagerFactory IPathManager pathMgr = PathManagerFactory.getPathManager();
.getPathManager(); LocalizationContext ctx = pathMgr.getContextForSite(
LocalizationContext ctx = pathMgr LocalizationType.EDEX_STATIC, db.getSiteId());
.getContextForSite(
LocalizationType.EDEX_STATIC,
db.getSiteId());
LocalizationContext baseCtx = pathMgr.getContext( LocalizationContext baseCtx = pathMgr.getContext(
LocalizationType.EDEX_STATIC, LocalizationType.EDEX_STATIC,
LocalizationLevel.BASE); LocalizationLevel.BASE);
File file = pathMgr.getFile(ctx, "smartinit"); File file = pathMgr.getFile(ctx, "smartinit");
if ((file != null) && file.exists()) { if ((file != null) && file.exists()) {
initScript.addSitePath(file.getPath(), pathMgr initScript
.getFile(baseCtx, "smartinit") .addSitePath(file.getPath(),
pathMgr.getFile(baseCtx, "smartinit")
.getPath()); .getPath());
sitePathsAdded.add(file.getPath()); sitePathsAdded.add(file.getPath());
} }
file = pathMgr.getFile(ctx, file = pathMgr.getFile(ctx, FileUtil.join("config", "gfe"));
FileUtil.join("config", "gfe"));
if ((file != null) && file.exists()) { if ((file != null) && file.exists()) {
initScript.addSitePath( initScript.addSitePath(
file.getPath(), file.getPath(),
@ -196,7 +159,7 @@ public class SmartInitSrv {
initScript.execute(argMap); initScript.execute(argMap);
} catch (Throwable e) { } catch (Throwable e) {
logger.error("Error running smart init for " statusHandler.error("Error running smart init for "
+ record.getId(), e); + record.getId(), e);
} finally { } finally {
try { try {
@ -204,22 +167,41 @@ public class SmartInitSrv {
initScript.removeSitePath(path); initScript.removeSitePath(path);
} }
} catch (JepException e) { } catch (JepException e) {
this.logger statusHandler
.error("Error cleaning up smart init interpreter's sys.path", .error("Error cleaning up smart init interpreter's sys.path",
e); e);
} }
} }
} else { } else {
this.logger.warn("Site " + db.getSiteId() statusHandler.warn("Site " + db.getSiteId()
+ " has been disabled. Smart init for " + " has been disabled. Smart init for "
+ record.getDbName() + record.getDbName() + " will not be processed.");
+ " will not be processed.");
} }
} catch (Throwable t) { } catch (Throwable t) {
this.logger.error("Error in SmartInitSrv", t); statusHandler.error("Error in SmartInitSrv", t);
} }
SmartInitTransactions.removeSmartInit(record); SmartInitTransactions.removeSmartInit(record);
} }
@Override
public void postStop() {
SmartInitQueue.getQueue().fireSmartInit();
super.postStop();
} }
public int getPendingInitMinTimeMillis() {
return pendingInitMinTimeMillis;
}
public void setPendingInitMinTimeMillis(int pendingInitMinTimeMillis) {
this.pendingInitMinTimeMillis = pendingInitMinTimeMillis;
}
public int getRunningInitTimeOutMillis() {
return runningInitTimeOutMillis;
}
public void setRunningInitTimeOutMillis(int runningInitTimeOutMillis) {
this.runningInitTimeOutMillis = runningInitTimeOutMillis;
} }
} }

View file

@ -1,91 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.smartinit;
import java.util.concurrent.Executor;
/**
* Smart Init Server config.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 24, 2010 #7277 rjpeter Initial creation
* Apr 23, 2013 #1949 rjpeter Removed initial delay
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class SmartInitSrvConfig {
protected int threads;
protected Executor executor;
protected int pendingInitMinTimeMillis;
protected int runningInitTimeOutMillis;
protected int threadSleepInterval;
public int getThreads() {
return threads;
}
public void setThreads(int threads) {
this.threads = threads;
}
public Executor getExecutor() {
return executor;
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public int getPendingInitMinTimeMillis() {
return pendingInitMinTimeMillis;
}
public void setPendingInitMinTimeMillis(int pendingInitMinTimeMillis) {
this.pendingInitMinTimeMillis = pendingInitMinTimeMillis;
}
public int getRunningInitTimeOutMillis() {
return runningInitTimeOutMillis;
}
public void setRunningInitTimeOutMillis(int runningInitTimeOutMillis) {
this.runningInitTimeOutMillis = runningInitTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -15,16 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.goessounding"/> <constructor-arg value="jms-durable:queue:Ingest.goessounding"/>
</bean> </bean>
<bean id="goessoundingCamelRegistered" factory-bean="contextManager"
factory-method="register"
depends-on="persistCamelRegistered">
<constructor-arg ref="goessounding-camel"/>
</bean>
<camelContext id="goessounding-camel" <camelContext id="goessounding-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="goessndgFileEndpoint" <endpoint id="goessndgFileEndpoint"
uri="file:${edex.home}/data/sbn/goessndg?noop=true&amp;idempotent=false" /> uri="file:${edex.home}/data/sbn/goessndg?noop=true&amp;idempotent=false" />

View file

@ -14,11 +14,6 @@
<bean id="useLatestAggregationStrategy" class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy" /> <bean id="useLatestAggregationStrategy" class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy" />
<bean id="gribDecodeCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="grib-decode"/>
</bean>
<bean id="gribPostProcessor" <bean id="gribPostProcessor"
class="com.raytheon.edex.plugin.grib.decoderpostprocessors.GribPostProcessor" class="com.raytheon.edex.plugin.grib.decoderpostprocessors.GribPostProcessor"
factory-method="getInstance" /> factory-method="getInstance" />
@ -35,8 +30,7 @@
factory-method="getInstance" depends-on="gridcoveragelookup"/> factory-method="getInstance" depends-on="gridcoveragelookup"/>
<camelContext id="grib-decode" xmlns="http://camel.apache.org/schema/spring" <camelContext id="grib-decode" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<endpoint id="gribSplitJmsEndpoint" uri="jms-durable:queue:Ingest.GribSplit?concurrentConsumers=${grib-split.count.threads}"/> <endpoint id="gribSplitJmsEndpoint" uri="jms-durable:queue:Ingest.GribSplit?concurrentConsumers=${grib-split.count.threads}"/>
<endpoint id="gribDecodeJmsEndpoint" uri="jms-durable:queue:Ingest.GribDecode?concurrentConsumers=${grib-decode.count.threads}"/> <endpoint id="gribDecodeJmsEndpoint" uri="jms-durable:queue:Ingest.GribDecode?concurrentConsumers=${grib-decode.count.threads}"/>
@ -50,9 +44,7 @@
<constant>grid</constant> <constant>grid</constant>
</setHeader> </setHeader>
<bean ref="stringToFile" /> <bean ref="stringToFile" />
<!-- strategyRef is needed because of camel bug https://issues.apache.org/activemq/browse/CAMEL-3333, <split streaming="true">
without the strategy it uses the original message in the multicast and it loses the largeFileLock header -->
<split strategyRef="useLatestAggregationStrategy" streaming="true">
<method bean="gribSplitter" method="split" /> <method bean="gribSplitter" method="split" />
<to uri="jms-durable:queue:Ingest.GribDecode" /> <to uri="jms-durable:queue:Ingest.GribDecode" />
</split> </split>
@ -70,6 +62,7 @@
<pipeline> <pipeline>
<bean ref="gribGridPointLock" method="reserve"/> <bean ref="gribGridPointLock" method="reserve"/>
<bean ref="gribDecoder" /> <bean ref="gribDecoder" />
<!-- send for processing --> <!-- send for processing -->
<bean ref="gribPostProcessor" method="process" /> <bean ref="gribPostProcessor" method="process" />
<to uri="direct-vm:persistIndexAlert" /> <to uri="direct-vm:persistIndexAlert" />

View file

@ -1,4 +1,4 @@
<?xml version="2.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- <!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company, This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government. pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.

View file

@ -18,15 +18,9 @@
<bean id="ldadhydroPointData" class="com.raytheon.edex.plugin.ldadhydro.dao.LdadhydroPointDataTransform"/> <bean id="ldadhydroPointData" class="com.raytheon.edex.plugin.ldadhydro.dao.LdadhydroPointDataTransform"/>
<bean id="ldadhydroCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadhydro-camel"/>
</bean>
<camelContext id="ldadhydro-camel" <camelContext id="ldadhydro-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="ldadhydroIngestRoute"> <route id="ldadhydroIngestRoute">
<from uri="jms-durable:queue:Ingest.ldadhydro"/> <from uri="jms-durable:queue:Ingest.ldadhydro"/>
<doTry> <doTry>

View file

@ -15,15 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ldadmanual"/> <constructor-arg value="jms-durable:queue:Ingest.ldadmanual"/>
</bean> </bean>
<bean id="ldadmanualCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadmanual-camel"/>
</bean>
<camelContext id="ldadmanual-camel" <camelContext id="ldadmanual-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="ldadmanualIngestRoute"> <route id="ldadmanualIngestRoute">
<from uri="jms-durable:queue:Ingest.ldadmanual"/> <from uri="jms-durable:queue:Ingest.ldadmanual"/>

View file

@ -19,15 +19,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ldadprofiler"/> <constructor-arg value="jms-durable:queue:Ingest.ldadprofiler"/>
</bean> </bean>
<bean id="ldadprofilerCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadprofiler-camel"/>
</bean>
<camelContext id="ldadprofiler-camel" <camelContext id="ldadprofiler-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="ldadprofilerFileEndpoint" uri="file:${edex.home}/data/sbn/ldadprofiler?noop=true" /> <endpoint id="ldadprofilerFileEndpoint" uri="file:${edex.home}/data/sbn/ldadprofiler?noop=true" />

View file

@ -3,16 +3,8 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="obsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="persistCamelRegistered,
shefCamelRegistered,
metarToHMDBCamelRegistered">
<constructor-arg ref="obs-camel" />
</bean>
<camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring" <camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- Begin METAR routes --> <!-- Begin METAR routes -->
<route id="metarIngestRoute"> <route id="metarIngestRoute">

View file

@ -5,15 +5,8 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- This spring configuration is currently only used by the ingestHydro EDEX instance. --> <!-- This spring configuration is currently only used by the ingestHydro EDEX instance. -->
<bean id="obsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="shefCamelRegistered,
metarToHMDBCamelRegistered">
<constructor-arg ref="obs-camel" />
</bean>
<camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring" <camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- Begin METAR routes --> <!-- Begin METAR routes -->
<route id="metarIngestRoute"> <route id="metarIngestRoute">

View file

@ -1,8 +1,7 @@
<beans <beans
xmlns="http://www.springframework.org/schema/beans" xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="obsDecoder" class="com.raytheon.edex.plugin.obs.ObsDecoder" /> <bean id="obsDecoder" class="com.raytheon.edex.plugin.obs.ObsDecoder" />

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.poessounding"/> <constructor-arg value="jms-durable:queue:Ingest.poessounding"/>
</bean> </bean>
<bean id="poessoundingCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="poessounding-camel"/>
</bean>
<camelContext id="poessounding-camel" <camelContext id="poessounding-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="poessndgFileEndpoint" uri="file:${edex.home}/data/sbn/poessndg?noop=true&amp;idempotent=false"/> <endpoint id="poessndgFileEndpoint" uri="file:${edex.home}/data/sbn/poessndg?noop=true&amp;idempotent=false"/>

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.profiler"/> <constructor-arg value="jms-durable:queue:Ingest.profiler"/>
</bean> </bean>
<bean id="profilerCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="profiler-camel"/>
</bean>
<camelContext id="profiler-camel" <camelContext id="profiler-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="profilerFileEndpoint" uri="file:${edex.home}/data/sbn/profiler?noop=true&amp;idempotent=false"/> <endpoint id="profilerFileEndpoint" uri="file:${edex.home}/data/sbn/profiler?noop=true&amp;idempotent=false"/>

View file

@ -18,15 +18,9 @@
<constructor-arg value="jms-durable:queue:Ingest.RadarRadarServer" /> <constructor-arg value="jms-durable:queue:Ingest.RadarRadarServer" />
</bean> </bean>
<bean id="radarCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="radar-camel"/>
</bean>
<camelContext id="radar-camel" <camelContext id="radar-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="radarFileEndpoint" uri="file:${edex.home}/data/sbn/radar?noop=true&amp;idempotent=false" /> <endpoint id="radarFileEndpoint" uri="file:${edex.home}/data/sbn/radar?noop=true&amp;idempotent=false" />

View file

@ -15,15 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.recco" /> <constructor-arg value="jms-durable:queue:Ingest.recco" />
</bean> </bean>
<bean id="reccoCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="recco-camel"/>
</bean>
<camelContext id="recco-camel" <camelContext id="recco-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="reccoFileEndpoint" uri="file:${edex.home}/data/sbn/recco?noop=true&amp;idempotent=false" /> <endpoint id="reccoFileEndpoint" uri="file:${edex.home}/data/sbn/recco?noop=true&amp;idempotent=false" />

View file

@ -45,22 +45,13 @@
<constructor-arg ref="spcMenuListener" /> <constructor-arg ref="spcMenuListener" />
</bean> </bean>
<!-- <bean factory-bean="contextManager" factory-method="registerClusteredContext">
<bean id="redbookCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="clusteredRedbook-camel"/>
</bean>
-->
<bean id="redbookCamelRegistered" factory-bean="clusteredCamelContextMgr"
factory-method="register">
<constructor-arg ref="clusteredRedbook-camel" /> <constructor-arg ref="clusteredRedbook-camel" />
</bean> </bean>
<camelContext id="clusteredRedbook-camel" <camelContext id="clusteredRedbook-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="redbookFileEndpoint" uri="file:${edex.home}/data/sbn/redbook?noop=true&amp;idempotent=false" /> <endpoint id="redbookFileEndpoint" uri="file:${edex.home}/data/sbn/redbook?noop=true&amp;idempotent=false" />

View file

@ -7,7 +7,7 @@
<property name="dao" ref="satelliteDao" /> <property name="dao" ref="satelliteDao" />
</bean> </bean>
<bean id="satelliteDao" class="com.raytheon.edex.plugin.satellite.dao.SatelliteDao"> <bean id="satelliteDao" class="com.raytheon.edex.plugin.satellite.dao.SatelliteDao" depends-on="satelliteProperties">
<constructor-arg ref="satellitePluginName" /> <constructor-arg ref="satellitePluginName" />
</bean> </bean>
@ -17,15 +17,9 @@
<constructor-arg value="jms-durable:queue:Ingest.Satellite" /> <constructor-arg value="jms-durable:queue:Ingest.Satellite" />
</bean> </bean>
<bean id="satCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="sat-camel"/>
</bean>
<camelContext id="sat-camel" <camelContext id="sat-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="satFileEndpoint" uri="file:${edex.home}/data/sbn/sat?noop=true&amp;idempotent=false" /> <endpoint id="satFileEndpoint" uri="file:${edex.home}/data/sbn/sat?noop=true&amp;idempotent=false" />

View file

@ -16,12 +16,6 @@
<constructor-arg value="jms-durable:queue:Ingest.sfcobs" /> <constructor-arg value="jms-durable:queue:Ingest.sfcobs" />
</bean> </bean>
<bean id="sfcobsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="persistCamelRegistered,
shefCamelRegistered">
<constructor-arg ref="sfcobs-camel" />
</bean>
<bean id="buoyListener" class="com.raytheon.edex.plugin.sfcobs.ingest.BuoySubscriber" /> <bean id="buoyListener" class="com.raytheon.edex.plugin.sfcobs.ingest.BuoySubscriber" />
<bean id="marineInfoListener" class="com.raytheon.edex.plugin.sfcobs.ingest.MarineInfoSubscriber"> <bean id="marineInfoListener" class="com.raytheon.edex.plugin.sfcobs.ingest.MarineInfoSubscriber">
@ -52,7 +46,7 @@
</bean> </bean>
<camelContext id="sfcobs-camel" xmlns="http://camel.apache.org/schema/spring" <camelContext id="sfcobs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- Begin sfcobs routes --> <!-- Begin sfcobs routes -->
<route id="sfcobsIngestRoute"> <route id="sfcobsIngestRoute">

View file

@ -44,22 +44,17 @@
<constructor-arg value="jms-durable:queue:Ingest.Shef"/> <constructor-arg value="jms-durable:queue:Ingest.Shef"/>
</bean> </bean>
<bean id="shefCamelRegistered" factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="shef-camel" />
</bean>
<!-- Start add for manual input --> <!-- Start add for manual input -->
<bean id="shefFileChangedStrategy" <bean id="shefFileChangedStrategy"
class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy" /> class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy" />
<bean factory-bean="clusteredCamelContextMgr" factory-method="register"> <bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredShefManualProc" /> <constructor-arg ref="clusteredShefManualProc" />
</bean> </bean>
<camelContext id="clusteredShefManualProc" xmlns="http://camel.apache.org/schema/spring" <camelContext id="clusteredShefManualProc" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<endpoint id="shefManualFileEndpoint" <endpoint id="shefManualFileEndpoint"
uri="file:${edex.home}/data/share/hydroapps/shefdecode/input?delete=true&amp;maxMessagesPerPoll=1000&amp;delay=15000&amp;exclusiveReadLockStrategy=#shefFileChangedStrategy" /> uri="file:${edex.home}/data/share/hydroapps/shefdecode/input?delete=true&amp;maxMessagesPerPoll=1000&amp;delay=15000&amp;exclusiveReadLockStrategy=#shefFileChangedStrategy" />
@ -75,7 +70,7 @@
<!-- End add for manual input --> <!-- End add for manual input -->
<camelContext id="shef-camel" xmlns="http://camel.apache.org/schema/spring" <camelContext id="shef-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<!-- Begin shef routes --> <!-- Begin shef routes -->
<route id="shefIngestRoute"> <route id="shefIngestRoute">

View file

@ -18,15 +18,9 @@
<constructor-arg value="jms-durable:queue:Ingest.taf"/> <constructor-arg value="jms-durable:queue:Ingest.taf"/>
</bean> </bean>
<bean id="tafCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="taf-camel"/>
</bean>
<camelContext id="taf-camel" <camelContext id="taf-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="tafFileEndpoint" uri="file:${edex.home}/data/sbn/taf?noop=true&amp;idempotent=false" /> <endpoint id="tafFileEndpoint" uri="file:${edex.home}/data/sbn/taf?noop=true&amp;idempotent=false" />

View file

@ -207,8 +207,7 @@
<camelContext id="clustered-text-camel" <camelContext id="clustered-text-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- TextPurge route --> <!-- TextPurge route -->
<route id="textPurgeRequestRoute"> <route id="textPurgeRequestRoute">
<from uri="jms-generic:queue:textPurgeRequest" /> <from uri="jms-generic:queue:textPurgeRequest" />
@ -232,8 +231,7 @@
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register">
<constructor-arg ref="clustered-text-camel" /> <constructor-arg ref="clustered-text-camel" />
</bean> </bean>
</beans> </beans>

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.textlightning"/> <constructor-arg value="jms-durable:queue:Ingest.textlightning"/>
</bean> </bean>
<bean id="textlightningCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="textlightning-camel"/>
</bean>
<camelContext id="textlightning-camel" <camelContext id="textlightning-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="textlightningFileEndpoint" <endpoint id="textlightningFileEndpoint"
uri="file:${edex.home}/data/sbn/textlightning?noop=true&amp;idempotent=false" /> uri="file:${edex.home}/data/sbn/textlightning?noop=true&amp;idempotent=false" />

View file

@ -17,15 +17,9 @@
<constructor-arg value="jms-durable:queue:Ingest.Warning"/> <constructor-arg value="jms-durable:queue:Ingest.Warning"/>
</bean> </bean>
<bean id="warningCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="warning-camel"/>
</bean>
<camelContext id="warning-camel" <camelContext id="warning-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<!-- <!--
<endpoint id="warningEndpoint" <endpoint id="warningEndpoint"
uri="file:${edex.home}/data/sbn/warning?noop=true&amp;idempotent=false" /> uri="file:${edex.home}/data/sbn/warning?noop=true&amp;idempotent=false" />

View file

@ -3,34 +3,36 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="geospatialDataGenerator" class="com.raytheon.edex.plugin.warning.gis.GeospatialDataGenerator">
<constructor-arg value="geospatialUpdateNotify"/>
</bean>
<bean id="generateGeospatialDataRequestHandler" class="com.raytheon.edex.plugin.warning.gis.GenerateGeospatialDataRequestHandler">
<constructor-arg ref="geospatialDataGenerator"/>
</bean>
<bean id="generateGeospatialDataRequestHandler" class="com.raytheon.edex.plugin.warning.gis.GenerateGeospatialDataRequestHandler" />
<bean factory-bean="handlerRegistry" factory-method="register"> <bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.warning.gis.GenerateGeospatialDataRequest"/> <constructor-arg value="com.raytheon.uf.common.dataplugin.warning.gis.GenerateGeospatialDataRequest"/>
<constructor-arg ref="generateGeospatialDataRequestHandler"/> <constructor-arg ref="generateGeospatialDataRequestHandler"/>
</bean> </bean>
<!-- Instantiating class causes a thread to be run that will generate the warngen geometries --> <camelContext id="geospatialDataGenerator-camel"
<bean class="com.raytheon.edex.plugin.warning.gis.GeospatialDataGeneratorThread" depends-on="spatialQueryRegistered" /> xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<!--Instantiating class will update the warngen geometries-->
<bean id="geospatialDataUpdater" class="com.raytheon.edex.plugin.warning.gis.GeospatialDataUpdater" />
<camelContext id="geospatialDataUpdater-context"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="geospatialDataUpdaterCron" <endpoint id="geospatialDataUpdaterCron"
uri="clusteredquartz://warning/geospatialDataUpdaterScheduled/?cron=${geospatial.updater.cron}" /> uri="clusteredquartz://warning/checkGeospatialData/?cron=${geospatial.updater.cron}" />
<route id="geospatialDataUpdaterScheduled"> <!-- Generate once on context start -->
<from uri="geospatialDataUpdaterCron" /> <route id="geospatialDataGeneratorRoute">
<to uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" /> <from uri="timer://generateWarngenGeometries?repeatCount=1"/>
<bean ref="geospatialDataGenerator" method="generateUniqueGeospatialMetadataGeometries"/>
</route> </route>
<route id="geospatialDataUpdaterScheduledWork"> <!-- check generate periodically -->
<from uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" /> <route id="geospatialDataUpdaterRoute">
<from ref="geospatialDataUpdaterCron"/>
<doTry> <doTry>
<bean ref="geospatialDataUpdater" method="runCheckUpdate" /> <bean ref="geospatialDataGenerator" method="generateUniqueGeospatialMetadataGeometries"/>
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
<to <to
@ -38,6 +40,12 @@
</doCatch> </doCatch>
</doTry> </doTry>
</route> </route>
</camelContext>
<!-- Route to send geospatial data update notification -->
<route id="geospatialUpdateNotify">
<from uri="vm:edex.geospatialUpdateNotification" />
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.geospatialUpdate.msg" />
</route>
</camelContext>
</beans> </beans>

View file

@ -23,7 +23,7 @@ import com.raytheon.uf.common.dataplugin.warning.gis.GenerateGeospatialDataReque
import com.raytheon.uf.common.serialization.comm.IRequestHandler; import com.raytheon.uf.common.serialization.comm.IRequestHandler;
/** /**
* TODO Add Description * Generates geospatial data on demand.
* *
* <pre> * <pre>
* *
@ -31,8 +31,8 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 22, 2011 rjpeter Initial creation * Jul 22, 2011 rjpeter Initial creation.
* * May 19, 2014 2726 rjpeter Updated call to GeospatialDataGenerator.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
@ -41,6 +41,13 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
public class GenerateGeospatialDataRequestHandler implements public class GenerateGeospatialDataRequestHandler implements
IRequestHandler<GenerateGeospatialDataRequest> { IRequestHandler<GenerateGeospatialDataRequest> {
final GeospatialDataGenerator dataGenerator;
public GenerateGeospatialDataRequestHandler(
GeospatialDataGenerator dataGenerator) {
this.dataGenerator = dataGenerator;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -51,8 +58,8 @@ public class GenerateGeospatialDataRequestHandler implements
@Override @Override
public Object handleRequest(GenerateGeospatialDataRequest request) public Object handleRequest(GenerateGeospatialDataRequest request)
throws Exception { throws Exception {
return GeospatialDataGenerator.generateGeoSpatialList( return dataGenerator.generateGeoSpatialList(request.getSite(),
request.getSite(), request.getMetaData()); request.getMetaData());
} }
} }

View file

@ -20,13 +20,16 @@
package com.raytheon.edex.plugin.warning.gis; package com.raytheon.edex.plugin.warning.gis;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TimeZone;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@ -62,6 +65,8 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.database.cluster.ClusterTask;
@ -97,6 +102,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
* May 7, 2013 15690 Qinglu Lin Added convertToMultiPolygon() and updated queryGeospatialData(). * May 7, 2013 15690 Qinglu Lin Added convertToMultiPolygon() and updated queryGeospatialData().
* Oct 22, 2013 2361 njensen Use JAXBManager for XML * Oct 22, 2013 2361 njensen Use JAXBManager for XML
* Feb 07, 2014 16090 mgamazaychikov Changed visibility of some methods * Feb 07, 2014 16090 mgamazaychikov Changed visibility of some methods
* Mar 19, 2014 2726 rjpeter Made singleton instance.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
@ -104,14 +110,19 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
*/ */
public class GeospatialDataGenerator { public class GeospatialDataGenerator {
private final IUFStatusHandler statusHandler = UFStatus
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(GeospatialDataGenerator.class); .getHandler(GeospatialDataGenerator.class);
private static final SingleTypeJAXBManager<GeospatialTimeSet> jaxb = SingleTypeJAXBManager private final SingleTypeJAXBManager<GeospatialTimeSet> jaxb = SingleTypeJAXBManager
.createWithoutException(GeospatialTimeSet.class); .createWithoutException(GeospatialTimeSet.class);
public static void generateUniqueGeospatialMetadataGeometries() { private final String updaterEndpoint;
public GeospatialDataGenerator(String updaterEndpoint) {
this.updaterEndpoint = updaterEndpoint;
}
public void generateUniqueGeospatialMetadataGeometries() {
String mySite = SiteUtil.getSite(); String mySite = SiteUtil.getSite();
DialogConfiguration dialogConfig = null; DialogConfiguration dialogConfig = null;
@ -129,7 +140,7 @@ public class GeospatialDataGenerator {
for (String site : sites) { for (String site : sites) {
statusHandler.handle(Priority.INFO, statusHandler.handle(Priority.INFO,
"Generating warngen geometries for site: " + site); "Checking warngen geometries for site: " + site);
for (GeospatialMetadata md : metaDataSet) { for (GeospatialMetadata md : metaDataSet) {
try { try {
generateGeoSpatialList(site, md); generateGeoSpatialList(site, md);
@ -143,7 +154,7 @@ public class GeospatialDataGenerator {
} }
} }
public static Set<GeospatialMetadata> getMetaDataSet(List<String> sites, public Set<GeospatialMetadata> getMetaDataSet(List<String> sites,
List<String> templates) { List<String> templates) {
Set<GeospatialMetadata> metaDataSet = new HashSet<GeospatialMetadata>(); Set<GeospatialMetadata> metaDataSet = new HashSet<GeospatialMetadata>();
@ -178,7 +189,8 @@ public class GeospatialDataGenerator {
} }
return metaDataSet; return metaDataSet;
} }
static List<String> getBackupSites(DialogConfiguration dialogConfig) {
public static List<String> getBackupSites(DialogConfiguration dialogConfig) {
String[] CWAs = dialogConfig.getBackupCWAs().split(","); String[] CWAs = dialogConfig.getBackupCWAs().split(",");
List<String> rval = new ArrayList<String>(CWAs.length + 1); List<String> rval = new ArrayList<String>(CWAs.length + 1);
for (String s : CWAs) { for (String s : CWAs) {
@ -189,7 +201,7 @@ public class GeospatialDataGenerator {
return rval; return rval;
} }
static List<String> getTemplates(DialogConfiguration dialogConfig) { public static List<String> getTemplates(DialogConfiguration dialogConfig) {
String[] mainProducts = dialogConfig.getMainWarngenProducts() String[] mainProducts = dialogConfig.getMainWarngenProducts()
.split(","); .split(",");
String[] otherProducts = dialogConfig.getOtherWarngenProducts().split( String[] otherProducts = dialogConfig.getOtherWarngenProducts().split(
@ -209,7 +221,7 @@ public class GeospatialDataGenerator {
return rval; return rval;
} }
public static GeospatialDataSet generateGeoSpatialList(String site, public GeospatialDataSet generateGeoSpatialList(String site,
GeospatialMetadata metaData) throws SpatialException { GeospatialMetadata metaData) throws SpatialException {
GeospatialDataSet dataSet = null; GeospatialDataSet dataSet = null;
String file = generateGeoDataFilename(metaData); String file = generateGeoDataFilename(metaData);
@ -307,6 +319,19 @@ public class GeospatialDataGenerator {
// save to disk // save to disk
try { try {
persistGeoData(site, lastRunTimeMap, curTime, dataSet); persistGeoData(site, lastRunTimeMap, curTime, dataSet);
if (updaterEndpoint != null) {
String updatedTimeStamp = getTimeStamp(curTime,
lastRunTime);
try {
EDEXUtil.getMessageProducer().sendAsync(
updaterEndpoint, updatedTimeStamp);
} catch (EdexException e) {
statusHandler.error("Could not send message to "
+ updaterEndpoint, e);
}
}
} catch (Exception e) { } catch (Exception e) {
statusHandler.handle(Priority.WARN, statusHandler.handle(Priority.WARN,
"Error occurred persisting area geometry data", e); "Error occurred persisting area geometry data", e);
@ -320,7 +345,7 @@ public class GeospatialDataGenerator {
return dataSet; return dataSet;
} }
public static GeospatialMetadata getMetaData(WarngenConfiguration template) { public GeospatialMetadata getMetaData(WarngenConfiguration template) {
GeospatialMetadata rval = new GeospatialMetadata(); GeospatialMetadata rval = new GeospatialMetadata();
GeospatialConfiguration geoConfig = template.getGeospatialConfig(); GeospatialConfiguration geoConfig = template.getGeospatialConfig();
AreaSourceConfiguration areaConfig = template.getHatchedAreaSource(); AreaSourceConfiguration areaConfig = template.getHatchedAreaSource();
@ -346,7 +371,7 @@ public class GeospatialDataGenerator {
return rval; return rval;
} }
static GeospatialTime queryForCurrentTimes( public static GeospatialTime queryForCurrentTimes(
GeospatialMetadata metaData) throws Exception { GeospatialMetadata metaData) throws Exception {
GeospatialTime rval = new GeospatialTime(); GeospatialTime rval = new GeospatialTime();
String areaSource = metaData.getAreaSource().toLowerCase(); String areaSource = metaData.getAreaSource().toLowerCase();
@ -355,12 +380,12 @@ public class GeospatialDataGenerator {
StringBuilder sql = new StringBuilder(200); StringBuilder sql = new StringBuilder(200);
sql.append("SELECT table_name, import_time FROM mapdata.map_version WHERE table_name in ('"); sql.append("SELECT table_name, import_time FROM mapdata.map_version WHERE table_name in ('");
sql.append(areaSource.toLowerCase()); sql.append(areaSource.toLowerCase());
if (tzSource != null && tzSource.length() > 0) { if ((tzSource != null) && (tzSource.length() > 0)) {
tzSource = tzSource.toLowerCase(); tzSource = tzSource.toLowerCase();
sql.append("', '"); sql.append("', '");
sql.append(tzSource); sql.append(tzSource);
} }
if (pAreaSource != null && pAreaSource.length() > 0) { if ((pAreaSource != null) && (pAreaSource.length() > 0)) {
pAreaSource = pAreaSource.toLowerCase(); pAreaSource = pAreaSource.toLowerCase();
sql.append("', '"); sql.append("', '");
sql.append(pAreaSource); sql.append(pAreaSource);
@ -390,7 +415,7 @@ public class GeospatialDataGenerator {
return rval; return rval;
} }
private static GeospatialData[] queryGeospatialData(String site, private GeospatialData[] queryGeospatialData(String site,
GeospatialMetadata metaData) throws SpatialException { GeospatialMetadata metaData) throws SpatialException {
String areaSource = metaData.getAreaSource(); String areaSource = metaData.getAreaSource();
@ -423,24 +448,26 @@ public class GeospatialDataGenerator {
Geometry clippedGeom = null; Geometry clippedGeom = null;
for (int i = 0; i < features.length; i++) { for (int i = 0; i < features.length; i++) {
multiPolygon = null; multiPolygon = null;
for (int j = 0; j < cwaFeatures.length; j++) { for (SpatialQueryResult cwaFeature : cwaFeatures) {
clippedGeom = features[i].geometry clippedGeom = features[i].geometry
.intersection(cwaFeatures[j].geometry); .intersection(cwaFeature.geometry);
if (clippedGeom instanceof GeometryCollection) { if (clippedGeom instanceof GeometryCollection) {
GeometryCollection gc = (GeometryCollection) clippedGeom; GeometryCollection gc = (GeometryCollection) clippedGeom;
if (multiPolygon != null) if (multiPolygon != null) {
multiPolygon = multiPolygon multiPolygon = multiPolygon
.union(convertToMultiPolygon(gc)); .union(convertToMultiPolygon(gc));
else } else {
multiPolygon = convertToMultiPolygon(gc); multiPolygon = convertToMultiPolygon(gc);
} }
} }
if (multiPolygon != null) }
if (multiPolygon != null) {
features[i].geometry = multiPolygon; features[i].geometry = multiPolygon;
else if (clippedGeom != null) } else if (clippedGeom != null) {
features[i].geometry = clippedGeom; features[i].geometry = clippedGeom;
} }
} }
}
topologySimplifyQueryResults(features); topologySimplifyQueryResults(features);
@ -463,7 +490,7 @@ public class GeospatialDataGenerator {
* *
* @param gc * @param gc
*/ */
private static MultiPolygon convertToMultiPolygon(GeometryCollection gc) { private MultiPolygon convertToMultiPolygon(GeometryCollection gc) {
GeometryCollectionIterator iter = new GeometryCollectionIterator(gc); GeometryCollectionIterator iter = new GeometryCollectionIterator(gc);
Set<Polygon> polygons = new HashSet<Polygon>(); Set<Polygon> polygons = new HashSet<Polygon>();
MultiPolygon mp = null; MultiPolygon mp = null;
@ -471,53 +498,60 @@ public class GeospatialDataGenerator {
while (iter.hasNext()) { while (iter.hasNext()) {
Object o = iter.next(); Object o = iter.next();
if (o instanceof MultiPolygon) { if (o instanceof MultiPolygon) {
if (mp == null) if (mp == null) {
mp = (MultiPolygon) o; mp = (MultiPolygon) o;
else } else {
mp = (MultiPolygon) mp.union((MultiPolygon) o); mp = (MultiPolygon) mp.union((MultiPolygon) o);
}
} else if (o instanceof Polygon) { } else if (o instanceof Polygon) {
polygons.add((Polygon) o); polygons.add((Polygon) o);
} else if (o instanceof LineString || o instanceof Point) { } else if ((o instanceof LineString) || (o instanceof Point)) {
LinearRing lr = null; LinearRing lr = null;
Coordinate[] coords = null; Coordinate[] coords = null;
if (o instanceof LineString) { if (o instanceof LineString) {
Coordinate[] cs = ((LineString) o).getCoordinates(); Coordinate[] cs = ((LineString) o).getCoordinates();
if (cs.length < 4) { if (cs.length < 4) {
coords = new Coordinate[4]; coords = new Coordinate[4];
for (int j = 0; j < cs.length; j++) for (int j = 0; j < cs.length; j++) {
coords[j] = new Coordinate(cs[j]); coords[j] = new Coordinate(cs[j]);
for (int j = cs.length; j < 4; j++) }
for (int j = cs.length; j < 4; j++) {
coords[j] = new Coordinate(cs[3 - j]); coords[j] = new Coordinate(cs[3 - j]);
}
} else { } else {
coords = new Coordinate[cs.length + 1]; coords = new Coordinate[cs.length + 1];
for (int j = 0; j < cs.length; j++) for (int j = 0; j < cs.length; j++) {
coords[j] = new Coordinate(cs[j]); coords[j] = new Coordinate(cs[j]);
}
coords[cs.length] = new Coordinate(cs[0]); coords[cs.length] = new Coordinate(cs[0]);
} }
} else { } else {
coords = new Coordinate[4]; coords = new Coordinate[4];
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++) {
coords[i] = ((Point) o).getCoordinate(); coords[i] = ((Point) o).getCoordinate();
} }
}
lr = (((Geometry) o).getFactory()).createLinearRing(coords); lr = (((Geometry) o).getFactory()).createLinearRing(coords);
Polygon poly = (new GeometryFactory()).createPolygon(lr, null); Polygon poly = (new GeometryFactory()).createPolygon(lr, null);
polygons.add((Polygon) poly); polygons.add(poly);
} else { } else {
statusHandler.handle(Priority.WARN, statusHandler.handle(Priority.WARN,
"Unprocessed Geometry object: " "Unprocessed Geometry object: "
+ o.getClass().getName()); + o.getClass().getName());
} }
} }
if (mp == null && polygons.size() == 0) if ((mp == null) && (polygons.size() == 0)) {
return null; return null;
}
if (polygons.size() > 0) { if (polygons.size() > 0) {
Polygon[] p = polygons.toArray(new Polygon[0]); Polygon[] p = polygons.toArray(new Polygon[0]);
if (mp != null) if (mp != null) {
mp = (MultiPolygon) mp.union(new MultiPolygon(p, gc mp = (MultiPolygon) mp.union(new MultiPolygon(p, gc
.getFactory())); .getFactory()));
else } else {
mp = new MultiPolygon(p, gc.getFactory()); mp = new MultiPolygon(p, gc.getFactory());
} }
}
return mp; return mp;
} }
@ -527,8 +561,7 @@ public class GeospatialDataGenerator {
* *
* @param results * @param results
*/ */
private static void topologySimplifyQueryResults( private void topologySimplifyQueryResults(SpatialQueryResult[] results) {
SpatialQueryResult[] results) {
GeometryFactory gf = new GeometryFactory(); GeometryFactory gf = new GeometryFactory();
Geometry[] geoms = new Geometry[results.length]; Geometry[] geoms = new Geometry[results.length];
for (int i = 0; i < results.length; i++) { for (int i = 0; i < results.length; i++) {
@ -571,7 +604,7 @@ public class GeospatialDataGenerator {
* @param hull * @param hull
* @param geoData * @param geoData
*/ */
private static GeospatialData[] queryTimeZones(GeospatialMetadata metaData, private GeospatialData[] queryTimeZones(GeospatialMetadata metaData,
Geometry hull, GeospatialData[] geoData) throws SpatialException { Geometry hull, GeospatialData[] geoData) throws SpatialException {
GeospatialData[] rval = null; GeospatialData[] rval = null;
String timezonePathcastTable = metaData.getTimeZoneSource(); String timezonePathcastTable = metaData.getTimeZoneSource();
@ -627,8 +660,8 @@ public class GeospatialDataGenerator {
* @return * @return
* @throws SpatialException * @throws SpatialException
*/ */
private static GeospatialData[] queryParentAreas( private GeospatialData[] queryParentAreas(GeospatialMetadata metaData,
GeospatialMetadata metaData, Geometry hull) throws SpatialException { Geometry hull) throws SpatialException {
GeospatialData[] rval = null; GeospatialData[] rval = null;
String parentAreaSource = metaData.getParentAreaSource(); String parentAreaSource = metaData.getParentAreaSource();
if (parentAreaSource != null) { if (parentAreaSource != null) {
@ -653,7 +686,7 @@ public class GeospatialDataGenerator {
return rval; return rval;
} }
private static void persistGeoData(String site, private void persistGeoData(String site,
Map<GeospatialMetadata, GeospatialTime> times, Map<GeospatialMetadata, GeospatialTime> times,
GeospatialTime curTime, GeospatialDataSet geoData) GeospatialTime curTime, GeospatialDataSet geoData)
throws SerializationException, LocalizationException, JAXBException { throws SerializationException, LocalizationException, JAXBException {
@ -681,7 +714,7 @@ public class GeospatialDataGenerator {
lf.write(xml.getBytes()); lf.write(xml.getBytes());
} }
private static void deleteGeomFiles(String site, GeospatialTime time) { private void deleteGeomFiles(String site, GeospatialTime time) {
String fileName = time.getFileName(); String fileName = time.getFileName();
IPathManager pathMgr = PathManagerFactory.getPathManager(); IPathManager pathMgr = PathManagerFactory.getPathManager();
@ -701,8 +734,28 @@ public class GeospatialDataGenerator {
} }
} }
private static final String generateGeoDataFilename( private String generateGeoDataFilename(GeospatialMetadata metaData) {
GeospatialMetadata metaData) {
return metaData.getAreaSource() + "_" + metaData.hashCode() + ".bin"; return metaData.getAreaSource() + "_" + metaData.hashCode() + ".bin";
} }
private String getTimeStamp(GeospatialTime curTime,
GeospatialTime lastRunTime) {
long tmStampMs = 0;
if (curTime.getAreaSourceTime() != lastRunTime.getAreaSourceTime()) {
tmStampMs = curTime.getAreaSourceTime();
} else if (curTime.getParentSourceTime() != lastRunTime
.getParentSourceTime()) {
tmStampMs = curTime.getParentSourceTime();
} else if (curTime.getTimeZoneSourceTime() != lastRunTime
.getTimeZoneSourceTime()) {
tmStampMs = curTime.getTimeZoneSourceTime();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(tmStampMs);
return sdf.format(calendar.getTime());
}
} }

View file

@ -1,140 +0,0 @@
package com.raytheon.edex.plugin.warning.gis;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.site.SiteUtil;
import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialMetadata;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialTime;
import com.raytheon.uf.common.geospatial.SpatialException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
/**
* Compares current time in the database against the time of last run
* generated geometry and if they differ regenerates the files.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 07, 2014 16090 mgamazaychikov Initial creation
* </pre>
*
* @author mgamazaychikov
* @version 1.0
*/
public class GeospatialDataUpdater {
private final static IUFStatusHandler statusHandler = UFStatus
.getHandler(GeospatialDataUpdater.class);
private static final String UPDATER_ENDPOINT = "geospatialUpdateNotify";
private static Log logger = LogFactory.getLog(Util.class);
private static Set<GeospatialMetadata> metaDataSet = null;
private static Map<GeospatialMetadata, GeospatialTime> map = null;
public static void runCheckUpdate() throws SpatialException {
StringBuilder sb = new StringBuilder();
if (metaDataSet == null){
runInit();
}
GeospatialTime curTime = null;
GeospatialTime lastRunTime = null;
boolean generate = false;
sb.append("GeospatialDataUpdater: ");
for (GeospatialMetadata md : metaDataSet) {
lastRunTime = map.get(md);
try {
curTime = GeospatialDataGenerator.queryForCurrentTimes(md);
} catch (Exception e) {
throw new SpatialException(
"Unable to look up database version times.",
e);
}
if (!curTime.equals(lastRunTime)) {
generate = true;
break;
}
else {
generate = false;
}
}
if (generate){
sb.append("Geometry database time differs from current geometry metadata time: regenerating geometries");
}
else {
return;
}
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.info(sb.toString());
}
GeospatialDataGenerator.generateUniqueGeospatialMetadataGeometries();
String updatedTimeStamp = getTimeStamp(curTime, lastRunTime);
try {
EDEXUtil.getMessageProducer().sendAsync(UPDATER_ENDPOINT, updatedTimeStamp);
} catch (EdexException e) {
logger.error("Could not send message to alarm/alert", e);
}
metaDataSet = null;
}
private static String getTimeStamp(GeospatialTime curTime,
GeospatialTime lastRunTime) {
long tmStampMs = 0;
if (curTime.getAreaSourceTime() != lastRunTime.getAreaSourceTime()) {
tmStampMs = curTime.getAreaSourceTime();
} else if (curTime.getParentSourceTime() != lastRunTime.getParentSourceTime()) {
tmStampMs = curTime.getParentSourceTime();
} else if (curTime.getTimeZoneSourceTime() != lastRunTime.getTimeZoneSourceTime()) {
tmStampMs = curTime.getTimeZoneSourceTime();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(tmStampMs);
return sdf.format(calendar.getTime());
}
private static void runInit() {
String mySite = SiteUtil.getSite();
DialogConfiguration dialogConfig = null;
try {
dialogConfig = DialogConfiguration.loadDialogConfig(mySite);
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Error loading warngen config.xml", e);
return;
}
List<String> sites = GeospatialDataGenerator.getBackupSites(dialogConfig);
sites.add(0, mySite);
List<String> templates = GeospatialDataGenerator.getTemplates(dialogConfig);
metaDataSet = GeospatialDataGenerator.getMetaDataSet(sites, templates);
map = GeospatialFactory.loadLastRunGeoTimeSet(mySite);
StringBuilder sb = new StringBuilder();
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
sb.append("GeospatialDataUpdater has been re-inited");
statusHandler.info(sb.toString());
}
}
}

View file

@ -5,7 +5,6 @@
<bean id="textDBStaticDataListener" class="com.raytheon.edex.textdb.ingest.TextDBStaticDataSubscriber"> <bean id="textDBStaticDataListener" class="com.raytheon.edex.textdb.ingest.TextDBStaticDataSubscriber">
<constructor-arg value="jms-generic:topic:textDBFilesChanged"/> <constructor-arg value="jms-generic:topic:textDBFilesChanged"/>
</bean> </bean>
<bean id="siteMapListener" class="com.raytheon.edex.textdb.ingest.SiteMapNationalDatasetSubscriber" /> <bean id="siteMapListener" class="com.raytheon.edex.textdb.ingest.SiteMapNationalDatasetSubscriber" />
<bean factory-bean="ndmProc" factory-method="registerListener"> <bean factory-bean="ndmProc" factory-method="registerListener">

View file

@ -8,7 +8,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.common.dataplugin, Export-Package: com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.dataplugin.annotations, com.raytheon.uf.common.dataplugin.annotations,
com.raytheon.uf.common.dataplugin.defaults,
com.raytheon.uf.common.dataplugin.exception, com.raytheon.uf.common.dataplugin.exception,
com.raytheon.uf.common.dataplugin.message, com.raytheon.uf.common.dataplugin.message,
com.raytheon.uf.common.dataplugin.persist, com.raytheon.uf.common.dataplugin.persist,

View file

@ -21,7 +21,6 @@ package com.raytheon.uf.common.dataplugin;
import java.util.List; import java.util.List;
import com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
/** /**
@ -32,8 +31,8 @@ import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Mar 20, 2009 njensen Initial creation * Mar 20, 2009 njensen Initial creation.
* * Mar 13, 2014 2726 rjpeter Moved default values to set on plugin registration.
* </pre> * </pre>
* *
* @author njensen * @author njensen
@ -54,7 +53,7 @@ public class PluginProperties {
protected Class<PluginDataObject> record; protected Class<PluginDataObject> record;
protected int initialRetentionTime; protected Integer initialRetentionTime;
protected String pluginFQN; protected String pluginFQN;
@ -62,22 +61,40 @@ public class PluginProperties {
protected IHDFFilePathProvider pathProvider; protected IHDFFilePathProvider pathProvider;
/**
* Set the defaults for any fields that haven't already been set to a not
* null value.
*
* @param defaults
*/
public void setDefaults(PluginProperties defaults) {
/*
* pluginName, pluginFQN, dependencyFQNs, and record have no defaults to
* inherit
*/
if (database == null) {
database = defaults.getDatabase();
}
if (initializer == null) {
initializer = defaults.getInitializer();
}
if (dao == null) {
dao = defaults.getDao();
}
if (initialRetentionTime == null) {
initialRetentionTime = defaults.getInitialRetentionTime();
}
if (pathProvider == null) {
pathProvider = defaults.getPathProvider();
}
}
/** /**
* Compression to use on storage, if null, no compression * Compression to use on storage, if null, no compression
*/ */
protected String compression; protected String compression;
/**
* Constructor that initializes values to default values
*/
public PluginProperties() {
database = PluginPropertyDefaults.getDatabase();
initializer = PluginPropertyDefaults.getInitializer();
dao = PluginPropertyDefaults.getDao();
initialRetentionTime = PluginPropertyDefaults.getInitialRetentionTime();
pathProvider = PluginPropertyDefaults.getPathProvider();
}
/** /**
* @return the database * @return the database
*/ */
@ -112,9 +129,13 @@ public class PluginProperties {
* @return the initialRetentionTime * @return the initialRetentionTime
*/ */
public int getInitialRetentionTime() { public int getInitialRetentionTime() {
if (initialRetentionTime != null) {
return initialRetentionTime; return initialRetentionTime;
} }
return 0;
}
/** /**
* @param initialRetentionTime * @param initialRetentionTime
* the initialRetentionTime to set * the initialRetentionTime to set
@ -199,5 +220,4 @@ public class PluginProperties {
public void setCompression(String compression) { public void setCompression(String compression) {
this.compression = compression; this.compression = compression;
} }
} }

View file

@ -1,120 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.defaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
/**
* Defaults for the data plugins. Setters should only be called once through
* Spring XML configuration.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 20, 2009 njensen Initial creation
*
* </pre>
*
* @author njensen
* @version 1.0
*/
public class PluginPropertyDefaults {
protected static String database;
protected static Class<?> initializer;
protected static Class<?> dao;
protected static int initialRetentionTime;
protected static IHDFFilePathProvider pathProvider;
/**
* @return the database
*/
public static String getDatabase() {
return database;
}
/**
* @param database
* the database to set
*/
public void setDatabase(String database) {
PluginPropertyDefaults.database = database;
}
/**
* @return the initialRetentionTime
*/
public static int getInitialRetentionTime() {
return initialRetentionTime;
}
/**
* @param initialRetentionTime
* the initialRetentionTime to set
*/
public void setInitialRetentionTime(int initialRetentionTime) {
PluginPropertyDefaults.initialRetentionTime = initialRetentionTime;
}
/**
* @return the initializer
*/
public static Class<?> getInitializer() {
return initializer;
}
/**
* @param initializer
* the initializer to set
*/
public void setInitializer(Class<?> initializer) {
PluginPropertyDefaults.initializer = initializer;
}
/**
* @return the dao
*/
public static Class<?> getDao() {
return dao;
}
/**
* @param dao
* the dao to set
*/
public void setDao(Class<?> dao) {
PluginPropertyDefaults.dao = dao;
}
public static IHDFFilePathProvider getPathProvider() {
return pathProvider;
}
public void setPathProvider(IHDFFilePathProvider pathProvider) {
PluginPropertyDefaults.pathProvider = pathProvider;
}
}

View file

@ -13,4 +13,5 @@ Import-Package: com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.annotations, com.raytheon.uf.common.serialization.annotations,
org.apache.commons.lang org.apache.commons.lang
Require-Bundle: net.sf.cglib;bundle-version="2.1.3", Require-Bundle: net.sf.cglib;bundle-version="2.1.3",
com.raytheon.uf.common.status;bundle-version="1.11.11" com.raytheon.uf.common.status;bundle-version="1.11.11",
com.raytheon.uf.common.util

View file

@ -20,18 +20,13 @@
package com.raytheon.uf.common.message; package com.raytheon.uf.common.message;
import java.io.Serializable; import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.raytheon.uf.common.message.adapter.WsIdAdapter; import com.raytheon.uf.common.message.adapter.WsIdAdapter;
import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdapter; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdapter;
import com.raytheon.uf.common.util.SystemUtil;
/** /**
* The WsId contains the work station identification for the user. * * The WsId contains the work station identification for the user. *
@ -46,7 +41,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdap
* Sep 19, 2012 #1190 dgilling Cache host names so toPrettyString() doesn't * Sep 19, 2012 #1190 dgilling Cache host names so toPrettyString() doesn't
* get delayed behind DNS requests. * get delayed behind DNS requests.
* Sep 20, 2012 #1190 dgilling Create method getHostName(). * Sep 20, 2012 #1190 dgilling Create method getHostName().
* * Mar 20, 2014 2726 rjpeter Moved hostNameCache to SystemUtil.
* </pre> * </pre>
* *
* @author randerso * @author randerso
@ -57,32 +52,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdap
@DynamicSerializeTypeAdapter(factory = WsIdAdapter.class) @DynamicSerializeTypeAdapter(factory = WsIdAdapter.class)
public class WsId implements Serializable, ISerializableObject { public class WsId implements Serializable, ISerializableObject {
private static class BoundedMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final int maxSize;
public BoundedMap(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
/*
* (non-Javadoc)
*
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > maxSize;
}
}
private static final long serialVersionUID = 1L;
private static final Map<InetAddress, String> hostNameCache = Collections
.synchronizedMap(new BoundedMap<InetAddress, String>(100));
private final InetAddress networkId; private final InetAddress networkId;
private final String userName; private final String userName;
@ -169,25 +140,14 @@ public class WsId implements Serializable, ISerializableObject {
this.progName = "unknown"; this.progName = "unknown";
} }
this.pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean() this.pid = SystemUtil.getPid();
.getName().split("@")[0]);
this.threadId = Thread.currentThread().getId(); this.threadId = Thread.currentThread().getId();
if (networkId != null) { if (networkId != null) {
this.networkId = networkId; this.networkId = networkId;
} else { } else {
InetAddress addr = null; this.networkId = SystemUtil.getLocalAddress();
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
try {
addr = InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 });
} catch (UnknownHostException e1) {
// won't happen
}
}
this.networkId = addr;
} }
} }
@ -203,7 +163,7 @@ public class WsId implements Serializable, ISerializableObject {
long addr = 0; long addr = 0;
byte[] bytes = networkId.getAddress(); byte[] bytes = networkId.getAddress();
for (int i = bytes.length - 1; i >= 0; i--) { for (int i = bytes.length - 1; i >= 0; i--) {
addr = addr << 8 | (0xff & bytes[i]); addr = (addr << 8) | (0xff & bytes[i]);
} }
o.append(addr).append(':').append(userName).append(':') o.append(addr).append(':').append(userName).append(':')
@ -219,7 +179,7 @@ public class WsId implements Serializable, ISerializableObject {
* @return WsId as pretty string * @return WsId as pretty string
*/ */
public String toPrettyString() { public String toPrettyString() {
String hostname = retrieveFromHostCache(networkId); String hostname = SystemUtil.getHostName(networkId);
StringBuilder o = new StringBuilder(); StringBuilder o = new StringBuilder();
o.append(userName).append('@').append(hostname).append(':') o.append(userName).append('@').append(hostname).append(':')
@ -229,16 +189,6 @@ public class WsId implements Serializable, ISerializableObject {
return o.toString(); return o.toString();
} }
private String retrieveFromHostCache(InetAddress address) {
String hostName = hostNameCache.get(address);
if (hostName == null) {
hostName = address.getHostName();
hostNameCache.put(address, hostName);
}
return hostName;
}
/** /**
* @return the _networkId * @return the _networkId
*/ */
@ -247,7 +197,7 @@ public class WsId implements Serializable, ISerializableObject {
} }
public String getHostName() { public String getHostName() {
return retrieveFromHostCache(networkId); return SystemUtil.getHostName(networkId);
} }
/** /**
@ -287,13 +237,13 @@ public class WsId implements Serializable, ISerializableObject {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (int) (threadId ^ (threadId >>> 32)); result = (prime * result) + (int) (threadId ^ (threadId >>> 32));
result = prime * result result = (prime * result)
+ ((networkId == null) ? 0 : networkId.hashCode()); + ((networkId == null) ? 0 : networkId.hashCode());
result = prime * result + pid; result = (prime * result) + pid;
result = prime * result result = (prime * result)
+ ((progName == null) ? 0 : progName.hashCode()); + ((progName == null) ? 0 : progName.hashCode());
result = prime * result result = (prime * result)
+ ((userName == null) ? 0 : userName.hashCode()); + ((userName == null) ? 0 : userName.hashCode());
return result; return result;
} }

View file

@ -21,9 +21,11 @@ package com.raytheon.uf.common.util;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.UnknownHostException;
import java.net.SocketException; import java.util.Collections;
import java.util.Enumeration; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/** /**
* System utilities such as hostname and pid lookup. * System utilities such as hostname and pid lookup.
@ -35,18 +37,57 @@ import java.util.Enumeration;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Sep 26, 2011 rjpeter Initial creation * Sep 26, 2011 rjpeter Initial creation
* * Apr 10, 2014 2726 rjpeter Moved hostName caching logic from WsId to here.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
* @version 1.0 * @version 1.0
*/ */
public class SystemUtil { public class SystemUtil {
/**
* Map that can be limited to a given number of entries.
*/
private static class BoundedMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private final int maxSize;
public BoundedMap(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
/*
* (non-Javadoc)
*
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > maxSize;
}
}
private static final Map<InetAddress, String> hostNameCache = Collections
.synchronizedMap(new BoundedMap<InetAddress, String>(100));
protected static String hostName; protected static String hostName;
protected static Integer pid; protected static Integer pid;
protected static InetAddress addr;
static {
/* attempt to initialize fields */
getPid();
getHostName();
}
/**
* Returns the pid of the current process.
*
* @return
*/
public static int getPid() { public static int getPid() {
if (pid == null) { if (pid == null) {
pid = new Integer(ManagementFactory.getRuntimeMXBean().getName() pid = new Integer(ManagementFactory.getRuntimeMXBean().getName()
@ -56,43 +97,65 @@ public class SystemUtil {
return pid.intValue(); return pid.intValue();
} }
public static String getHostName() { /**
if (hostName == null) { * Returns the local INetAddress.
InetAddress addrToUse = null; *
boolean found = false; * @return
*/
public static InetAddress getLocalAddress() {
if (addr == null) {
try { try {
Enumeration<NetworkInterface> nis = NetworkInterface addr = InetAddress.getLocalHost();
.getNetworkInterfaces(); } catch (UnknownHostException e) {
while (nis.hasMoreElements() && !found) { try {
NetworkInterface ni = nis.nextElement(); return InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 });
ni.isVirtual(); } catch (UnknownHostException e1) {
ni.isUp(); // won't happen
Enumeration<InetAddress> addrs = ni.getInetAddresses();
while (addrs.hasMoreElements() && !found) {
InetAddress addr = addrs.nextElement();
if (addr.isLinkLocalAddress() == false
&& addr.isSiteLocalAddress() == false
&& addr.isLoopbackAddress() == false) {
addrToUse = addr;
found = true;
} }
} }
} }
} catch (SocketException e) { return addr;
e.printStackTrace();
} }
if (addrToUse == null) { /**
* Returns the hostName for the given inet address. The address is cached
* for the lifetime of the jvm after first look up. If a machine changes IPs
* it will get mapped to the wrong hostName until a reboot.
*
* @param address
* @return
*/
public static String getHostName(InetAddress address) {
String hostName = hostNameCache.get(address);
if (hostName == null) {
hostName = address.getHostName();
hostNameCache.put(address, hostName);
}
return hostName;
}
/**
* Returns local host name.
*
* @return
*/
public static String getHostName() {
if (hostName == null) {
InetAddress addr = getLocalAddress();
hostName = getHostName(addr);
if (hostName == null) {
String hostNameProp = System.getenv("HOSTNAME"); String hostNameProp = System.getenv("HOSTNAME");
if (hostNameProp != null && hostNameProp.trim().length() == 0) { if ((hostNameProp != null)
&& (hostNameProp.trim().length() == 0)) {
hostName = hostNameProp; hostName = hostNameProp;
} else { } else {
hostName = "localhost"; hostName = "localhost";
} }
} else {
hostName = addrToUse.getHostName();
} }
} }
return hostName; return hostName;
} }
} }

View file

@ -1,14 +1,11 @@
<beans <beans
xmlns="http://www.springframework.org/schema/beans" xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<camelContext id="clusteredActiveTableContext" <camelContext id="clusteredActiveTableContext"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="activeTablePendingRoute"> <route id="activeTablePendingRoute">
<from uri="jms-durable:queue:activeTablePending"/> <from uri="jms-durable:queue:activeTablePending"/>
@ -37,8 +34,7 @@
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register">
<constructor-arg ref="clusteredActiveTableContext" /> <constructor-arg ref="clusteredActiveTableContext" />
</bean> </bean>
</beans> </beans>

View file

@ -89,7 +89,7 @@
<bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/> <bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/>
<camelContext id="activeTableSharingRoutes" <camelContext id="activeTableSharingRoutes"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<route id="activeSiteForFetchATSrv"> <route id="activeSiteForFetchATSrv">
<from uri="jms-generic:queue:gfeSiteActivated" /> <from uri="jms-generic:queue:gfeSiteActivated" />
@ -102,8 +102,7 @@
</doTry> </doTry>
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register">
<constructor-arg ref="activeTableSharingRoutes" /> <constructor-arg ref="activeTableSharingRoutes" />
</bean> </bean>
</beans> </beans>

View file

@ -22,9 +22,7 @@ package com.raytheon.uf.edex.core;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
@ -52,12 +50,13 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 04/23/08 1088 chammack Split from Util * 04/23/2008 1088 chammack Split from Util
* 11/22/2010 2235 cjeanbap Added audio file to StatusMessage. * 11/22/2010 2235 cjeanbap Added audio file to StatusMessage.
* 02/02/2011 6500 cjeanbap Added paramter to method signature and * 02/02/2011 6500 cjeanbap Added paramter to method signature and
* properly assign source value. * properly assign source value.
* 06/12/2012 0609 djohnson Use EDEXUtil for EDEX_HOME. * 06/12/2012 0609 djohnson Use EDEXUtil for EDEX_HOME.
* 3/18/2013 1802 bphillip Added getList utility function * 03/18/2013 1802 bphillip Added getList utility function
* 04/10/2014 2726 rjpeter Added methods for waiting for edex to be running.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -81,20 +80,7 @@ public class EDEXUtil implements ApplicationContextAware {
// TODO // TODO
private static final String alertEndpoint = "alertVizNotify"; private static final String alertEndpoint = "alertVizNotify";
private static int serverId; private static final Object waiter = new Object();
static {
try {
String hostname = InetAddress.getLocalHost().getCanonicalHostName();
serverId = hostname.hashCode();
} catch (UnknownHostException e) {
serverId = 0;
// assume localhost, no network connection
}
}
public static int getServerId() {
return serverId;
}
@Override @Override
public void setApplicationContext(ApplicationContext context) public void setApplicationContext(ApplicationContext context)
@ -146,6 +132,30 @@ public class EDEXUtil implements ApplicationContextAware {
return "Operational".equals(System.getProperty("System.status")); return "Operational".equals(System.getProperty("System.status"));
} }
/**
* Blocks until EDEX is in the running state.
*/
public static void waitForRunning() {
synchronized (waiter) {
try {
while (!isRunning()) {
waiter.wait(15000);
}
} catch (InterruptedException e) {
// ignore
}
}
}
/**
* Called once EDEX is in a running state to notify all waiting clients.
*/
public static void notifyIsRunning() {
synchronized (waiter) {
waiter.notifyAll();
}
}
public static boolean containsESBComponent(String name) { public static boolean containsESBComponent(String name) {
return CONTEXT.containsBean(name); return CONTEXT.containsBean(name);
} }
@ -176,9 +186,10 @@ public class EDEXUtil implements ApplicationContextAware {
persistDir = envProperties.getEnvValue("PERSISTDIR"); persistDir = envProperties.getEnvValue("PERSISTDIR");
persistDir = FileUtil.convertFilePath(persistDir); persistDir = FileUtil.convertFilePath(persistDir);
if (persistDir == null) if (persistDir == null) {
throw new PluginException( throw new PluginException(
"Unable to retrieve value for the PERSISTDIR"); "Unable to retrieve value for the PERSISTDIR");
}
dbDirectory = new File(persistDir); dbDirectory = new File(persistDir);
dbDirectory.mkdirs(); dbDirectory.mkdirs();

View file

@ -0,0 +1,172 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.core;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
/**
* Base class for Timer based threading. Allows previous thread based paradigms
* to hook in to a camel context with minimal work.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 19, 2014 2826 rjpeter Initial creation.
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public abstract class EdexTimerBasedThread implements IContextStateProcessor {
/**
* Number of threads that have been started.
*/
protected final AtomicInteger threadCount = new AtomicInteger(0);
/**
* Current active threads.
*/
protected final List<Thread> threads = new LinkedList<Thread>();
/**
* Whether the container is running or not.
*/
protected volatile boolean running = true;
/**
* Interval thread should sleep between calls.
*/
protected int threadSleepInterval = 30000;
/**
* The name to use for the threads.
*
* @return
*/
public abstract String getThreadGroupName();
/**
* Method to do the work. Should return when done. Run method handles start
* up/shutdown mechanism.
*
* @throws Exception
*/
public abstract void process() throws Exception;
/**
* Can be overridden to do any work to cleanup the thread on shutdown.
*/
public void dispose() {
}
/**
* Called by camel to do the processing. Will run until the context is
* shutdown.
*/
public void run() {
synchronized (threads) {
threads.add(Thread.currentThread());
}
try {
Thread.currentThread().setName(
getThreadGroupName() + "-" + threadCount.incrementAndGet());
while (running) {
try {
process();
} catch (Exception e) {
UFStatus.getHandler().error(
"Error occurred during processing", e);
}
try {
/*
* use waiter to allow shutdown to wake thread for immediate
* shutdown
*/
synchronized (threads) {
threads.wait(threadSleepInterval);
}
} catch (InterruptedException e) {
// ignore
}
}
} finally {
synchronized (threads) {
threads.remove(Thread.currentThread());
threads.notify();
}
dispose();
}
}
@Override
public void preStart() {
}
@Override
public void postStart() {
}
@Override
public void preStop() {
running = false;
synchronized (threads) {
threads.notifyAll();
}
}
@Override
public void postStop() {
IUFStatusHandler statusHandler = UFStatus.getHandler();
String msg = "Waiting for " + getThreadGroupName()
+ " threads to finish";
synchronized (threads) {
while (!threads.isEmpty()) {
statusHandler.info(msg);
try {
threads.wait(10000);
} catch (Exception e) {
// ignore
}
}
}
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -17,10 +17,11 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
package com.raytheon.edex.plugin.warning.gis; package com.raytheon.uf.edex.core;
/** /**
* TODO Add Description * Methods to be called as part of the context life cycle for starting and
* stopping the context.
* *
* <pre> * <pre>
* *
@ -28,31 +29,36 @@ package com.raytheon.edex.plugin.warning.gis;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 24, 2011 rjpeter Initial creation * Feb 26, 2014 2726 rjpeter Initial creation
* *
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
* @version 1.0 * @version 1.0
*/ */
public interface IContextStateProcessor {
public class GeospatialDataGeneratorThread { /**
public GeospatialDataGeneratorThread() { * Perform any work that needs to be done before the context is started,
Thread t = new Thread("WarngenGeometryGenerator") { * such as initialization.
public void run() { */
// TODO: Move to camel timer, when camel upgraded to at least public void preStart();
// 2.8 and take advantage of single run timer
try { /**
// delay to allow server to start * Perform any work that needs to be done after the context is started, such
Thread.sleep(120000); * as sending notifications to clients.
} catch (InterruptedException e) { */
// ignore public void postStart();
}
GeospatialDataGenerator /**
.generateUniqueGeospatialMetadataGeometries(); * Perform any work that needs to be done before context is stopped, such as
// scan and clean old geometries * notifying async threads to stop.
} */
}; public void preStop();
t.start();
} /**
* Perform any work that needs to be done after the context is stopped, such
* as sending in memory data.
*/
public void postStop();
} }

View file

@ -35,8 +35,8 @@ import com.raytheon.uf.common.util.registry.RegistryException;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Aug 6, 2009 mschenke Initial creation * Aug 6, 2009 mschenke Initial creation.
* * Mar 19, 2014 2726 rjpeter Updated for graceful shutdown and easier spring dependency management.
* </pre> * </pre>
* *
* @author mschenke * @author mschenke
@ -47,7 +47,15 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
private static PluginRegistry instance = new PluginRegistry(); private static PluginRegistry instance = new PluginRegistry();
private List<IPluginRegistryChanged> listeners = new ArrayList<IPluginRegistryChanged>(); /**
* Plugin registry listeners.
*/
private final List<IPluginRegistryChanged> listeners = new ArrayList<IPluginRegistryChanged>();
/**
* Default values for plugins registered with the registry.
*/
private PluginProperties defaultPluginProperties;
private PluginRegistry() { private PluginRegistry() {
super(); super();
@ -61,6 +69,8 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
public Object register(String pluginName, PluginProperties pluginProperties) public Object register(String pluginName, PluginProperties pluginProperties)
throws RegistryException { throws RegistryException {
if (!registry.containsKey(pluginName)) { if (!registry.containsKey(pluginName)) {
pluginProperties.setDefaults(defaultPluginProperties);
super.register(pluginName, pluginProperties); super.register(pluginName, pluginProperties);
for (IPluginRegistryChanged iprc : listeners) { for (IPluginRegistryChanged iprc : listeners) {
iprc.pluginAdded(pluginName); iprc.pluginAdded(pluginName);
@ -77,4 +87,22 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
return this; return this;
} }
public PluginProperties getDefaultPluginProperties() {
return defaultPluginProperties;
}
public void setDefaultPluginProperties(
PluginProperties defaultPluginProperties) {
this.defaultPluginProperties = defaultPluginProperties;
}
/**
* The initial listeners to the plugin registry to ensure minimum
* requirements are meant via spring launching.
*
* @param listeners
*/
public void setInitialListeners(List<IPluginRegistryChanged> listeners) {
this.listeners.addAll(listeners);
}
} }

View file

@ -5,15 +5,9 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="cpgSrvDispatcher" class="com.raytheon.uf.edex.cpgsrv.CPGDispatcher" depends-on="commonTimeRegistered"/> <bean id="cpgSrvDispatcher" class="com.raytheon.uf.edex.cpgsrv.CPGDispatcher" depends-on="commonTimeRegistered"/>
<bean id="cpgsrvCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="cpgsrv-camel"/>
</bean>
<camelContext id="cpgsrv-camel" <camelContext id="cpgsrv-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="cpgProcessAlerts"> <route id="cpgProcessAlerts">
<from uri="direct-vm:processCPGAlerts"/> <from uri="direct-vm:processCPGAlerts"/>
<to uri="direct-vm:stageNotification"/> <to uri="direct-vm:stageNotification"/>
@ -21,8 +15,7 @@
</camelContext> </camelContext>
<camelContext id="clusteredCpgSrvRoutes" <camelContext id="clusteredCpgSrvRoutes"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<route id="cpgsrvListenerRoute"> <route id="cpgsrvListenerRoute">
<!-- Data from plugin notification --> <!-- Data from plugin notification -->
<from uri="jms-durable:queue:cpgsrvFiltering?concurrentConsumers=5"/> <from uri="jms-durable:queue:cpgsrvFiltering?concurrentConsumers=5"/>
@ -38,8 +31,7 @@
</doTry> </doTry>
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register">
<constructor-arg ref="clusteredCpgSrvRoutes" /> <constructor-arg ref="clusteredCpgSrvRoutes" />
</bean> </bean>
</beans> </beans>

View file

@ -49,7 +49,9 @@
<constructor-arg ref="saveOrUpdateHandler"/> <constructor-arg ref="saveOrUpdateHandler"/>
</bean> </bean>
<bean id="pluginFactory" class="com.raytheon.uf.edex.database.plugin.PluginFactory" factory-method="getInstance"/> <bean id="pluginFactory" class="com.raytheon.uf.edex.database.plugin.PluginFactory" factory-method="getInstance">
<property name="defaultPathProvider" ref="defaultPathProvider"/>
</bean>
<bean id="pluginFactoryRegisteredToDataURIUtil" <bean id="pluginFactoryRegisteredToDataURIUtil"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

View file

@ -41,7 +41,7 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Apr 28, 2010 #5050 rjpeter Initial creation * Apr 28, 2010 #5050 rjpeter Initial creation
* * May 29, 2014 2726 rjpeter Added initial listeners and properties for easier spring dependency management.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
@ -56,7 +56,9 @@ public class DatabasePluginRegistry extends
private static DatabasePluginRegistry instance = new DatabasePluginRegistry(); private static DatabasePluginRegistry instance = new DatabasePluginRegistry();
private List<IDatabasePluginRegistryChanged> listeners = new ArrayList<IDatabasePluginRegistryChanged>(); private final List<IDatabasePluginRegistryChanged> listeners = new ArrayList<IDatabasePluginRegistryChanged>();
private List<DatabasePluginProperties> initialProperties;
private DatabasePluginRegistry() { private DatabasePluginRegistry() {
super(); super();
@ -66,6 +68,18 @@ public class DatabasePluginRegistry extends
return instance; return instance;
} }
/**
* Called by spring to initialize the registry. Mainly used to ensure the
* base database plugin is always loaded.
*/
public void init() throws RegistryException {
if ((initialProperties != null) && !initialProperties.isEmpty()) {
for (DatabasePluginProperties dbProp : initialProperties) {
register(dbProp.getPluginFQN(), dbProp);
}
}
}
@Override @Override
public Object register(String pluginFQN, public Object register(String pluginFQN,
DatabasePluginProperties pluginProperties) throws RegistryException { DatabasePluginProperties pluginProperties) throws RegistryException {
@ -95,7 +109,8 @@ public class DatabasePluginRegistry extends
public void pluginAdded(String pluginName) { public void pluginAdded(String pluginName) {
PluginProperties props = PluginRegistry.getInstance() PluginProperties props = PluginRegistry.getInstance()
.getRegisteredObject(pluginName); .getRegisteredObject(pluginName);
if (props.getPluginFQN() != null && props.getPluginFQN().length() > 0) { if ((props.getPluginFQN() != null)
&& (props.getPluginFQN().length() > 0)) {
// multiple plugins may use the same jar file. // multiple plugins may use the same jar file.
if (!registry.containsKey(props.getPluginFQN())) { if (!registry.containsKey(props.getPluginFQN())) {
try { try {
@ -109,4 +124,14 @@ public class DatabasePluginRegistry extends
} }
} }
} }
public void setInitialListeners(
List<IDatabasePluginRegistryChanged> listeners) {
this.listeners.addAll(listeners);
}
public void setInitialProperties(
List<DatabasePluginProperties> initialProperties) {
this.initialProperties = initialProperties;
}
} }

View file

@ -31,7 +31,6 @@ import com.raytheon.uf.common.dataplugin.IPluginClassMapper;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.PluginProperties; import com.raytheon.uf.common.dataplugin.PluginProperties;
import com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
@ -50,7 +49,7 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
* Feb 06, 2009 1990 bphillip Refactored to use spring container * Feb 06, 2009 1990 bphillip Refactored to use spring container
* Mar 20, 2009 njensen Refactored to use PluginProperties * Mar 20, 2009 njensen Refactored to use PluginProperties
* May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings.
* * Mar 19, 2014 2726 rjpeter Added defaultPathProvider field.
* </pre> * </pre>
* *
* @author garmendariz * @author garmendariz
@ -75,7 +74,9 @@ public class PluginFactory implements IPluginClassMapper {
private Map<String, PluginDao> pluginDaoMap = new HashMap<String, PluginDao>(); private Map<String, PluginDao> pluginDaoMap = new HashMap<String, PluginDao>();
private Object daoMapLock = new Object(); private final Object daoMapLock = new Object();
private IHDFFilePathProvider defaultPathProvider = null;
/** /**
* Private constructor * Private constructor
@ -173,6 +174,7 @@ public class PluginFactory implements IPluginClassMapper {
* @throws PluginException * @throws PluginException
* If the class cannot be determined * If the class cannot be determined
*/ */
@Override
public Class<PluginDataObject> getPluginRecordClass(String pluginName) public Class<PluginDataObject> getPluginRecordClass(String pluginName)
throws PluginException { throws PluginException {
PluginProperties props = PluginRegistry.getInstance() PluginProperties props = PluginRegistry.getInstance()
@ -233,7 +235,7 @@ public class PluginFactory implements IPluginClassMapper {
if (props != null) { if (props != null) {
rval = props.getPathProvider(); rval = props.getPathProvider();
} else { } else {
rval = PluginPropertyDefaults.getPathProvider(); rval = defaultPathProvider;
} }
return rval; return rval;
} }
@ -280,4 +282,13 @@ public class PluginFactory implements IPluginClassMapper {
+ " is not registered with the PluginRegistry"); + " is not registered with the PluginRegistry");
} }
} }
/**
* Set the default path provider. Used by spring to configure the factory.
*
* @param defaultPathProvider
*/
public void setDefaultPathProvider(IHDFFilePathProvider defaultPathProvider) {
this.defaultPathProvider = defaultPathProvider;
}
} }

View file

@ -20,13 +20,8 @@
class="com.raytheon.uf.edex.datadelivery.event.notification.NotificationPurge" class="com.raytheon.uf.edex.datadelivery.event.notification.NotificationPurge"
depends-on="ddEventRegister" /> depends-on="ddEventRegister" />
<bean id="noitfyCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ddNotify-camel" />
</bean>
<camelContext id="ddNotify-camel" xmlns="http://camel.apache.org/schema/spring" <camelContext id="ddNotify-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<route id="notificationPurgeRoute"> <route id="notificationPurgeRoute">
<from uri="timer://notifiyPurge?period=60s" /> <from uri="timer://notifiyPurge?period=60s" />

View file

@ -10,12 +10,17 @@
<constructor-arg ref="ProviderHandler" /> <constructor-arg ref="ProviderHandler" />
</bean> </bean>
<bean id="DataSetMetaDataPurgeLauncher" class="com.raytheon.uf.edex.datadelivery.harvester.purge.DataSetMetaDataPurgeLauncher"
factory-method="getInstance" depends-on="DbInit">
</bean>
<camelContext id="MetaData-context" <camelContext id="MetaData-context"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"> errorHandlerRef="errorHandler">
<endpoint id="metaDataCron" uri="quartz://datadelivery/harvester/?cron=${metadata-process.cron}"/> <endpoint id="metaDataCron" uri="quartz://datadelivery/harvester/?cron=${metadata-process.cron}"/>
<endpoint id="harvesterProcessWorkEndpoint" uri="jms-generic:queue:metaDataProcessWork?concurrentConsumers=${metadata-process.threads}&amp;threadName=harvester"/> <endpoint id="harvesterProcessWorkEndpoint" uri="jms-generic:queue:metaDataProcessWork?concurrentConsumers=${metadata-process.threads}&amp;threadName=harvester"/>
<endpoint id="datasetMetaDataPurgeCron" uri="quartz://datadelivery/metaDataPurge/?cron=${metadata-purge.cron}"/>
<route id="metaDataProcess"> <route id="metaDataProcess">
<from uri="metaDataCron" /> <from uri="metaDataCron" />
@ -35,19 +40,6 @@
</doTry> </doTry>
</route> </route>
</camelContext>
<!-- Start of DataSetMetaData purge configuration -->
<bean id="DataSetMetaDataPurgeLauncher" class="com.raytheon.uf.edex.datadelivery.harvester.purge.DataSetMetaDataPurgeLauncher"
factory-method="getInstance" depends-on="DbInit">
</bean>
<camelContext id="DataSetMetaDataPurge-context"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="datasetMetaDataPurgeCron" uri="quartz://datadelivery/metaDataPurge/?cron=${metadata-purge.cron}"/>
<route id="metaDataPurge"> <route id="metaDataPurge">
<from uri="datasetMetaDataPurgeCron" /> <from uri="datasetMetaDataPurgeCron" />
<to uri="jms-generic:queue:metaDataPurgeWork" /> <to uri="jms-generic:queue:metaDataPurgeWork" />
@ -67,6 +59,4 @@
</route> </route>
</camelContext> </camelContext>
<!-- End of DataSetMetaData purge configuration -->
</beans> </beans>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="dataDeliveryRestClient" class="com.raytheon.uf.edex.datadelivery.registry.web.DataDeliveryRESTServices"/> <bean id="dataDeliveryRestClient" class="com.raytheon.uf.edex.datadelivery.registry.web.DataDeliveryRESTServices"/>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="FederatedRegistryMonitor" class="com.raytheon.uf.edex.datadelivery.registry.availability.FederatedRegistryMonitor"> <bean id="FederatedRegistryMonitor" class="com.raytheon.uf.edex.datadelivery.registry.availability.FederatedRegistryMonitor">
<constructor-arg ref="registryObjectDao"/> <constructor-arg ref="registryObjectDao"/>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- This should be moved to a grid OGC plugin when one exists --> <!-- This should be moved to a grid OGC plugin when one exists -->
<bean factory-bean="metadataAdapterRegistry" factory-method="register"> <bean factory-bean="metadataAdapterRegistry" factory-method="register">

View file

@ -20,20 +20,6 @@
</bean> </bean>
<camelContext id="handleoupAckMgrContext" xmlns="http://camel.apache.org/schema/spring" <camelContext id="handleoupAckMgrContext" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<route id="oupAckMGrRoute">
<from uri="jms-generic:topic:mhs.ackmgr" />
<doTry>
<bean ref="oupAckMgr" method="processAck" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:oup?level=INFO"/>
</doCatch>
</doTry>
</route>
</camelContext>
<camelContext id="handleoupFilePushContext" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"> errorHandlerRef="errorHandler">
<!-- Non clustered, specifically used by handleOUP.py to push published <!-- Non clustered, specifically used by handleOUP.py to push published
files directly into stream --> files directly into stream -->
@ -50,11 +36,21 @@
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
<to <to
uri="log:manual?level=ERROR&amp;showBody=true" /> uri="log:oup?level=ERROR&amp;showBody=true" />
</doCatch> </doCatch>
</doTry> </doTry>
</route> </route>
<route id="oupAckMGrRoute">
<from uri="jms-generic:topic:mhs.ackmgr" />
<doTry>
<bean ref="oupAckMgr" method="processAck" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:oup?level=INFO"/>
</doCatch>
</doTry>
</route>
</camelContext> </camelContext>
</beans> </beans>

View file

@ -10,8 +10,7 @@
<camelContext id="distro" <camelContext id="distro"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" errorHandlerRef="errorHandler">
autoStartup="false">
<endpoint id="refreshDistributionCron" uri="quartz://refreshDist/refreshDistRoute/?cron=${distribution.cron}"/> <endpoint id="refreshDistributionCron" uri="quartz://refreshDist/refreshDistRoute/?cron=${distribution.cron}"/>
@ -59,8 +58,4 @@
</doTry> </doTry>
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="distro"/>
</bean>
</beans> </beans>

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: Camel Plug-in Bundle-Name: Camel Plug-in
Bundle-SymbolicName: com.raytheon.uf.edex.esb.camel Bundle-SymbolicName: com.raytheon.uf.edex.esb.camel
Bundle-Version: 1.12.1174.qualifier Bundle-Version: 1.14.0
Bundle-Vendor: Raytheon Bundle-Vendor: Raytheon
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.apache.camel;bundle-version="1.0.0", Require-Bundle: org.apache.camel;bundle-version="1.0.0",
@ -19,7 +19,7 @@ Require-Bundle: org.apache.camel;bundle-version="1.0.0",
com.raytheon.uf.common.comm;bundle-version="1.12.1174", com.raytheon.uf.common.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.json;bundle-version="1.0.0" com.raytheon.uf.common.json;bundle-version="1.0.0"
Export-Package: com.raytheon.uf.edex.esb.camel, Export-Package: com.raytheon.uf.edex.esb.camel,
com.raytheon.uf.edex.esb.camel.directvm, com.raytheon.uf.edex.esb.camel.context,
com.raytheon.uf.edex.esb.camel.jms com.raytheon.uf.edex.esb.camel.jms
Import-Package: com.raytheon.uf.common.event, Import-Package: com.raytheon.uf.common.event,
com.raytheon.uf.common.message, com.raytheon.uf.common.message,

View file

@ -31,7 +31,9 @@ import java.util.concurrent.CountDownLatch;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.PropertiesUtil; import com.raytheon.uf.common.util.PropertiesUtil;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.modes.EDEXModesUtil; import com.raytheon.uf.edex.core.modes.EDEXModesUtil;
import com.raytheon.uf.edex.esb.camel.context.ContextManager; import com.raytheon.uf.edex.esb.camel.context.ContextManager;
@ -54,7 +56,7 @@ import com.raytheon.uf.edex.esb.camel.context.ContextManager;
* Feb 14, 2013 1638 mschenke Removing activemq reference in stop * Feb 14, 2013 1638 mschenke Removing activemq reference in stop
* Apr 22, 2013 #1932 djohnson Use countdown latch for a shutdown hook. * Apr 22, 2013 #1932 djohnson Use countdown latch for a shutdown hook.
* Dec 04, 2013 2566 bgonzale refactored mode methods to a utility in edex.core. * Dec 04, 2013 2566 bgonzale refactored mode methods to a utility in edex.core.
* * Mar 19, 2014 2726 rjpeter Added graceful shutdown.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -66,15 +68,36 @@ public class Executor {
private static final CountDownLatch shutdownLatch = new CountDownLatch(1); private static final CountDownLatch shutdownLatch = new CountDownLatch(1);
public static void start() throws Exception { public static void start() throws Exception {
final long t0 = System.currentTimeMillis();
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@Override @Override
public void run() { public void run() {
ContextManager ctxMgr = ContextManager.getInstance();
long t1 = System.currentTimeMillis();
System.out
.println("**************************************************");
System.out
.println("* EDEX ESB is shutting down *");
System.out
.println("**************************************************");
ctxMgr.stopContexts();
long t2 = System.currentTimeMillis();
System.out
.println("**************************************************");
System.out
.println("* EDEX ESB is shut down *");
System.out.println("* Total time to shutdown: "
+ TimeUtil.prettyDuration(t2 - t1));
System.out.println("* EDEX ESB uptime: "
+ TimeUtil.prettyDuration(t2 - t0));
System.out
.println("**************************************************");
shutdownLatch.countDown(); shutdownLatch.countDown();
} }
}); });
long t0 = System.currentTimeMillis();
Thread.currentThread().setName("EDEXMain"); Thread.currentThread().setName("EDEXMain");
System.setProperty("System.status", "Starting"); System.setProperty("System.status", "Starting");
@ -113,7 +136,7 @@ public class Executor {
String modeName = System.getProperty("edex.run.mode"); String modeName = System.getProperty("edex.run.mode");
if (modeName != null && modeName.length() > 0) { if ((modeName != null) && (modeName.length() > 0)) {
System.out.println("EDEX run configuration: " + modeName); System.out.println("EDEX run configuration: " + modeName);
} else { } else {
System.out System.out
@ -123,8 +146,7 @@ public class Executor {
+ System.getProperty("aw.site.identifier")); + System.getProperty("aw.site.identifier"));
List<String> discoveredPlugins = EDEXModesUtil.extractSpringXmlFiles( List<String> discoveredPlugins = EDEXModesUtil.extractSpringXmlFiles(
xmlFiles, xmlFiles, modeName);
modeName);
System.out.println(); System.out.println();
System.out.println(" "); System.out.println(" ");
@ -141,8 +163,10 @@ public class Executor {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
xmlFiles.toArray(new String[xmlFiles.size()])); xmlFiles.toArray(new String[xmlFiles.size()]));
ContextManager ctxMgr = (ContextManager) context ContextManager ctxMgr = (ContextManager) context
.getBean("contextManager"); .getBean("contextManager");
// start final routes // start final routes
ctxMgr.startContexts(); ctxMgr.startContexts();
@ -151,11 +175,12 @@ public class Executor {
.println("**************************************************"); .println("**************************************************");
System.out System.out
.println("* EDEX ESB is now operational *"); .println("* EDEX ESB is now operational *");
System.out.println("* Total startup time: " + ((t1 - t0) / 1000) System.out.println("* Total startup time: "
+ " seconds"); + TimeUtil.prettyDuration(t1 - t0));
System.out System.out
.println("**************************************************"); .println("**************************************************");
System.setProperty("System.status", "Operational"); System.setProperty("System.status", "Operational");
EDEXUtil.notifyIsRunning();
shutdownLatch.await(); shutdownLatch.await();
} }

View file

@ -19,51 +19,106 @@
**/ **/
package com.raytheon.uf.edex.esb.camel; package com.raytheon.uf.edex.esb.camel;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.ConfigurationException;
import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelContext; import org.apache.camel.CamelContext;
import org.apache.camel.CamelExecutionException; import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern; import org.apache.camel.ExchangePattern;
import org.apache.camel.Processor;
import org.apache.camel.ProducerTemplate; import org.apache.camel.ProducerTemplate;
import org.apache.camel.Route; import org.apache.camel.Route;
import org.springframework.beans.BeansException; import org.apache.camel.model.ProcessorDefinition;
import org.springframework.context.ApplicationContext; import org.apache.camel.spi.InterceptStrategy;
import org.springframework.context.ApplicationContextAware;
import com.raytheon.uf.common.message.IMessage; import com.raytheon.uf.common.message.IMessage;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.core.IMessageProducer; import com.raytheon.uf.edex.core.IMessageProducer;
import com.raytheon.uf.edex.esb.camel.context.ContextData;
import com.raytheon.uf.edex.esb.camel.context.ContextManager;
/** /**
* Sends message to endpoints programmatically. * Sends message to endpoints programmatically. Implements the camel
* {@link InterceptStrategy} to allow for tracking of camel dependencies where
* possible so that the ProducerTemplate is created from the correct context.
* *
* <pre> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 14, 2008 njensen Initial creation * Nov 14, 2008 njensen Initial creation.
* Mar 27, 2014 2726 rjpeter Modified for graceful shutdown changes.
* </pre> * </pre>
* *
* @author njensen * @author njensen
* @version 1.0 * @version 1.0
*/ */
public class MessageProducer implements ApplicationContextAware, public class MessageProducer implements IMessageProducer, InterceptStrategy {
IMessageProducer { private final IUFStatusHandler statusHandler = UFStatus
.getHandler(MessageProducer.class);
private static ApplicationContext springContext; /*
* setup via an interceptor used for tracking what context the current
* thread is participating in for dependency management of runtime
* IMessageProducer message sends.
*/
private final ThreadLocal<CamelContext> currentThreadContext = new ThreadLocal<CamelContext>();
private static List<CamelContext> camelContextList; private final ConcurrentMap<CamelContext, ProducerTemplate> contextProducerMap = new ConcurrentHashMap<CamelContext, ProducerTemplate>();
private static Map<String, String> endpointIdUriMap = new HashMap<String, String>(); /**
* List of messages waiting to be sent.
*/
private final List<WaitingMessage> waitingMessages = new LinkedList<WaitingMessage>();
private static Map<String, CamelContext> endpointContextMap = new HashMap<String, CamelContext>(); /**
* Internal variable for tracking if messages should be queued or not.
*/
private volatile boolean started = false;
private static Map<CamelContext, ProducerTemplate> contextProducerMap = new HashMap<CamelContext, ProducerTemplate>(); /**
* Constructor that launches an internal thread that will send all async
* messages that queue up while camel starts up.
*/
public MessageProducer() {
Thread t = new Thread() {
@Override
public void run() {
EDEXUtil.waitForRunning();
started = true;
sendPendingAsyncMessages();
}
};
t.setName("MessageProducer-pendingMessageSender");
t.start();
}
/**
* Returns the ContextData
*
* @return
* @throws EdexException
*/
protected ContextData getContextData() throws EdexException {
try {
return ContextManager.getInstance().getContextData();
} catch (ConfigurationException e) {
throw new EdexException("Unable to look up camel context data", e);
}
}
/* /*
* (non-Javadoc) * (non-Javadoc)
@ -72,21 +127,42 @@ public class MessageProducer implements ApplicationContextAware,
* com.raytheon.uf.edex.esb.camel.IMessageProducer#sendAsync(java.lang.String * com.raytheon.uf.edex.esb.camel.IMessageProducer#sendAsync(java.lang.String
* , java.lang.Object) * , java.lang.Object)
*/ */
@Override
public void sendAsync(String endpoint, Object message) throws EdexException { public void sendAsync(String endpoint, Object message) throws EdexException {
CamelContext camelContext = getCamelContext(endpoint); if (!started && queueWaitingMessage(WaitingType.ID, endpoint, message)) {
ProducerTemplate template = getProducerTemplate(camelContext); return;
String uri = endpointIdUriMap.get(endpoint); }
Map<String, Object> headers = getHeaders(message);
String uri = getContextData().getEndpointUriForRouteId(endpoint);
sendAsyncUri(uri, message);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.core.IMessageProducer#sendAsyncUri(java.lang.String,
* java.lang.Object)
*/
@Override
public void sendAsyncUri(String uri, Object message) throws EdexException {
if (!started && queueWaitingMessage(WaitingType.URI, uri, message)) {
return;
}
try { try {
ProducerTemplate template = getProducerTemplateForUri(uri);
Map<String, Object> headers = getHeaders(message);
if (headers != null) { if (headers != null) {
template.sendBodyAndHeaders(uri, ExchangePattern.InOnly, template.sendBodyAndHeaders(uri, ExchangePattern.InOnly,
message, headers); message, headers);
} else { } else {
template.sendBody(uri, ExchangePattern.InOnly, message); template.sendBody(uri, ExchangePattern.InOnly, message);
} }
} catch (CamelExecutionException e) { } catch (Exception e) {
throw new EdexException("Error sending asynchronous message: " throw new EdexException("Error sending asynchronous message: "
+ message + " to endpoint: " + uri, e); + message + " to uri: " + uri, e);
} }
} }
@ -97,114 +173,112 @@ public class MessageProducer implements ApplicationContextAware,
* com.raytheon.uf.edex.esb.camel.IMessageProducer#sendSync(java.lang.String * com.raytheon.uf.edex.esb.camel.IMessageProducer#sendSync(java.lang.String
* , java.lang.Object) * , java.lang.Object)
*/ */
@Override
public Object sendSync(String endpoint, Object message) public Object sendSync(String endpoint, Object message)
throws EdexException { throws EdexException {
CamelContext camelContext = getCamelContext(endpoint); if (!started) {
ProducerTemplate template = getProducerTemplate(camelContext); throw new EdexException("Cannot send synchronous message to "
String uri = endpointIdUriMap.get(endpoint); + endpoint + " before EDEX has started");
Map<String, Object> headers = getHeaders(message); }
String uri = getContextData().getEndpointUriForRouteId(endpoint);
try { try {
ProducerTemplate template = getProducerTemplateForUri(uri);
Map<String, Object> headers = getHeaders(message);
if (headers != null) { if (headers != null) {
return template.sendBodyAndHeaders(uri, ExchangePattern.OutIn, return template.sendBodyAndHeaders(uri, ExchangePattern.OutIn,
message, headers); message, headers);
} else { } else {
return template.sendBody(uri, ExchangePattern.OutIn, message); return template.sendBody(uri, ExchangePattern.OutIn, message);
} }
} catch (CamelExecutionException e) { } catch (Exception e) {
throw new EdexException("Error sending synchronous message: " throw new EdexException("Error sending synchronous message: "
+ message + " to uri: " + uri, e); + message + " to uri: " + uri, e);
} }
} }
private synchronized CamelContext getCamelContext(String endpointId) /**
throws EdexException { * Queues up an async message for sending to an endpoint.
CamelContext ctx = endpointContextMap.get(endpointId); *
if (ctx == null) { * @param type
List<CamelContext> list = getCamelContextList(); * @param endpoint
boolean found = false; * @param message
for (CamelContext c : list) { * @return
List<Route> routes = c.getRoutes(); */
for (Route r : routes) { private boolean queueWaitingMessage(WaitingType type, String endpoint,
if (r.getProperties() != null Object message) {
&& endpointId.equals(r.getProperties().get( synchronized (waitingMessages) {
Route.ID_PROPERTY))) { // make sure container hasn't started while waiting
ctx = c; if (!started) {
endpointContextMap.put(endpointId, ctx); WaitingMessage wm = new WaitingMessage();
endpointIdUriMap.put(endpointId, r.getEndpoint() wm.type = type;
.getEndpointUri()); wm.dest = endpoint;
found = true; wm.msg = message;
break; waitingMessages.add(wm);
return true;
} }
}
if (found) { return false;
break;
}
}
if (ctx == null) {
throw new EdexException("Route id " + endpointId
+ " not found. Check loaded spring configurations.");
} }
} }
return ctx; /**
* Returns the a producer template for the CamelContext this thread is
* currently a part of. If thread is not part of a context, will use context
* of the uri. If the uri is not registered in this jvm, will use the first
* context available.
*
* @return
*/
protected ProducerTemplate getProducerTemplateForUri(String uri)
throws ConfigurationException, EdexException {
CamelContext ctx = currentThreadContext.get();
if (ctx == null) {
ContextData contextData = getContextData();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if (typeAndName != null) {
Route route = contextData.getRouteForEndpointName(typeAndName
.getSecond());
if (route != null) {
ctx = route.getRouteContext().getCamelContext();
}
} }
private ProducerTemplate getProducerTemplate(CamelContext ctx) { if (ctx == null) {
// this jvm does not consume from this route, use first context
List<CamelContext> contexts = contextData.getContexts();
if (contexts.size() > 0) {
// should always be a context defined
ctx = contexts.iterator().next();
}
}
}
if (ctx != null) {
ProducerTemplate tmp = contextProducerMap.get(ctx); ProducerTemplate tmp = contextProducerMap.get(ctx);
if (tmp == null) { if (tmp == null) {
tmp = ctx.createProducerTemplate(); tmp = ctx.createProducerTemplate();
contextProducerMap.put(ctx, tmp); ProducerTemplate prev = contextProducerMap
} .putIfAbsent(ctx, tmp);
if ((prev != null) && (prev != tmp)) {
try {
tmp.stop();
} catch (Exception e) {
}
tmp = prev;
}
}
return tmp; return tmp;
} }
private synchronized List<CamelContext> getCamelContextList() { throw new ConfigurationException(
if (springContext == null) { "Could not find a CamelContext for routing to uri [" + uri
springContext = EDEXUtil.getSpringContext(); + "]. Check loaded spring configurations.");
}
if (springContext == null) {
throw new IllegalStateException(
"Spring context has not been initialized on "
+ MessageProducer.class.getName());
}
if (camelContextList == null) {
camelContextList = new ArrayList<CamelContext>();
String[] camelContexts = springContext
.getBeanNamesForType(CamelContext.class);
for (String name : camelContexts) {
CamelContext c = (CamelContext) springContext.getBean(name);
camelContextList.add(c);
}
}
return camelContextList;
}
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
springContext = context;
}
@Override
public void sendAsyncUri(String uri, Object message) throws EdexException {
CamelContext ctx = getCamelContextList().get(0);
ProducerTemplate template = getProducerTemplate(ctx);
Map<String, Object> headers = getHeaders(message);
try {
if (headers != null) {
template.sendBodyAndHeaders(uri, ExchangePattern.InOnly,
message, headers);
} else {
template.sendBody(uri, ExchangePattern.InOnly, message);
}
} catch (CamelExecutionException e) {
throw new EdexException("Error sending asynchronous message: " + message
+ " to uri: " + uri, e);
}
} }
private Map<String, Object> getHeaders(Object message) { private Map<String, Object> getHeaders(Object message) {
@ -224,4 +298,90 @@ public class MessageProducer implements ApplicationContextAware,
return headers; return headers;
} }
/**
* Sends any messages that were queued up while Camel started.
*/
protected void sendPendingAsyncMessages() {
synchronized (waitingMessages) {
for (WaitingMessage wm : waitingMessages) {
try {
switch (wm.type) {
case ID:
sendAsync(wm.dest, wm.msg);
break;
case URI:
sendAsyncUri(wm.dest, wm.msg);
break;
}
} catch (Exception e) {
statusHandler
.error("Error occurred sending startup delayed async message",
e);
}
}
}
}
/**
* Setup for use with MessageProducer to track what context the current
* operating thread is using.
*/
@Override
public Processor wrapProcessorInInterceptors(final CamelContext context,
final ProcessorDefinition<?> definition, final Processor target,
final Processor nextTarget) throws Exception {
return new AsyncProcessor() {
@Override
public void process(Exchange exchange) throws Exception {
/*
* track the thread this context is using for proper dependency
* management.
*/
MessageProducer.this.currentThreadContext.set(context);
target.process(exchange);
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
/*
* track the thread this context is using for proper dependency
* management.
*/
MessageProducer.this.currentThreadContext.set(context);
try {
target.process(exchange);
} catch (Throwable e) {
exchange.setException(e);
}
callback.done(true);
return true;
}
@Override
public String toString() {
return "MessageProducer - ContainerWideInterceptor[" + target
+ "]";
}
};
}
/**
* Enum for handling whether the waiting type was uri or msg.
*/
private enum WaitingType {
ID, URI
};
/**
* Inner class for handling messages sent before edex is up.
*/
private class WaitingMessage {
private WaitingType type;
private String dest;
private Object msg;
}
} }

View file

@ -20,12 +20,13 @@
package com.raytheon.uf.edex.esb.camel; package com.raytheon.uf.edex.esb.camel;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import org.apache.camel.Exchange; import org.apache.camel.Exchange;
import org.apache.camel.Processor; import org.apache.camel.Processor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/** /**
* Performs a transform from Strings to Files * Performs a transform from Strings to Files
@ -38,9 +39,9 @@ import org.apache.commons.logging.LogFactory;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Dec 1, 2008 chammack Initial creation * Dec 1, 2008 chammack Initial creation.
* 15Jul2010 6624 garmendariz Log error and interrupt if file missing * 15Jul2010 6624 garmendariz Log error and interrupt if file missing.
* * Mar 19, 2014 2726 rjpeter Added debug logging of file being processed.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -49,7 +50,8 @@ import org.apache.commons.logging.LogFactory;
public class StringToFile implements Processor { public class StringToFile implements Processor {
protected transient Log logger = LogFactory.getLog(getClass()); protected final IUFStatusHandler statusHandler = UFStatus
.getHandler(StringToFile.class);
/* /*
* (non-Javadoc) * (non-Javadoc)
@ -69,12 +71,15 @@ public class StringToFile implements Processor {
// if file does not exist, set fault to interrupt processing // if file does not exist, set fault to interrupt processing
if (!file.exists()) { if (!file.exists()) {
logger.error("File does not exist : " + bodyString); statusHandler.error("File does not exist : " + bodyString);
arg0.getOut().setFault(true); arg0.getOut().setFault(true);
} else { } else {
arg0.getIn().setBody(file); arg0.getIn().setBody(file);
arg0.getIn().setHeader("ingestFileName", file.toString()); arg0.getIn().setHeader("ingestFileName", file.toString());
arg0.getIn().setHeader("dequeueTime", System.currentTimeMillis()); arg0.getIn().setHeader("dequeueTime", System.currentTimeMillis());
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.debug("Processing file: " + file.toString());
}
} }
} }
} }

View file

@ -1,190 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.ServiceStatus;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
/**
* Dynamically starts/stops a context and its associated routes so that only one
* context in the cluster is running. This should mainly be used for reading
* from topics so that only box is processing the topic data in the cluster for
* singleton type events.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 10, 2010 5050 rjpeter Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Stop consumers instead of whole context
* May 14, 2013 1989 njensen Camel 2.11 compatibility
* Aug 26, 2013 DR 2272 bkowal Append an optional suffix to the cluster task details
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ClusteredContextManager {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ClusteredContextManager.class);
private static final String taskName = "ClusteredContext";
private String myName;
private List<CamelContext> clusteredContextList = new ArrayList<CamelContext>();
private int timeOutMillis;
private static ClusteredContextManager instance = new ClusteredContextManager();
public static ClusteredContextManager getInstance() {
return instance;
}
private ClusteredContextManager() {
myName = getHostName() + ":" + System.getProperty("edex.run.mode");
}
private static String getHostName() {
String hostname = System.getenv("HOSTNAME");
if (hostname == null) {
hostname = System.getenv("COMPUTERNAME");
}
if (hostname == null) {
hostname = System.getenv("HOST");
}
if (hostname == null) {
try {
Enumeration<NetworkInterface> nis = NetworkInterface
.getNetworkInterfaces();
while (nis.hasMoreElements()) {
NetworkInterface ni = nis.nextElement();
ni.isVirtual();
ni.isUp();
Enumeration<InetAddress> addrs = ni.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = addrs.nextElement();
if (addr.isLinkLocalAddress() == false
&& addr.isSiteLocalAddress() == false
&& addr.isLoopbackAddress() == false) {
hostname = addr.getHostName();
}
}
}
} catch (SocketException e) {
statusHandler.handle(Priority.ERROR,
"Failed to determine hostname", e);
}
}
return hostname;
}
public void checkClusteredContexts() {
String suffix = ClusterLockUtils.CLUSTER_SUFFIX;
for (CamelContext camelContext : clusteredContextList) {
String contextName = camelContext.getName() + suffix;
ClusterTask lock = ClusterLockUtils.lock(taskName, contextName,
myName, timeOutMillis, false);
boolean activateRoute = false;
switch (lock.getLockState()) {
case ALREADY_RUNNING:
// check if we already have lock
activateRoute = lock.getExtraInfo().equals(myName);
break;
case SUCCESSFUL:
activateRoute = true;
break;
default:
}
try {
if (activateRoute) {
ClusterLockUtils.updateLockTime(taskName, contextName,
System.currentTimeMillis());
for (Route route : camelContext.getRoutes()) {
String routeId = route.getId();
ServiceStatus status = camelContext
.getRouteStatus(routeId);
if (status == ServiceStatus.Stopped
|| status == ServiceStatus.Stopping) {
camelContext.startRoute(routeId);
} else if (status == ServiceStatus.Suspended
|| status == ServiceStatus.Suspending) {
camelContext.resumeRoute(routeId);
}
}
} else {
for (Route route : camelContext.getRoutes()) {
String routeId = route.getId();
ServiceStatus status = camelContext
.getRouteStatus(routeId);
if (status == ServiceStatus.Started
|| status == ServiceStatus.Starting) {
// CamelContext API says to use suspend, not stop
camelContext.suspendRoute(routeId);
}
}
}
} catch (Exception e) {
StringBuilder msg = new StringBuilder();
msg.append("Failed to ");
if (activateRoute) {
msg.append("start ");
} else {
msg.append("suspend ");
}
msg.append("context ");
msg.append(camelContext.getName());
statusHandler.handle(Priority.ERROR, msg.toString(), e);
}
}
}
public ClusteredContextManager register(CamelContext context) {
clusteredContextList.add(context);
return this;
}
public int getTimeOutMillis() {
return timeOutMillis;
}
public void setTimeOutMillis(int timeOutMillis) {
this.timeOutMillis = timeOutMillis;
}
}

View file

@ -0,0 +1,144 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.concurrent.ExecutorService;
import org.apache.camel.CamelContext;
import com.raytheon.uf.common.util.SystemUtil;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
/**
* Implementation of {@link IContextStateManager} that handles clustered
* contexts. Extends {@code DependencyContextStateManager} to allow for
* clustered contexts to work with dependencies also.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ClusteredContextStateManager extends DependencyContextStateManager {
/**
* Name field for cluster task.
*/
private static final String taskName = "ClusteredContext";
/**
* Field for extra-info to designate this host.
*/
private final String myName;
/**
* Constructor that takes an {@code ExecutorService}. The
* {@code ExecutorService} is used for starting/stopping dependent contexts.
*
* @param service
*/
public ClusteredContextStateManager(ExecutorService service) {
super(service);
myName = SystemUtil.getHostName() + ":"
+ System.getProperty("edex.run.mode");
}
/**
* Get the {@code ClusterLock} details field.
*
* @param context
* @return
*/
protected static String getLockDetails(CamelContext context) {
return context.getName() + ClusterLockUtils.CLUSTER_SUFFIX;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DependencyContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
boolean canStartContext = super.isContextStartable(context);
/*
* Check cluster lock if we can start the context or if context is
* already started in case we need to update the cluster lock.
*/
if (canStartContext || context.getStatus().isStarted()) {
ClusterTask lock = ClusterLockUtils.lock(taskName,
getLockDetails(context), myName, ContextManager
.getInstance().getTimeOutMillis(), false);
switch (lock.getLockState()) {
case ALREADY_RUNNING:
// check if we already have lock
canStartContext = lock.getExtraInfo().equals(myName);
if (canStartContext) {
// update the lock time
ClusterLockUtils
.updateLockTime(taskName, getLockDetails(context),
System.currentTimeMillis());
}
break;
case SUCCESSFUL:
canStartContext = true;
break;
default:
canStartContext = false;
}
}
return canStartContext;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DependencyContextStateManager#
* stopContext(org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
// on stop, unlock the cluster lock if we own it
String contextName = context.getName()
+ ClusterLockUtils.CLUSTER_SUFFIX;
ClusterTask lock = ClusterLockUtils.lookupLock(taskName, contextName);
if (lock.getExtraInfo().equals(myName) && lock.isRunning()) {
ClusterLockUtils.unlock(taskName, contextName);
}
return super.stopContext(context);
}
}

View file

@ -0,0 +1,222 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.EdexException;
/**
* Contains all known contexts and parsed data about the contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ContextData {
private final List<CamelContext> contexts;
private final Map<String, Route> consumerRouteMapping;
private final Map<String, String> routeIdUriMapping;
/**
* Pulls the direct-vm:name, vm:name, queue:name, topic:name section from
* the endpoint URI.
*/
private static final Pattern endpointUriParsePattern = Pattern
.compile("([^:]+)://([^?]+)");
/**
* Parses passed contexts for route and endpoint data about all contexts.
*
* @param contexts
* @throws ConfigurationException
*/
public ContextData(List<CamelContext> contexts)
throws ConfigurationException {
this.contexts = Collections.unmodifiableList(contexts);
this.consumerRouteMapping = Collections
.unmodifiableMap(generateRouteMappings(this.contexts));
Map<String, String> idUriMapping = new HashMap<String, String>(
consumerRouteMapping.size(), 1);
for (Route route : consumerRouteMapping.values()) {
idUriMapping.put(route.getId(), route.getEndpoint()
.getEndpointUri());
}
this.routeIdUriMapping = Collections.unmodifiableMap(idUriMapping);
}
/**
* Populates an endpointName to {@code Route} mapping for the passed
* {@code CamelContext}s.
*
* @return
* @throws ConfigurationException
*/
protected static Map<String, Route> generateRouteMappings(
List<CamelContext> contexts) throws ConfigurationException {
Map<String, Route> routeMapping = new HashMap<String, Route>(
contexts.size() * 2, 1);
// populate the consumer definitions
for (CamelContext context : contexts) {
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = getEndpointTypeAndName(uri);
if (typeAndName != null) {
String endpointName = typeAndName.getSecond();
Route prev = routeMapping.put(endpointName, route);
if (prev != null) {
throw new ConfigurationException(
"Two contexts listen to the same endpoint name ["
+ endpointName
+ "]. ContextManager cannot handle this situation. Double check configuration. Conflicting contexts ["
+ prev.getRouteContext()
.getCamelContext()
.getName() + "] and ["
+ context.getName() + "]");
}
}
}
}
}
return routeMapping;
}
/**
* Returns the known contexts.
*
* @return
*/
public List<CamelContext> getContexts() {
return contexts;
}
/**
* Parses URI for component type and endpoint name.
*
* @param uri
* @return
*/
public static Pair<String, String> getEndpointTypeAndName(String uri) {
Pair<String, String> rval = null;
Matcher m = endpointUriParsePattern.matcher(uri);
if (m.find()) {
String endpointType = m.group(1);
String endpointName = m.group(2);
rval = new Pair<String, String>(endpointType, endpointName);
}
return rval;
}
/**
* Scans the camel context and associated routes. Groups the routes by
* consumer type.
*
* @return
*/
public Map<String, List<Route>> getContextRoutesByEndpointType()
throws ConfigurationException {
Map<String, List<Route>> routesByType = new HashMap<String, List<Route>>();
for (CamelContext context : contexts) {
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = getEndpointTypeAndName(uri);
String type = typeAndName.getFirst();
List<Route> routesForType = routesByType.get(type);
if (routesForType == null) {
routesForType = new LinkedList<Route>();
routesByType.put(type, routesForType);
}
routesForType.add(route);
}
}
}
return routesByType;
}
/**
* Returns the uri for the consumer endpoint of the route with the specified
* routeId.
*
* @param routeId
* @return
* @throws EdexException
*/
public String getEndpointUriForRouteId(String routeId) throws EdexException {
String uri = routeIdUriMapping.get(routeId);
if (uri == null) {
throw new EdexException("Route id " + routeId
+ " not found. Check loaded spring configurations.");
}
return uri;
}
/**
* Returns the route for the endpoint with the passed name as returned from
* getEndpointTypeAndName().
*
* @param endpointName
* @return
* @throws EdexException
*/
public Route getRouteForEndpointName(String endpointName)
throws EdexException {
Route route = consumerRouteMapping.get(endpointName);
if (route == null) {
throw new EdexException("Endpoint " + endpointName
+ " not found. Check loaded spring configurations.");
}
return route;
}
}

View file

@ -0,0 +1,268 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Route;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
/**
* Contains context dependency mappings.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 26, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ContextDependencyMapping {
/**
* Endpoint types that should be tracked for dependency mapping
*/
protected static final Set<String> DEPENDENCY_ENDPOINT_TYPES;
static {
/*
* Endpoint types that are used for inner context routing. If we add
* other inner jvm routing types, they should be added here.
*/
Set<String> types = new HashSet<String>(8);
types.add("vm");
types.add("direct-vm");
types.add("seda");
types.add("jmx");
types.add("guava-eventbus");
DEPENDENCY_ENDPOINT_TYPES = Collections.unmodifiableSet(types);
}
/**
* The dependency mappings.
*/
protected final Map<CamelContext, DependencyNode> dependencyMapping;
/**
* Populates the dependency mappings for all camel contexts.
* {@code suppressExceptions} can be used to differentiate between
* startup/shutdown conditions to allow the map to be populated regardless
* of detected issues.
*
* @param contextData
* @param suppressExceptions
* @throws ConfigurationException
*/
public ContextDependencyMapping(ContextData contextData,
boolean suppressExceptions) throws ConfigurationException {
dependencyMapping = Collections
.unmodifiableMap(populateDependencyMapping(contextData,
suppressExceptions));
}
/**
* Returns a {@code IUFStatusHandler}. Not cached as rarely used.
*
* @return
*/
private static IUFStatusHandler getHandler() {
return UFStatus.getHandler(ContextDependencyMapping.class);
}
/**
* Dependency mappings per context. The dependency mapping is only for
* internal vm types that have a direct dependency. Indirect dependency via
* a JMS queue for example is not returned/enforced.
*
* @param contextData
* @param suppressExceptions
* Done in a shutdown scenario to get the dependencyMapping as
* close as possible.
*/
protected static Map<CamelContext, DependencyNode> populateDependencyMapping(
ContextData contextData, boolean suppressExceptions)
throws ConfigurationException {
List<CamelContext> contexts = contextData.getContexts();
Map<CamelContext, DependencyNode> dependencyMapping = new LinkedHashMap<CamelContext, DependencyNode>(
contexts.size());
// set up dependency nodes for internal types
Map<String, CamelContext> consumesFrom = new HashMap<String, CamelContext>();
Map<String, List<CamelContext>> producesTo = new HashMap<String, List<CamelContext>>();
Set<String> consumers = new HashSet<String>();
// scan for consuming and producing internal endpoints
for (CamelContext context : contexts) {
dependencyMapping.put(context, new DependencyNode(context));
consumers.clear();
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if ((typeAndName != null)
&& DEPENDENCY_ENDPOINT_TYPES.contains(typeAndName
.getFirst())) {
String endpointName = typeAndName.getSecond();
consumers.add(endpointName);
/*
* Internal types don't support a fanout type policy
* where multiple routes can listen to the same
* endpoint.
*/
CamelContext prev = consumesFrom.put(endpointName,
context);
if (prev != null) {
String msg = "Two contexts listen to the same internal endpoint ["
+ endpointName
+ "]. ContextManager cannot handle this situation. Double check configuration. Conflicting contexts ["
+ prev.getName()
+ "] and ["
+ context.getName() + "]";
if (suppressExceptions) {
getHandler().error(msg);
} else {
throw new ConfigurationException(msg);
}
}
}
}
}
Collection<Endpoint> endpoints = context.getEndpoints();
if ((endpoints != null) && (endpoints.size() > 0)) {
for (Endpoint ep : endpoints) {
String uri = ep.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if ((typeAndName != null)
&& DEPENDENCY_ENDPOINT_TYPES.contains(typeAndName
.getFirst())) {
String endpointName = typeAndName.getSecond();
if (!consumers.contains(endpointName)) {
List<CamelContext> producerCtxs = producesTo
.get(endpointName);
if (producerCtxs == null) {
producerCtxs = new LinkedList<CamelContext>();
producesTo.put(endpointName, producerCtxs);
}
producerCtxs.add(context);
}
}
}
}
}
// setup dependencies for internal routes
for (Map.Entry<String, List<CamelContext>> producersEntry : producesTo
.entrySet()) {
String endpoint = producersEntry.getKey();
CamelContext consumer = consumesFrom.get(endpoint);
List<CamelContext> producers = producersEntry.getValue();
if (consumer == null) {
StringBuilder msg = new StringBuilder(200);
msg.append("Internal Routing Endpoint [")
.append(endpoint)
.append("] has no defined consumers. This is endpoint is used in contexts [");
Iterator<CamelContext> producerIter = producers.iterator();
while (producerIter.hasNext()) {
CamelContext producer = producerIter.next();
msg.append(producer.getName());
if (producerIter.hasNext()) {
msg.append(", ");
}
}
msg.append("]");
if (suppressExceptions) {
getHandler().error(msg.toString());
} else {
throw new ConfigurationException(msg.toString());
}
} else {
DependencyNode consumerNode = dependencyMapping.get(consumer);
for (CamelContext producer : producers) {
DependencyNode producerNode = dependencyMapping
.get(producer);
consumerNode.addDependentNode(producerNode);
}
}
}
return dependencyMapping;
}
/**
* Get the contexts that depend upon the passed context to work. If the
* passed context is unknown null will be returned.
*
* @param context
* @return
*/
public Set<CamelContext> getDependentContexts(CamelContext context) {
DependencyNode dNode = dependencyMapping.get(context);
if (dNode == null) {
return null;
}
return dNode.getDependentContexts();
}
/**
* Get the contexts that the passed context requires to be running to work.
* If the passed context is unknown null will be returned.
*
* @param context
* @return
*/
public Set<CamelContext> getRequiredContexts(CamelContext context) {
DependencyNode dNode = dependencyMapping.get(context);
if (dNode == null) {
return null;
}
return dNode.getRequiredContexts();
}
}

View file

@ -20,77 +20,568 @@
package com.raytheon.uf.edex.esb.camel.context; package com.raytheon.uf.edex.esb.camel.context;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext; import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.IContextStateProcessor;
/** /**
* Dynamically starts/stops a context and its associated routes so that only one * Tracks all contexts and is used to auto determine context dependencies and
* context in the cluster is running. This should mainly be used for reading * start/stop them in the right order. Dynamically starts/stops a clustered
* from topics so that only box is processing the topic data in the cluster for * context and its associated routes so that only one context in the cluster is
* singleton type events. * running. This should mainly be used for reading from topics so that only box
* is processing the topic data in the cluster for singleton type events.
* *
* <pre> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 10, 2010 5050 rjpeter Initial creation * Nov 10, 2010 5050 rjpeter Initial creation.
* May 13, 2013 1989 njensen Camel 2.11 compatibility * May 13, 2013 1989 njensen Camel 2.11 compatibility.
* Mar 11, 2014 2726 rjpeter Implemented graceful shutdown.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
* @version 1.0 * @version 1.0
*/ */
public class ContextManager { public class ContextManager implements ApplicationContextAware,
BeanFactoryPostProcessor {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ContextManager.class); .getHandler(ContextManager.class);
private List<CamelContext> contextList = new ArrayList<CamelContext>();
private static ContextManager instance = new ContextManager(); private static ContextManager instance = new ContextManager();
/**
* Service used for start up and shut down threading.
*/
private final ExecutorService service = Executors.newCachedThreadPool();
private final Set<CamelContext> clusteredContexts = new HashSet<CamelContext>();
/**
* State Manager for all contexts that are not clustered.
*/
private final IContextStateManager defaultStateManager = new DependencyContextStateManager(
service);
/**
* State Manager used for all clustered contexts.
*/
private final IContextStateManager clusteredStateManager = new ClusteredContextStateManager(
service);
/**
* Spring context. Set by the spring container after bean construction.
*/
private ApplicationContext springCtx = null;
/**
* Endpoint types that are internal only. Mainly used at shutdown time to
* designate routes that shouldn't be shutdown immediately.
*/
private final Set<String> internalEndpointTypes = new HashSet<String>();
/**
* Map of context processors that have been registered for a given context.
* Used to allow contexts to do custom worn on startup/shutdown.
*/
private final Map<CamelContext, IContextStateProcessor> contextProcessors = new HashMap<CamelContext, IContextStateProcessor>();
/**
* Cluster lock timeout for clustered contexts.
*/
private int timeOutMillis;
/**
* Parsed context data for all contexts known in the spring container.
*/
private volatile ContextData contextData;
/**
* Flag to control shutting down the jvm. This handles shutdown being called
* during startup to short circuit startup.
*/
private final AtomicBoolean shuttingDown = new AtomicBoolean(false);
/**
* Dependency mappings for all camel contexts in the spring container. This
* should only be changed in a sync block. Otherwise mark as volatile.
*/
private ContextDependencyMapping dependencyMapping = null;
/**
* Last time dependency mapping was generated. Used to periodically
* regenerate the dependency mappings.
*/
private final long lastDependencyTime = 0;
public static ContextManager getInstance() { public static ContextManager getInstance() {
return instance; return instance;
} }
/**
* Private constructor. Sets up internal types for prioritized stopping of
* routes on shutdown.
*/
private ContextManager() { private ContextManager() {
internalEndpointTypes
.addAll(ContextDependencyMapping.DEPENDENCY_ENDPOINT_TYPES);
internalEndpointTypes.add("timer");
internalEndpointTypes.add("quartz");
internalEndpointTypes.add("clusteredquartz");
} }
/**
* Gets the context data.
*
* @return
* @throws ConfigurationException
*/
public ContextData getContextData() throws ConfigurationException {
if (contextData == null) {
synchronized (this) {
if (contextData == null) {
contextData = new ContextData(new ArrayList<CamelContext>(
springCtx.getBeansOfType(CamelContext.class)
.values()));
}
}
}
return contextData;
}
/**
* Get the {@link IContextStateManager} for the passed {@code CamelContext}.
*
* @param context
* @return
*/
protected IContextStateManager getStateManager(CamelContext context) {
if (clusteredContexts.contains(context)) {
return clusteredStateManager;
}
return defaultStateManager;
}
/**
* Get the {@link IContextStateProcessor} for the passed
* {@code CamelContext}.
*
* @param context
* @return
*/
public IContextStateProcessor getStateProcessor(CamelContext context) {
return contextProcessors.get(context);
}
/**
* Get the {@link ContextDependencyMapping} for all contexts.
*
* @param suppressExceptions
* @return
* @throws ConfigurationException
*/
public ContextDependencyMapping getDependencyMapping(
boolean suppressExceptions) throws ConfigurationException {
/*
* This is not permanently cashed and regenerated periodically since
* routing via code can change at runtime.
*/
synchronized (this) {
long millis = System.currentTimeMillis();
if ((dependencyMapping == null)
|| (millis > (lastDependencyTime + TimeUtil.MILLIS_PER_MINUTE))) {
dependencyMapping = new ContextDependencyMapping(
getContextData(), suppressExceptions);
}
}
return dependencyMapping;
}
/**
* Starts all routes for all contexts. If a route fails to start the entire
* jvm will be shutdown.
*/
public void startContexts() { public void startContexts() {
statusHandler.info("Context Manager starting routes"); statusHandler.info("Context Manager starting contexts");
for (CamelContext camelContext : contextList) {
try {
ContextData cxtData = getContextData();
List<Future<Pair<CamelContext, Boolean>>> callbacks = new LinkedList<Future<Pair<CamelContext, Boolean>>>();
for (final CamelContext context : cxtData.getContexts()) {
final IContextStateManager stateManager = getStateManager(context);
if (stateManager.isContextStartable(context)) {
/*
* Have the ExecutorService start the context to allow for
* quicker startup.
*/
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = false;
try {
rval = stateManager
.startContext(context);
if (!rval) {
statusHandler.error("Context ["
+ context.getName()
+ "] failed to start, shutting down");
System.exit(1);
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred starting context: "
+ context
.getName(),
e);
System.exit(1);
}
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
}
}
/*
* Double check call backs that everything started successfully. If
* some did not start successfully, force shutdown.
*/
for (Future<Pair<CamelContext, Boolean>> callback : callbacks) {
Pair<CamelContext, Boolean> val = callback.get();
if (!val.getSecond().booleanValue()) {
statusHandler.error("Context [" + val.getFirst().getName()
+ "] failed to start, shutting down");
System.exit(1);
}
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred starting contexts, shutting down", e);
System.exit(1);
}
}
/**
* Register a clustered context that is meant to run as a singleton in the
* cluster.
*
* @param context
* @return
*/
public ContextManager registerClusteredContext(final CamelContext context) {
clusteredContexts.add(context);
return this;
}
/**
* Register a context state processor to be called on start/stop of the
* context.
*
* @param context
* @param processor
* @return
*/
public ContextManager registerContextStateProcessor(
final CamelContext context, final IContextStateProcessor processor) {
contextProcessors.put(context, processor);
return this;
}
/**
* Stops all contexts. Note this method can only be called once for the life
* of the jvm and will gracefully shut down all of camel.
*/
public void stopContexts() {
/*
* flag to ensure no one else runs shutdown also stops
* checkClusteredContext from starting contexts once shutdown has been
* initiated
*/
if (shuttingDown.compareAndSet(false, true)) {
if (springCtx == null) {
statusHandler
.info("Spring Context not set. Start up never completed, cannot orderly shutdown");
}
statusHandler.info("Context Manager stopping routes");
try { try {
/* /*
* In camel 2.11, all contexts are "started" automatically but * begin immediate shutdown of routes that are not an internal
* the isAutoStartup() flag determines if the routes are * type
* automatically started. The code in DefaultCamelContext is
* safe to call start() on a second time to get the routes
* started.
*
* For more information, see:
* http://camel.465427.n5.nabble.com/Camel
* -context-autostartup-td5721638.html
*
* https://issues.apache.org/jira/browse/CAMEL-5759
*/ */
if (!camelContext.isAutoStartup()) { LinkedList<Route> routesToStop = new LinkedList<Route>();
camelContext.start(); ContextData ctxData = getContextData();
List<CamelContext> contexts = ctxData.getContexts();
List<Future<Pair<CamelContext, Boolean>>> callbacks = new LinkedList<Future<Pair<CamelContext, Boolean>>>();
for (final CamelContext context : contexts) {
/*
* group routes by context due to sync lock at context level
* for stopping a route
*/
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String type = typeAndName.getFirst();
if (!internalEndpointTypes.contains(type)) {
routesToStop.add(route);
} }
}
}
if (routesToStop.size() > 0) {
final IContextStateManager stateMgr = getStateManager(context);
final List<Route> tmp = routesToStop;
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = true;
for (Route route : tmp) {
try {
statusHandler.info("Stopping route ["
+ route.getId()
+ "]");
rval &= stateMgr
.stopRoute(route);
} catch (Exception e) { } catch (Exception e) {
statusHandler.handle(Priority.ERROR, statusHandler.error(
"Failed to start routes for " + camelContext.getName(), "Error occurred closing route: "
+ route.getId(),
e); e);
} }
} }
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
routesToStop = new LinkedList<Route>();
}
} }
public ContextManager register(CamelContext context) { List<CamelContext> failures = waitForCallbacks(callbacks,
contextList.add(context); "Waiting for external routes to shutdown: ", 1000);
return this;
for (CamelContext failure : failures) {
statusHandler.error("Context [" + failure.getName()
+ "] has routes that failed to stop");
}
statusHandler.info("Shutting down contexts");
for (final CamelContext context : contexts) {
final IContextStateManager stateManager = getStateManager(context);
if (stateManager.isContextStoppable(context)) {
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = false;
try {
statusHandler.info("Stopping context ["
+ context.getName()
+ "]");
rval = stateManager
.stopContext(context);
if (!rval) {
statusHandler.error("Context ["
+ context
.getName()
+ "] failed to stop");
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred stopping context: "
+ context
.getName(),
e);
}
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
}
}
failures = waitForCallbacks(callbacks,
"Waiting for contexts to shutdown: ", 1000);
for (CamelContext failure : failures) {
statusHandler.error("Context [" + failure.getName()
+ "] had a failure trying to stop");
}
} catch (Throwable e) {
statusHandler.fatal("Error occurred during shutdown", e);
}
}
}
/**
* Waits for all callbacks to finish printing a periodic message with number
* of remaining callbacks. Returns a list of contexts that had a failure
* status.
*
* @param callbacks
* @param message
* @param sleepInterval
* @return
*/
private static List<CamelContext> waitForCallbacks(
List<Future<Pair<CamelContext, Boolean>>> callbacks,
String message, long sleepInterval) {
statusHandler.info(message + callbacks.size() + " remaining");
List<CamelContext> failures = new LinkedList<CamelContext>();
while (!callbacks.isEmpty()) {
boolean foundOne = false;
Iterator<Future<Pair<CamelContext, Boolean>>> callbackIter = callbacks
.iterator();
while (callbackIter.hasNext()) {
Future<Pair<CamelContext, Boolean>> callback = callbackIter
.next();
if (callback.isDone()) {
foundOne = true;
callbackIter.remove();
try {
Pair<CamelContext, Boolean> val = callback.get();
if (!val.getSecond().booleanValue()) {
failures.add(val.getFirst());
}
} catch (Exception e) {
statusHandler.error("Failure in callback task", e);
}
}
}
if (!foundOne) {
statusHandler.info(message + callbacks.size() + " remaining");
try {
Thread.sleep(sleepInterval);
} catch (Exception e) {
// ignore
}
}
}
return failures;
}
/**
* Checks the clustered contexts. If context is not running in the cluster
* the context will be started.
*/
public void checkClusteredContexts() {
if (!shuttingDown.get()) {
for (CamelContext camelContext : clusteredContexts) {
boolean activateRoute = true;
try {
IContextStateManager stateManager = getStateManager(camelContext);
if (stateManager.isContextStartable(camelContext)) {
stateManager.startContext(camelContext);
} else if (stateManager.isContextStoppable(camelContext)) {
activateRoute = false;
stateManager.stopContext(camelContext);
}
} catch (Exception e) {
StringBuilder msg = new StringBuilder();
msg.append("Failed to ");
if (activateRoute) {
msg.append("start ");
} else {
msg.append("stop ");
}
msg.append("context ");
msg.append(camelContext.getName());
statusHandler.handle(Priority.ERROR, msg.toString(), e);
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
springCtx = context;
}
public int getTimeOutMillis() {
return timeOutMillis;
}
public void setTimeOutMillis(int timeOutMillis) {
this.timeOutMillis = timeOutMillis;
}
public boolean isShuttingDown() {
return shuttingDown.get();
}
/**
* Update all camel beans to have autoStartup to false and handles quart
* workaround when JMX is disabled.
*/
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (CamelContext ctx : beanFactory.getBeansOfType(CamelContext.class)
.values()) {
ctx.setAutoStartup(false);
if ((ctx instanceof DefaultCamelContext)
&& (ctx.getManagementName() == null)) {
((DefaultCamelContext) ctx).setManagementName(ctx.getName());
}
}
} }
} }

View file

@ -0,0 +1,215 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.EnumSet;
import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.ServiceStatus;
import com.raytheon.uf.edex.core.IContextStateProcessor;
/**
* Implementation of IContextStateManager that does basic validation of context
* status as well as handling IContextStateProcessor for startup/shutdown of
* contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DefaultContextStateManager implements IContextStateManager {
private static final Set<ServiceStatus> STARTABLE_STATES = EnumSet.of(
ServiceStatus.Stopped, ServiceStatus.Suspended,
ServiceStatus.Suspending);
private static final Set<ServiceStatus> SUSPENDABLE_STATES = EnumSet.of(
ServiceStatus.Starting, ServiceStatus.Started);
private static final Set<ServiceStatus> STOPPABLE_STATES = EnumSet.of(
ServiceStatus.Starting, ServiceStatus.Started,
ServiceStatus.Suspending, ServiceStatus.Suspended);
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.IContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
return STARTABLE_STATES.contains(status)
|| (status.isStarted() && !context.isAutoStartup());
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#startContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean startContext(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
boolean rval = status.isStarted();
if (rval && !context.isAutoStartup()) {
for (Route route : context.getRoutes()) {
rval &= context.getRouteStatus(route.getId()).isStarted();
}
}
if (!rval) {
IContextStateProcessor processor = ContextManager.getInstance()
.getStateProcessor(context);
if (processor != null) {
processor.preStart();
}
context.start();
rval = context.getStatus().isStarted();
/*
* if a context has autoStartup = false, all of its routes are
* started on the second time context.start is called, adding route
* check for future proofing just in case.
*/
if (!context.isAutoStartup()) {
for (Route route : context.getRoutes()) {
rval &= startRoute(route);
}
/*
* clear the auto start up flag since its an initial condition
* only
*/
context.setAutoStartup(true);
}
if (processor != null) {
processor.postStart();
}
}
return rval;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#startRoute
* (org.apache.camel.Route)
*/
@Override
public boolean startRoute(Route route) throws Exception {
String routeId = route.getId();
CamelContext ctx = route.getRouteContext().getCamelContext();
ServiceStatus status = ctx.getRouteStatus(routeId);
if (STARTABLE_STATES.contains(status)) {
ctx.startRoute(routeId);
status = ctx.getRouteStatus(routeId);
}
return status.isStarted();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.IContextStateManager#
* isContextStoppable (org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStoppable(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
boolean shuttingDown = ContextManager.getInstance().isShuttingDown();
return (shuttingDown && STOPPABLE_STATES.contains(status))
|| (!shuttingDown && SUSPENDABLE_STATES.contains(status));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#stopContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
if (isContextStoppable(context)) {
IContextStateProcessor processor = ContextManager.getInstance()
.getStateProcessor(context);
if (processor != null) {
processor.preStop();
}
// a context will automatically stop all its routes
if (ContextManager.getInstance().isShuttingDown()) {
context.stop();
} else {
context.suspend();
}
if (processor != null) {
processor.postStop();
}
status = context.getStatus();
}
return status.isStopped();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#stopRoute
* (org.apache.camel.Route)
*/
@Override
public boolean stopRoute(Route route) throws Exception {
String routeId = route.getId();
CamelContext ctx = route.getRouteContext().getCamelContext();
ServiceStatus status = ctx.getRouteStatus(routeId);
if (STOPPABLE_STATES.contains(status)) {
ctx.stopRoute(routeId);
status = ctx.getRouteStatus(routeId);
}
return status.isStopped();
}
}

View file

@ -0,0 +1,229 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
/**
* Implementation of IContextStateManager that handles dependencies between
* contexts so that contexts start/stop in the correct order. Can be given an
* ExecutorService to use to start/stop dependent contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DependencyContextStateManager extends DefaultContextStateManager {
/**
* Service to use to start/stop dependent contexts. If null, context
* processing will happen on current thread.
*/
protected final ExecutorService service;
public DependencyContextStateManager() {
this(null);
}
public DependencyContextStateManager(ExecutorService service) {
this.service = service;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
if (!super.isContextStartable(context)) {
return false;
}
Set<CamelContext> requiredContexts = ContextManager.getInstance()
.getDependencyMapping(false).getRequiredContexts(context);
if (requiredContexts != null) {
for (CamelContext rContext : requiredContexts) {
if (!rContext.getStatus().isStarted()) {
return false;
} else {
for (Route rRoute : rContext.getRoutes()) {
if (!rContext.getRouteStatus(rRoute.getId())
.isStarted()) {
return false;
}
}
}
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* startContext(org.apache.camel.CamelContext)
*/
@Override
public boolean startContext(CamelContext context) throws Exception {
boolean rval = super.startContext(context);
ContextManager ctxMgr = ContextManager.getInstance();
if (rval) {
Set<CamelContext> dContexts = ctxMgr.getDependencyMapping(false)
.getDependentContexts(context);
if (dContexts != null) {
List<Future<Boolean>> callbacks = null;
for (final CamelContext dCtx : dContexts) {
final IContextStateManager stateMgr = ctxMgr
.getStateManager(dCtx);
if (stateMgr.isContextStartable(dCtx)) {
if (service != null) {
if (callbacks == null) {
callbacks = new LinkedList<Future<Boolean>>();
}
callbacks.add(service
.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return stateMgr.startContext(dCtx);
}
}));
} else {
stateMgr.startContext(dCtx);
}
}
}
if (callbacks != null) {
for (Future<Boolean> callback : callbacks) {
rval &= callback.get().booleanValue();
}
}
}
}
return rval;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* isContextStoppable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStoppable(CamelContext context) throws Exception {
if (!super.isContextStoppable(context)) {
return false;
}
Set<CamelContext> dContexts = ContextManager.getInstance()
.getDependencyMapping(true).getDependentContexts(context);
if (dContexts != null) {
for (CamelContext dContext : dContexts) {
/*
* only need to check if the context has stopped, can't have a
* stopped context with started routes.
*/
if (!dContext.getStatus().isStopped()) {
return false;
}
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#stopContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
boolean rval = super.stopContext(context);
ContextManager ctxMgr = ContextManager.getInstance();
if (rval) {
Set<CamelContext> rContexts = ctxMgr.getDependencyMapping(true)
.getRequiredContexts(context);
if (rContexts != null) {
List<Future<Boolean>> callbacks = null;
for (final CamelContext rCtx : rContexts) {
final IContextStateManager stateMgr = ctxMgr
.getStateManager(rCtx);
if (stateMgr.isContextStoppable(rCtx)) {
if (service != null) {
if (callbacks == null) {
callbacks = new LinkedList<Future<Boolean>>();
}
callbacks.add(service
.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return stateMgr.stopContext(rCtx);
}
}));
} else {
stateMgr.stopContext(rCtx);
}
}
}
if (callbacks != null) {
for (Future<Boolean> callback : callbacks) {
rval &= callback.get().booleanValue();
}
}
}
}
return rval;
}
}

View file

@ -0,0 +1,145 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.HashSet;
import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Route;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
/**
* Class to map a context to its required and dependent contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DependencyNode {
private final CamelContext context;
/**
* Contexts required by this context.
*/
private final Set<CamelContext> requiredContexs = new HashSet<CamelContext>();
/**
* Contexts that depend on this context.
*/
private final Set<CamelContext> dependentContexts = new HashSet<CamelContext>();
public DependencyNode(CamelContext context) {
this.context = context;
}
/**
* Add a node who is dependent on this node. Applies linking in both
* directions.
*
* @param dNode
*/
public void addDependentNode(DependencyNode dNode) {
if (!requiredContexs.contains(dNode.context)) {
dependentContexts.add(dNode.context);
dNode.requiredContexs.add(context);
} else {
StringBuilder msg = new StringBuilder(300);
msg.append("Circular CamelContext dependency detected between ")
.append(context.getName())
.append(" and ")
.append(dNode.context.getName())
.append(". Removing dependency, startup/shutdown may be incorrect, verify configuration. ");
addRouteData(context, msg);
addRouteData(dNode.context, msg);
UFStatus.getHandler(DependencyNode.class).warn(msg.toString());
}
}
public CamelContext getContext() {
return context;
}
/**
* Get all contexts that this context requires to be running.
*
* @return
*/
public Set<CamelContext> getRequiredContexts() {
return requiredContexs;
}
/**
* Get all contexts that depend on this context to be running.
*
* @return
*/
public Set<CamelContext> getDependentContexts() {
return dependentContexts;
}
/**
* Utility method for printing information about a context.
*
* @param ctx
* @param builder
*/
private static void addRouteData(CamelContext ctx, StringBuilder builder) {
builder.append("Context [").append(ctx.getName())
.append("] consumes from [");
Set<String> consumerEndpoints = new HashSet<String>();
for (Route route : ctx.getRoutes()) {
Endpoint endpoint = route.getEndpoint();
String uri = endpoint.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String name = typeAndName.getFirst() + ":"
+ typeAndName.getSecond();
builder.append(name).append(", ");
consumerEndpoints.add(name);
}
builder.delete(builder.length() - 2, builder.length());
builder.append("] and produces to [");
for (Endpoint endpoint : ctx.getEndpoints()) {
String uri = endpoint.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String name = typeAndName.getFirst() + ":"
+ typeAndName.getSecond();
if (!consumerEndpoints.contains(name)) {
builder.append(name).append(", ");
}
}
builder.delete(builder.length() - 2, builder.length());
builder.append("]. ");
}
}

View file

@ -0,0 +1,96 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
/**
* Represents a way for managing a context for starting and stopping. Allows for
* Context with different purposes to be handled independently of each other.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation.
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public interface IContextStateManager {
/**
* Is the {@code CamelContext} startable?
*
* @param context
* @return
* @throws Exception
*/
public boolean isContextStartable(CamelContext context) throws Exception;
/**
* Start the {@code CamelContext}.
*
* @param context
* @return
* @throws Exception
*/
public boolean startContext(CamelContext context) throws Exception;
/**
* Start the {@code Route}.
*
* @param context
* @return
* @throws Exception
*/
public boolean startRoute(Route route) throws Exception;
/**
* Is the {@code CamelContext} stoppable?
*
* @param context
* @return
* @throws Exception
*/
public boolean isContextStoppable(CamelContext context) throws Exception;
/**
* Stop the {@code CamelContext}.
*
* @param context
* @return
* @throws Exception
*/
public boolean stopContext(CamelContext context) throws Exception;
/**
* Stop the {@code Route}.
*
* @param context
* @return
* @throws Exception
*/
public boolean stopRoute(Route route) throws Exception;
}

View file

@ -1,100 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.camel.Endpoint;
import org.apache.camel.component.direct.DirectComponent;
import org.apache.camel.impl.DefaultConsumer;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.util.ServiceHelper;
/**
* Provides a cross-context synchronous component.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 18, 2008 chammack Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Don't stop all consumer in doStop.
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author chammack
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@SuppressWarnings("unchecked")
@Deprecated
public class DirectVMComponent extends DirectComponent {
private static Map<String, CopyOnWriteArrayList<DefaultConsumer>> CONSUMERS = new HashMap<String, CopyOnWriteArrayList<DefaultConsumer>>();
@Override
protected Endpoint createEndpoint(String uri, String remaining,
Map parameters) throws Exception {
synchronized (CONSUMERS) {
CopyOnWriteArrayList<DefaultConsumer> consumers = CONSUMERS
.get(uri);
if (consumers == null) {
consumers = new CopyOnWriteArrayList<DefaultConsumer>();
CONSUMERS.put(uri, consumers);
}
Endpoint endpoint = new DirectVMEndpoint(uri, this, consumers);
setProperties(endpoint, parameters);
return endpoint;
}
}
@Override
protected void doStop() throws Exception {
Collection<CopyOnWriteArrayList<DefaultConsumer>> set = CONSUMERS
.values();
/*
* Stop only the consumers created through this instance of the
* component.
*/
for (CopyOnWriteArrayList<DefaultConsumer> consumerList : set)
for (DefaultConsumer consumer : consumerList) {
Endpoint endpoint = consumer.getEndpoint();
if (endpoint instanceof DefaultEndpoint)
if (((DefaultEndpoint) endpoint).getComponent() == this)
ServiceHelper.stopService(consumer);
}
super.doStop();
}
}

View file

@ -1,102 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.camel.Consumer;
import org.apache.camel.Producer;
import org.apache.camel.component.direct.DirectEndpoint;
import org.apache.camel.impl.DefaultConsumer;
/**
*
* Provides a cross-context synchronous component.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 18, 2008 chammack Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Override correct methods
* May 09, 2013 1989 njensen Camel 2.11 compatibility
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author chammack
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@Deprecated
public class DirectVMEndpoint extends DirectEndpoint {
private boolean allowMultipleConsumers = true;
private CopyOnWriteArrayList<DefaultConsumer> consumers = new CopyOnWriteArrayList<DefaultConsumer>();
public DirectVMEndpoint(String uri, DirectVMComponent component) {
super(uri, component);
}
public DirectVMEndpoint(String uri, DirectVMComponent component,
CopyOnWriteArrayList<DefaultConsumer> consumers) {
super(uri, component);
this.consumers = consumers;
}
@Override
public Producer createProducer() throws Exception {
return new DirectVMProducer(this);
}
@Override
public Consumer createConsumer(org.apache.camel.Processor processor)
throws Exception {
return new DefaultConsumer(this, processor) {
@Override
protected void doStart() throws Exception {
if (!allowMultipleConsumers && !consumers.isEmpty()) {
throw new IllegalStateException(
"Endpoint "
+ getEndpointUri()
+ " only allows 1 active consumer but you attempted to start a 2nd consumer.");
}
consumers.add(this);
super.doStart();
}
@Override
protected void doStop() throws Exception {
super.doStop();
consumers.remove(this);
}
};
}
public List<DefaultConsumer> getConsumers() {
return consumers;
}
}

View file

@ -1,111 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.List;
import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelExchangeException;
import org.apache.camel.Exchange;
import org.apache.camel.component.direct.DirectProducer;
import org.apache.camel.impl.DefaultConsumer;
import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
import org.apache.camel.util.AsyncProcessorHelper;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Direct VM Producer used with DirectVMConsumer.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 27, 2010 mschenke Initial creation
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author mschenke
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@Deprecated
public class DirectVMProducer extends DirectProducer {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(DirectVMProducer.class);
private DirectVMEndpoint endpoint;
/**
* @param endpoint
*/
public DirectVMProducer(DirectVMEndpoint endpoint) {
super(endpoint);
this.endpoint = endpoint;
}
public void process(Exchange exchange) throws Exception {
List<DefaultConsumer> consumers = endpoint.getConsumers();
if (consumers == null || consumers.size() == 0) {
statusHandler.handle(Priority.PROBLEM,
"No consumers available on endpoint: " + endpoint
+ " to process: " + exchange);
throw new CamelExchangeException(
"No consumers available on endpoint: " + endpoint, exchange);
} else {
for (DefaultConsumer consumer : consumers) {
consumer.getProcessor().process(exchange);
}
}
}
public boolean process(Exchange exchange, AsyncCallback callback) {
List<DefaultConsumer> consumers = endpoint.getConsumers();
if (consumers == null || consumers.size() == 0) {
statusHandler.handle(Priority.PROBLEM,
"No consumers available on endpoint: " + endpoint
+ " to process: " + exchange);
// indicate its done synchronously
exchange.setException(new CamelExchangeException(
"No consumers available on endpoint: " + endpoint, exchange));
callback.done(true);
return true;
} else {
boolean sync = true;
for (DefaultConsumer consumer : consumers) {
AsyncProcessor processor = AsyncProcessorTypeConverter
.convert(consumer.getProcessor());
sync &= AsyncProcessorHelper.process(processor, exchange,
callback);
}
return sync;
}
}
}

View file

@ -86,7 +86,6 @@ public class DedicatedThreadJmsComponent extends JmsComponent {
executor.setMaxPoolSize(Math.max(jmsE.getConcurrentConsumers(), executor.setMaxPoolSize(Math.max(jmsE.getConcurrentConsumers(),
jmsE.getMaxConcurrentConsumers())); jmsE.getMaxConcurrentConsumers()));
executor.setQueueCapacity(0); executor.setQueueCapacity(0);
executor.afterPropertiesSet();
jmsE.setTaskExecutor(executor); jmsE.setTaskExecutor(executor);
jmsE.setMessageListenerContainerFactory(MonitoredDefaultMessageListenerContainerFactory jmsE.setMessageListenerContainerFactory(MonitoredDefaultMessageListenerContainerFactory

View file

@ -19,6 +19,8 @@
**/ **/
package com.raytheon.uf.edex.esb.camel.spring; package com.raytheon.uf.edex.esb.camel.spring;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/** /**
@ -32,7 +34,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 15, 2010 rjpeter Initial creation * Nov 15, 2010 rjpeter Initial creation
* * Apr 10, 2014 2726 rjpeter Updated to create/initialize the ThreadPoolExecutor on demand.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
@ -40,6 +42,25 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
*/ */
public class JmsThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { public class JmsThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final long serialVersionUID = 1L;
private volatile boolean needToInitialize = true;
@Override
public ThreadPoolExecutor getThreadPoolExecutor()
throws IllegalStateException {
// don't initialize until first needed
if (needToInitialize) {
synchronized (this) {
if (needToInitialize) {
afterPropertiesSet();
needToInitialize = false;
}
}
}
return super.getThreadPoolExecutor();
}
@Override @Override
public boolean prefersShortLivedTasks() { public boolean prefersShortLivedTasks() {
return false; return false;

View file

@ -12,9 +12,9 @@
<bean id="pluginNotifier" class="com.raytheon.uf.edex.ingest.notification.PluginNotifier"/> <bean id="pluginNotifier" class="com.raytheon.uf.edex.ingest.notification.PluginNotifier"/>
<bean id="persistCamelRegistered" factory-bean="contextManager" <bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
factory-method="register">
<constructor-arg ref="persist-camel"/> <constructor-arg ref="persist-camel"/>
<constructor-arg ref="pluginNotifier"/>
</bean> </bean>
<camelContext id="persist-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> <camelContext id="persist-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">

View file

@ -1,7 +1,6 @@
<beans <beans
xmlns="http://www.springframework.org/schema/beans" xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="index" class="com.raytheon.uf.edex.ingest.IndexSrv"/> <bean id="index" class="com.raytheon.uf.edex.ingest.IndexSrv"/>

View file

@ -49,6 +49,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.ITimer; import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.core.IContextStateProcessor;
import com.raytheon.uf.edex.ingest.notification.PluginNotifierConfig.EndpointType; import com.raytheon.uf.edex.ingest.notification.PluginNotifierConfig.EndpointType;
import com.raytheon.uf.edex.ingest.notification.PluginNotifierConfig.NotifyFormat; import com.raytheon.uf.edex.ingest.notification.PluginNotifierConfig.NotifyFormat;
import com.raytheon.uf.edex.ingest.notification.router.DataUriRouter; import com.raytheon.uf.edex.ingest.notification.router.DataUriRouter;
@ -70,13 +71,14 @@ import com.raytheon.uf.edex.ingest.notification.router.PdoRouter;
* Jun 13, 2013 mnash Initial creation. * Jun 13, 2013 mnash Initial creation.
* Nov 19, 2013 2170 rjpeter Add plugin contributed config files, filtering, * Nov 19, 2013 2170 rjpeter Add plugin contributed config files, filtering,
* and support for pdo vs datauri. * and support for pdo vs datauri.
* Mar 19, 2014 2726 rjpeter Added graceful shutdown support.
* </pre> * </pre>
* *
* @author mnash * @author mnash
* @version 1.0 * @version 1.0
*/ */
public class PluginNotifier { public class PluginNotifier implements IContextStateProcessor {
private static final IUFStatusHandler theHandler = UFStatus private static final IUFStatusHandler theHandler = UFStatus
.getHandler(PluginNotifier.class); .getHandler(PluginNotifier.class);
@ -153,9 +155,6 @@ public class PluginNotifier {
"Error occurred accessing file: " + lf, e); "Error occurred accessing file: " + lf, e);
} }
} }
rebuildTree();
} }
/** /**
@ -419,4 +418,24 @@ public class PluginNotifier {
} }
} }
} }
@Override
public void preStart() {
rebuildTree();
}
@Override
public void postStart() {
}
@Override
public void preStop() {
}
@Override
public void postStop() {
sendQueuedNotifications();
}
} }

View file

@ -19,14 +19,9 @@
<property name="sessionFactory" ref="hmdbSessionFactory" /> <property name="sessionFactory" ref="hmdbSessionFactory" />
</bean> </bean>
<bean id="metarToHMDBCamelRegistered" factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="metarToHMDB-camel"/>
</bean>
<camelContext id="metarToHMDB-camel" <camelContext id="metarToHMDB-camel"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<endpoint id="metarToHMDBEndpoint" /> <endpoint id="metarToHMDBEndpoint" />
<route id="metarToHMDBRoute"> <route id="metarToHMDBRoute">

View file

@ -5,7 +5,7 @@
<camelContext id="clusteredNdmProc" <camelContext id="clusteredNdmProc"
xmlns="http://camel.apache.org/schema/spring" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false"> errorHandlerRef="errorHandler">
<endpoint id="ndmFileEndpoint" <endpoint id="ndmFileEndpoint"
uri="file:${edex.home}/data/ndm?delete=true&amp;delay=5000&amp;maxMessagesPerPoll=1000&amp;exclusiveReadLockStrategy=#ndmFileChangedStrategy" /> uri="file:${edex.home}/data/ndm?delete=true&amp;delay=5000&amp;maxMessagesPerPoll=1000&amp;exclusiveReadLockStrategy=#ndmFileChangedStrategy" />
@ -15,12 +15,10 @@
</route> </route>
</camelContext> </camelContext>
<bean factory-bean="clusteredCamelContextMgr" <bean factory-bean="contextManager" factory-method="registerClusteredContext">
factory-method="register"> <constructor-arg ref="clusteredNdmProc"/>
<constructor-arg ref="clusteredNdmProc" />
</bean> </bean>
<bean id="ndmProc" class="com.raytheon.uf.edex.ndm.ingest.NationalDatasetIngester"/> <bean id="ndmProc" class="com.raytheon.uf.edex.ndm.ingest.NationalDatasetIngester"/>
<bean id="ndmFileChangedStrategy" class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy"/> <bean id="ndmFileChangedStrategy" class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy"/>
</beans> </beans>

Some files were not shown because too many files have changed in this diff Show more