I have a simple application that uses Spring 3 for dependency injection. I have a JFrame for the user to look at and some background tasks for synchronizing with a back-end server and local database maintenance.
This is the relevant part of my application context:
<task:scheduler id="scheduler" pool-size="1"/>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="synchronizer" method="incrementalSync" fixed-delay="600000"/>
... more tasks ...
</task:scheduled-tasks>
<bean id="mainFrame" class="nl.gdries.myapp.client.ui.MainFrame">
... properties and such ...
</bean>
When I start this applicationContext the scheduler immediately starts executing the background tasks even while my UI is loading. Because the first task is a rather heavy one at the start I want it to wait for the UI to fully load and display before it starts execution.
Does anyone know how to tell Spring to delay executing the scheduled tasks until a moment of my choosing?
This seems to have been left out of the <task:scheduled> bean definition, something I only just noticed last week.
Remember, though, that the <task:...> definitions are just shortcuts, you can always use the explicit approach, by defining a ScheduledExecutorFactoryBean, with nested ScheduledExecutorTask beans. This gives you much finer control, including initialDelay.
I've had the same problem and came back to TimerTask as it is in 25.7.1 point in http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html
<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!-- wait 25 seconds before starting repeated execution -->
<property name="delay" value="25000" />
<!-- run every 50 seconds -->
<property name="period" value="50000" />
<property name="timerTask" ref="task" />
</bean>
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask" />
</list>
</property>
</bean>
I hope in Spring 3.1 will be initialDelay attribute in <task:scheduled>, since in Spring 3.0 TimerFactoryBean is Deprecated.
You can vote for this issue: jira.springframework.org/browse/SPR-7022
This has been introduced by the way in spring 3.2 so if you use the 3.2 schema it's available again -- e.g.:
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
....
the above allows you to do this:
<task:scheduler id="scheduler" pool-size="1"/>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="synchronizer" method="incrementalSync" fixed-delay="600000" initial-delay="initial delay needed for the app to start"/>
... more tasks ...
</task:scheduled-tasks>
Related
I am new to the CAS setup, started using CAS 4.2.x version. With help of the below , doing the setup.
[https://apereo.github.io/cas/4.2.x/installation/LDAP-Authentication.html][1]
After adding bean reference "http://www.ldaptive.org/schema/spring-ext" in the deployerConfigcontext.xml, getting the error
Configuration problem: Unable to locate Spring Namespace handler for xml schema namespace [http://www.ldaptive.org/schema/spring-ext]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ldaptive="http://www.ldaptive.org/schema/spring-ext"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.ldaptive.org/schema/spring-ext http://www.ldaptive.org/schema/spring-ext.xsd">
I am using CAS 3.5.2 and was facing the same issue ..... the below workaround worked for me. You can give it a shot and see if it works for you as well.
Add the following dependency in your pom.xml file
<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-support-ldap</artifactId>
<version>${cas.version}</version>
</dependency>
then remove the below lines from your deployerConfigcontext.xml
xmlns:ldaptive="http://www.ldaptive.org/schema/spring-ext"
http://www.ldaptive.org/schema/spring-ext http://www.ldaptive.org/schema/spring-ext.xsd
In your deployerConfigcontext.xml remove the ldaptive declaration and replace it with the below format.
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<!-- DO NOT enable JNDI pooling for context sources that perform LDAP bind operations. -->
<property name="pooled" value="false"/>
<!--
Although multiple URLs may defined, it's strongly recommended to avoid this configuration
since the implementation attempts hosts in sequence and requires a connection timeout
prior to attempting the next host, which incurs unacceptable latency on node failure.
A proper HA setup for LDAP directories should use a single virtual host that maps to multiple
real hosts using a hardware load balancer.
-->
<property name="url" value="your-ldap-url" />
<!--
Manager credentials are only required if your directory does not support anonymous searches.
Never provide these credentials for FastBindLdapAuthenticationHandler since the user's
credentials are used for the bind operation.
-->
<property name="userDn" value="your-userDn-info"/>
<property name="password" value="password-for-your-userDn"/>
<!-- Place JNDI environment properties here. -->
<property name="baseEnvironmentProperties">
<map>
<!-- Three seconds is an eternity to users. -->
<entry key="com.sun.jndi.ldap.connect.timeout" value="3000" />
<entry key="com.sun.jndi.ldap.read.timeout" value="3000" />
<!-- Explained at http://docs.oracle.com/javase/jndi/tutorial/ldap/security/auth.html -->
<entry key="java.naming.security.authentication" value="simple" />
</map>
</property>
</bean>
Also in your deployerConfigcontext.xml remove your ldapAuthenticationHandler bean and replace it with the following
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"
p:filter="your-ldap-filter"
p:searchBase="your-search-base"
p:contextSource-ref="contextSource"
p:ignorePartialResultException="true" />
Please note that i am using CAS 3.5.2 so you might have to make some more changes ...
I have seen various thread on timertask issues. However I would like some clarification on the inner working on spring Scheduler APIs (3.1).
I have a requirement to kick off a timer every 10 secs. The application runs in clustered websphere zos. (atleast 4 jvm nodes).
Here is the wiring.
<bean id="dataProcessSchedulerTask" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject" ref="ondataTransferTimerWakeupService" />
<property name="targetMethod" value="processDataFeedMetadata" />
</bean>
<bean id="DATA_PROCESS_TIMER"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="DATAProcessSchedulerTask" />
<property name="delay" value="#{systemProperties.DATA_PROCESS_TIMER}" />
<property name="period" value="#{systemProperties.DATA_PROCESS_TIMER}" />
</bean>
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
list>
<ref bean="DATA_PROCESS_TIMER" />
</list>
</property>
</bean>
<bean id="onDATATransferTimerWakeupService" class="com.serviceimpl.OnDATATransferTimerWakeupService" />
I have defined (#async) for processDataFeedMetadata method.
The problem I am seeing the timer which fires every 10 secs correctly to begin with (4 jvms - 24 timer occurrences every min), started misbehaving after few hours (2 or 3 jvms stop firing any timer at all - 6 to 12 timer occurrences every min). I understand timertask implementation has it's own limitation. However, if I invoke an ASYNC method from MethodInvokingTimerTaskFactoryBean, Why would the timertask misbehave as
(1) timer should complete well within the interval as soon as it invokes ASYNC method.
(2) I don't see any exception from app logs and MethodInvokingTimerTaskFactoryBean should have handled and consume any exception if there are any.
Really appreciate if anyone has input on what is going on here ?
I suggest you utilizing Quartz Scheduler for Spring Scheduler implementation
http://quartz-scheduler.org/
Do you have this problem with 1 jvm ?
I have three different .properties files in a Spring Batch project, and I'm trying to set which .properties file should be used as a JobParameter. I'd like to be able to run the job like so:
java CommandLineJobRunner context.xml jobName region=us
The region should specify which .properties file should be used. The problem is getting the context to recognize the JobParameter. I've tried the following to no avail:
<context:property-placeholder location="classpath:batch.#{jobParameters['region']}.properties"/>
And also:
<util:properties id="batchProperties" location="classpath:batch.#{jobParameters['region']}.properties"></util:properties>
I had heard that adding scope="step" could fix similar issues, but I tried adding that to both of the above solutions and still had exceptions.
I think I'm missing a fundamental idea of why I can't get this working, but I'm unable to figure out what that idea is.
If anyone has any suggestions on getting this working and/or explaining why my previous approaches failed, I'd appreciate it.
This is not the right way to proceed (it is impossible do what you are trying to do).
You have to think that jobParameters is available only when a job is running and only for its composing steps marked with scope="step" (and not <context:property-placeholder> nor <util:properties> has a step attribute).
A way for solving the problem is to load properties file in job's execution context before first step is running with a listener:
public class PropertyLoaderJobExecutionListener extends StepExecutionListenerSupport {
Properties countryProperties;
public void setCountryProperties(Properties pfb) {
this.countryProperties = pfb;
}
#Override
public void beforeStep(StepExecution stepExecution) {
super.beforeStep(stepExecution);
// Store property file content in jobExecutionContext with name "batchProperties"
stepExecution.getJobExecution().getExecutionContext().put("batchProperties", countryProperties);
}
}
in your job.xml
<bean id="loadPropertiesListener" class="PropertyLoaderJobExecutionListener" scope="step">
<property name="pfb">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:batch.#{jobParameters['region']}.properties" />
</bean>
</property>
</bean>
and register this listener in your first step (you can't do that in your JobExectionListsner.beforeJob() because there isn't a scope="job" for now and late-binding of #{jobParameters['region']} value is not available).
To access your data with spEL use this syntax:
#{jobExecutionContext.get('batchProperties').getProperty('language')}
or a better syntax to access properties (IDK spEL so good, sorry).
Hope to be clear and can help to solve your problem.
EDIT (full code of my working job.xml):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-util-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<job id="sourceJob" xmlns="http://www.springframework.org/schema/batch">
<step id="step1">
<tasklet ref="getRemoteFileTasklet" />
<listeners>
<listener ref="loadPropertiesListener" />
</listeners>
</step>
</job>
<bean id="loadPropertiesListener" class="PropertyLoaderJobExecutionListener" scope="step">
<property name="pfb">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:batch.#{jobParameters['region']}.properties" />
</bean>
</property>
</bean>
<bean id="getRemoteFileTasklet" class="GetRemoteFileTasklet" />
I am attempting to use Apache Shiro with Spring and MongoDB. I am using Spring Data Repositories which are autowired. I have created my own custom realm for Shiro which uses a Spring Data repository to talk to Mongo:
public class PlatformRealm extends AuthorizingRealm {
#Autowired(required = true)
protected UserRepository userRepository = null;
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
...
}
}
The problem I'm seeing is the userRepository isn't being autowired. I get the following line in my console output referring to the PlatformRealm:
INFO org.springframework.web.context.support.XmlWebApplicationContext - Bean 'platformRealm' of type [class com.resonance.platform.core.security.PlatformRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
This is because of the Apache Shiro ShiroFilterFactoryBean. What is happening is this bean and all of its dependencies are being loaded up immediately when the container is started. It doesn't wait for my persistence beans to be initialized prior to resolving dependencies. This causes the repository reference to be null.
The following bean configurations are loaded via the contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/web-platform-persistence.xml,
/WEB-INF/web-platform-services.xml
</param-value>
</context-param>
Services bean configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<bean id="userSession"
class="com.resonance.platform.web.core.services.ShiroUserSessionService" />
<!-- Shiro (Security) -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/" />
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter
bean -->
<!-- defined will be automatically acquired and available via its beanName
in chain -->
<!-- definitions, but you can perform instance overrides or name aliases
here if you like: -->
<!-- <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/>
</util:map> </property> -->
<property name="filterChainDefinitions">
<value>
# some example chain definitions:
/admin/** = passThruFilter, roles[admin]
/** = passThruFilter
</value>
</property>
</bean>
<bean id="passThruFilter"
class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property
instead. -->
<property name="realm" ref="platformRealm" />
<!-- By default the servlet container sessions will be used. Uncomment
this line to use shiro's native sessions (see the JavaDoc for more): -->
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- Define the Shiro Realm implementation you want to use to connect to
your back-end -->
<!-- security datasource: -->
<bean id="platformRealm" class="com.resonance.platform.core.security.PlatformRealm" />
Persistence bean config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<mongo:mongo id="mongo" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo" />
<constructor-arg value="platform" />
<property name="writeConcern">
<util:constant static-field="com.mongodb.WriteConcern.SAFE" ></util:constant>
</property>
</bean>
<mongo:repositories base-package="com.resonance.platform.core.data.repositories" />
User Repository:
package com.resonance.platform.core.data.repositories;
import org.bson.types.ObjectId;
import org.springframework.data.repository.CrudRepository;
import com.resonance.platform.core.entities.User;
/**
* A repository used to manage User entities.
* #author Kyle
*/
public interface UserRepository extends CrudRepository<User, ObjectId> {
/**
* Gets a user by the specified login.
* #param login
* #return
*/
User getByLogin(String login);
}
My question is, how can I get the userRepository dependency to resolved properly? I understand that the ShiroFilterFactoryBean has to be initialized before the other dependencies and whatnot, but there must be a way to get the userRepository dependency to be resolved.
EDIT: Added User Repository code.
I am running into the same problem described here.
I am noticing two spring factories.
from the dispacher-servlet.xml which loads #Service #Repository classes due to component-scan defined at an base package level so I can #Autowire Service class into Controller.
from application context doesn't seem to #Autowire classes marked as #Service because they are not loaded.
If I understand you right you should be able to create a subclass of ShiroFilterFactoryBean which implements org.springframework.beans.factory.InitializingBean. In InitializingBean.afterPropertiesSet() you would then add some code that gets the UserRepository and sets it to that field. Not the most elegant solution, but this looks like an exceptional case.
I've had this problem too. It has something to do with the order of bean initialization in the Spring container. The workaround is not to autowire the repository but have your realm implement ApplicationContextAware and get the needed beans straight from the context. It's not elegant, but it'll work.
I am not too sure if this is helpful, but you may check this question from me for an alternative solution.
But, the core issue probably still stays open.
Concrete problem explanation taken from ShiroFilterFactoryBean-and-a-spring-data-mongodb-realm:
The problem is that spring-data-mongodb requires a spring
ApplicationEventMulticaster to have been initialised before it can be
used.
ShiroFilterFactoryBean is a beanPostProcessor, and as such, during
initialisation, spring attempts to configure its realms(and hence my
realm and spring data mongo based userDao). it fails because
ApplicationEventMulticaster has not yet been created.
After I've tried several suggested ways to solve this problem, like the InitializingBean, ApplicationContextAware or BeanPostProcessor interfaces (each resulting in a premature invocation, hence before initializing my necessary service/repository stuff), I came up with the following solution:
Let spring create your shiro context without any automatic bean resolution to your services/repositories.
Let spring create your service/repository context, including mongodb
Create a simple class which will take care of your shiro-service coupling and configure it accordingly in your spring config. This class will be invoked after your shiro and service context has been successful set up.
To (1), sth. like this:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="filterChainDefinitions">
<value>
<!-- Your definitions -->
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"
p:realm-ref="myShiroRealm" />
<bean id="myShiroRealm" class="com.acme.MyShiroRealm"
<!--no bean refs here-->
/>
To (2), sth. like this:
<bean id="myService" class="com.acme.MyService"
c:myRepository-ref="myRepository" />
...
<!-- Ask Spring Data to scan our repositories -->
<mongo:repositories base-package="com.acme.repository.impl.mongodb" />
To (3):
public class ShiroRealmServiceBridge {
public static void postInject( MyShiroServerRealm realm, MyService service ) {
realm.setService( service );
}
}
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"><value>com.acme.ShiroRealmServiceBridge</value></property>
<property name="targetMethod"><value>postInject</value></property>
<property name="arguments">
<list>
<ref bean="myShiroRealm" />
<ref bean="myService" />
</list>
</property>
Advantages:
It works xD
No additional burden/dependencies on your shiro stuff
Complete spring configuration and setup, resulting in a consistent state after initialization
Disadvantage:
One time overhead setup
May result in an inconsistent state, which will complain at runtime rather than at startup, if you forget or bump the glue-configuration
The ShiroFilterFactoryBean implements the BeanPostProcessor and, since it has dependencies on the security manager w/ its own dependencies on data stores, data access objects, etc. it can cause a whole slew of Bean X of type Y is not eligible for getting processed by all BeanPostProcessors messages.
The worst part is that it seems to be just a way to see the Filter implementations that Spring is instantiating in order to track and possibly inject properties into AuthorizationFilters.
Frankly I don't need that headache just for filter tracking, so I created a custom version that did not include the BeanPostProcessor. I'm now forced to manually wire in Filter implementations to the beans "filters" property, but at least I don't have to deal with that error and the questionable status of my security manager and related beans.
I have a simple Spring Scheduled Taks defined by the following:
<context:component-scan base-package="com/test"/>
<task:scheduled-tasks>
<task:scheduled ref="myScheduler" method="doMyTask" fixed-rate="300000"/>
</task:scheduled-tasks>
<task:scheduler id="taskScheduler" pool-size="1"/>
<task:executor id="executorWithPoolSizeRange"
pool-size="1"
queue-capacity="100"/>
<bean id="cleanupClass" class="com.test.CleanupClass">
<property name="myProperty" value="3600"/>
</bean>
I would like to run a single thread synchronously every 5 minutes. However, what I get is FIVE instances of the task running consecutively every 5 minutes. Does anyone know if there is something missing from the XML description above?
I got the behavior I wanted using the #Scheduled annotations but I would rather not use annotation for the fixed-rate as I want it to be configurable outside of the code.
Thanks.
the following worked for me:
<bean id="task" class="com.foo.MyTask">
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="task" method="run" fixed-delay="300000" />
</task:scheduled-tasks>
<task:scheduler id="scheduler" pool-size="10" />
Greetings,
Mark
Is this the behavior you are seeing in the STS when you deploy it to tomcat? If so, you would want to undeploy the application, redeploy it and restart the application.
Another idea is to use SPEL expression from a properties file to use it with #Sched annotation. In that way it is still configurable while using that annotation.