how to control quartz scheduler from running using spring & weblogic deployment plan - spring

i have a quartz scheduler configured with spring, it has five triggers
that trigger appropriate jobs. what i am looking for is to have flag
that i can use to disable the jobs in dev and test environments and
enable in production. below is configuration in my
applicationContext.xml for quartz Scheduler.
<!-- ====================================================================== -->
<!-- ========================== QUARTZ SCHEDULER ========================== -->
<!-- ====================================================================== -->
<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="autoStartup" value="false" />
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="overwriteExistingJobs" value="true"/>
<property name="waitForJobsToCompleteOnShutdown" value="true"/>
<property name="triggers">
<list>
<!-- if you remove a trigger, make sure you
also remove the trigger
from the QRTZ_TRIGGERS table.
-->
<ref bean="Trigger1" />
<ref bean="Trigger2" />
<ref bean="Trigger3" />
<ref bean="Trigger4"/>
<ref bean="Trigger5"/>
</list>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">ClusteredScheduler</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate</prop>
<prop key="org.quartz.jobStore.tablePrefix">qrtz_</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<!-- Set to 7 to correspond to the 7 nightly jobs that run in the morning -->
<prop key="org.quartz.threadPool.threadCount">7</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
</props>
</property>
</bean>
Cron Trigger :
<bean id="Trigger1" class="org.springframework.scheduling.quartz.CronTriggerBean" scope="prototype">
<property name="jobDetail">
<bean name="nightlyJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="My custom class that extends QuartzJobBean"/>
<property name="group" value="nightly"/>
<property name="requestsRecovery" value="true" />
</bean>
</property>
<!-- Cron expression to run job every 10 minutes for testing -->
<!-- <property name="cronExpression" value="0 0/10 * * * ?"/> -->
<!-- Cron expression that runs at 2:10AM -->
<property name="cronExpression" value="0 10 2 * * ?"/>
</bean>
What i tried : I tried setting the cron expression to feb31, so that
it will never run, but that requires a code change or a script to be
run in the database.
What i need : need a flag in my weblogic deployment plan that will turn on or off quartz scheduler

If you need to prevent all jobs from firing, cannot you just leave the scheduler in a stopped state on configured environments (i.e use autoStartup=false on dev/test and autoStartup=true on prod)? It is not actually clear to me how you start your scheduler on prod, because you already seem to have autoStart=false.
If the above is a no go, you have several options:
Separate (partial) Spring contexts with the schedulerBean for individual environments. Contexts for dev/test would contain empty job/trigger lists. Then you can use Spring profiles to pick the applicable context based on whatever condition you can think of (e.g. a domain suffix if you use .devel/.test/*.prod, some config value, JVM sys property etc.)
Implement SchedulerListener and make its schedulerStarted method pause the entire scheduler, or pause all job groups on dev/test.
Implement a TriggerListener and make its vetoJobExecution always return true for dev/test and false for prod.
BTW: If you want a visual tool to help you with pausing/unpausing schedulers, jobs and triggers etc., check out QuartzDesk. Disclaimer: I am the principal developer of this tool.

Related

Configuring auto_escape in freemarker spring-mvc Application

I am using spring-mvc with freemarker-2.3.27-incubating.jar.
And bean configuration for view-resolver like below...
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/"/>
<property name="freemarkerSettings">
<props>
<prop key="template_exception_handler">rethrow</prop>
<prop key="number_format">0.########</prop>
<prop key="date_format">dd/MM/yyyy</prop>
</props>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="suffix" value=".ftl"/>
<property name="exposeSpringMacroHelpers" value="true"/>
<property name="exposeRequestAttributes" value="true"/>
<property name="exposeSessionAttributes" value="true"/>
<property name="requestContextAttribute" value="rc"/>
</bean>
Where and how can I use <#ftl output_format="HTML"> or <#ftl output_format="HTML" auto_esc=true> to enable HTML auto-scape ?
The #ftl tags you just add at the beginning of the template files themselves. But I would recommend setting recognize_standard_file_extensions to true in the freemarkerSettings properties, and then use .ftlh file extension instead of .ftl. Or, even better, you set incompatible_improvements to 2.3.27 there instead, which enables recognize_standard_file_extensions and some fixes. (Last not least, in case you want this for .ftl for some reason, you can set output_format to HTMLOutputFormat in freemarkerSettings properties too.)

Spring and H2 or Derby - Multiple Transactions

I have a project that uses Spring. In local environment I use Derby (with Jetty) that gives me the perfomance that I need in this environemnt (in production is used Oracle and Weblogic).
The problem is that I need new transactions in some specific operations. This specific operations use the annotation #Transactional(propagation=REQUIRES_NEW).
The problem is that with Derby when comes the time that a new transaction was supposed to be createad, the operation hangs and due time out. I tried to use H2 but in the same moment of creation of the new transaction, the database is restarted, meaning, the tables are dropped and are created again.
Derby and H2 don't support multiple transactions? I can't find anything that tells me the opposite.
My database configuration is:
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
<property name="persistenceUnitName" value="ORACLE_PU"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.DerbyPlatform"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="shared-cache-mode">NONE</prop>
<prop key="eclipselink.cache.shared.default">false</prop>
<prop key="eclipselink.query-results-cache">false</prop>
<prop key="eclipselink.weaving">false</prop>
<prop key="eclipselink.ddl-generation">${oracle.eclipselink.ddl.generation}</prop>
<prop key="eclipselink.ddl-generation.output-mode">database</prop>
<prop key="eclipselink.create-ddl-jdbc-file-name">create-tables.sql</prop>
<prop key="eclipselink.drop-ddl-jdbc-file-name">drop-tables.sql</prop>
<prop key="eclipselink.application-location">target/generated-sources/database</prop>
<prop key="eclipselink.jdbc.cache-statements">true</prop>
<prop key="eclipselink.custom.sql.import.file">${oracle.eclipselink.custom.sql.import.file}</prop>
...
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManager"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="url" value="jdbc:derby:target/memory;create=true"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</bean>
My attempt with H2 is similar but with the proper configurations. In weblogic environemnt everything works as expected.
What I'm missing?
It seems you are using derby in embedded in-memory mode. AFAIK, both derby and H2 support concurrent transactions only in standalone mode, when you connect through a TCP connection, but not in embedded mode. Try running derby as a seperate procese and change your database to connect to it.

the count sessionFactory.getStatistics().getTransactionCount() is 0

This question is to improve my understanding of how the transactions are managed within the sessions in spring hibernate. When I print getSessionFactory()getStatistics().getTransactionCount() , it prints '0' when getSessionFactory().getCurrentSession().getTransaction().isActive() is 'true'. I am really confused. Kindly clear the same for me .
Following is the piece of code in which I want the transaction to happen:
#Transactional(propagation=Propagation.REQUIRED)
public int insertNewRecord(){
System.out.println(getSessionFactory().getCurrentSession().getTransaction().isActive());//gives `true`
System.out.println(getSessionFactory().getCurrentSession().getStatistics()); //Gives statistics
System.out.println(getSessionFactory().getStatistics().getSessionOpenCount());// Gives 1
System.out.println(getSessionFactory().getStatistics().getTransactionCount());// Gives 0
}
My spring and Hibernate configuration:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingLocations">
<list><value>classpath:Employee.hbm.xml</value></list>
</property>
<property name="hibernateProperties">
<props>
<!-- SQL dialect -->
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<!-- Enable Hibernate's current session context -->
<!-- <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop> --><!-- org.hibernate.context.internal.ThreadLocalSessionContext -->
<!-- Disable the second-level cache -->
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<!-- Echo all executed SQL to stdout -->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
Below is the transaction manager:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Well, you might want to try executing that code a few times, since the getTransactionCount() method is documented as:
The number of transactions we know to have completed
So if you started with zero, but then you take a count in the middle of a transaction, the transaction has not completed yet, so the count would still be zero.
You might also want to add a call to isStatisticsEnabled() and print the result, just to double-check that stats are enabled.

Spring,Quartz and JobStoreTX

By using CronTriggerBean i have created two triggers(say trigger A & B) for invoking two different action. We have placed our project as .war in 2 servers.I am using JobStoreTX for clustering. The problem i am facing is that i want to cluster only one trigger i.e A and trigger B should not be clustered. Is there a way to specify through code which trigger has to be clustered. My code goes on as below.
<bean id="shedulerJobStoreTX" class="org.quartz.impl.jdbcjobstore.JobStoreTX>
<property name="driverDelegateClass" value="org.quartz.impl. jdbcjobstore.oracle.OracleDelegate">
<property name="dataSource" value ="jndiDS"/>
<property name="tablePrefix" value="someschemaName"/>
<property name="isClustered" value="true"/>
<property name="clusterCheckinInterval" value="${someValue}"/>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
<ref bean="clusterCronTrigger"/>
</list>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runAppJob" />
<property name="cronExpression" value="${someTimeValue1}"/>
</bean>
<bean id="clusterCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runClusterJob" />
<property name="cronExpression" value="${someTimeValue2}"/>
</bean>
Hi, I have refined the code and the above said issue is not happening.PFB the code for the same.
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
<ref bean="clusterCronTrigger"/>
</list>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.jobStore.isClustered">false</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key ="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.
JobStoreTX </prop>
<prop key="org.quartz.jobStore.tablePrefix">schemaName</prop>
<prop key="org.quartz.jobStore.driverDelegateClass"> org.quartz.impl.jdbcjobstore.oracle.OracleDelegate</prop>
<prop key="org.quartz.jobStore.selectWithLockSQL"> SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME= ?</prop>
</props>
</property>
<property name="dataSource" ref="fsmJndiDataSource"/>
But the problem on executing the above code is that i am getting the below exception when the quartz is trying to get the lock ..."Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist"
you need to create required quartz tables in database before you run scheduler.
default quartz tables sql script is available at \docs\dbTables..
example if you are using quartz 2.2.1 distribution (quartz-2.2.1-distribution.tar\quartz-2.2.1\docs\dbTables\tables_oracle)
execute the sql script on database and make sure you see the tables created in it refer below image
Due to the message "ORA-00942: table or view does not exist", I think the table "schemaNameLOCKS" is missing. Indeed, from the doc:
org.quartz.jobStore.selectWithLockSQL
Must be a SQL string that selects a row in the "LOCKS" table and
places a lock on the row. If not set, the default is "SELECT * FROM
{0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE", which
works for most databases. The "{0}" is replaced during run-time with
the TABLE_PREFIX that you configured above. The "{1}" is replaced with
the scheduler's name.

Spring PropertyPlaceholderConfigurer Default Properties Not Read

I am trying to embed activemq broker in a Tomcat. The code base will be deployed in different environments. I want to externalize some parameters, but want to provide default values for those parameters in case the deployed environment does not provide values for place holders.
This is what I have :
<property name="properties">
<props>
<prop key="embed.broker.networkConnectorURI">static:(failover:(tcp://server01:61616,tcp://server02:61616))
</prop>
<prop key="embed.broker.transportConnectorURI">vm://localhost:61616</prop>
</props>
</property>
<bean id="broker" class="org.apache.activemq.broker.BrokerService"
init-method="start" destroy-method="stop">
<property name="networkConnectorURIs">
<list>
<ref >${embed.broker.networkConnectorURI}</ref>
</list>
</property>
<property name="transportConnectorURIs">
<list>
<value>${embed.broker.transportConnectorURI}</value>
</list>
</property>
<property name="brokerName" value="embed-broker" />
</bean>
When I deploy this in an environment where the place holders are missing, Tomcat throws "Could not resolve placeholder 'embed.broker.networkConnectorURI' " error. In other words, the default values are not being picked up.
Any help would be appreciated.
To have some default values, go on this way:
<bean id="myServer" class="com.gordondickens.myapp.MyServerConfig">
<property name="serverName" value="${server.name?localhost}" />
<property name="serverPort" value="${server.port?25}" />
</bean>
Use a PropertyOverrideConfigurer instead of a PropertyPlaceholderConfigurer. That way your defaults specified in the context file will be used if no overriding property file entries are found.

Resources