I have a web application which is supposed to run a scheduled code:
package com.myproject.daemon.jobs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class MyDaemonJob {
private static final Logger log = LoggerFactory.getLogger(MyDaemonJob.class);
#PostConstruct
public void init() {
log.info("MyDaemonJob is intialized " );
}
#Scheduled(fixedDelay = 1000)
public void startDaemon() {
try {
log.info("MyDaemonJob is running ...");
} catch (Exception e) {
log.error("Encountered error running scheduled job: " + e.getMessage());
}
}
}
It surely is recognized as a Spring bean and initialized, as I can see from the PostConstruct log. However the method with the #Scheduled annotation never runs although it is supposed to run every 1 second.
Here is app context xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="
com.myproject.daemon.jobs,
com.myproject.product" />
</beans>
Thank you ALL for quick help. This is really helpful.
The code started working, once I added config class with annotations as shown below --
package com.myproject;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
#Configuration
#EnableScheduling
public class AppConfig {
// various #Bean definitions
}
To use the #scheduled annotation it is necessary to include the spring task name space in spring bean configuration xml file. You can update the following namespac e in your xml configuration file.
<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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd">
Otherwise if you use the spring-boot application you can include the #EnableScheduling in your configuration file
Related
I have the following class:
package org.edgexfoundry.pkg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
#EnableDiscoveryClient
public class Application {
public static ConfigurableApplicationContext ctx;
public static void main(String[] args) {
ctx = SpringApplication.run(Application.class, args);
System.out.println("WELCOME!");
}
and in another class of the same project I have:
#ImportResource("spring-config.xml")
public class BaseService {
#PostConstruct
private void postConstructInitialize() {
logger.debug("post construction initialization");
}
}
where my spring-config.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core" xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder
location="classpath:*.properties" />
<bean class="org.edgexfoundry.pkg.HeartBeat" />
<context:component-scan base-package="org.edgexfoundry.pkg" />
<context:component-scan base-package="org.edgexfoundry" />
</beans>
and the HeartBeat class:
#EnableScheduling
public class HeartBeat {
private static final EdgeXLogger logger = EdgeXLoggerFactory.getEdgeXLogger(HeartBeat.class);
#Scheduled(fixedRateString = "${heart.beat.time}")
public void pulse() {
logger.info("Beating...");
}
}
When I run the project, I get the following output:
BySpringCGLIB$$1088c4ff] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
/*******************************************************************************
* Copyright 2017, Dell, Inc. All Rights Reserved.
******************************************************************************/
WELCOME!
2019-04-02 12:50:24.574 INFO 1 --- [ main] org.edgexfoundry.pkg.Application : No active profile set, falling back to default profiles: default
and after a long time, (about 8 minutes), I get the last line:
2019-04-02 12:57:04.611 DEBUG 1 --- [ main] org.edgexfoundry.pkg.BaseService : post construction initialization
What is being done in the meantime? Why does the #PostConstruct method need so much time to run i.e. why does SpringApplication.run() method finish so late? Any ideas?
One reason for a apparently slow startup is the default implementation of SecureRandom which scans network interfaces to provide an additional source of system entropy.
One can avoid this by registering an own java.security.Provider or by using the SecureRandomSpi.
Amongst others there is also this good introduction in the topic of (fast) and secure pseudo random number generation in Java.
I'm stuck with the following problem. My application doesn't create my Services at startup and I end up with a NullPointerException when I try to use them in my Maven Tests after Inject them with #Autowired.
I don't understand where it comes from. I have done some research but I still don't understand why it doesn't work.
Here is the class where my Autowired administrationActionService is null:
public class AdministrationActionTests extends EntityTests {
#Autowired
AdministrationActionService administrationActionService;
#Test
public void equalsTests() {
administrationActionService.getExample();
[...]
The class :
package com.bloombooking.services;
#org.springframework.stereotype.Service
public class AdministrationActionService extends ServiceEntity{
#Autowired private AdministrationActionDao administrationActionDao;
[...]
And my ApplicationContext.xml. I've placed it in src/ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.bloombooking.services, com.bloombooking.dao"/>
</beans>
I really don't know what I could have done wrong. Can someone help me? Thanks!
To make it work you have to make the following changes:
add #RunWith(SpringJUnit4ClassRunner.class) to your class.
add #ContextConfiguration("path_to_you_spring_beans.xml")
So your class becomes:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("path_to_you_spring_beans.xml")
AdministrationActionTests {
}
I am using Spring AOP to create an Aspect. The Aspect that I defined is being executed twice. I can't seem to figure out why. I'd appreciate any inputs anyone has on this issue.
Thanks!
// Spring Configuration
<?xml version="1.0" encoding="UTF-8"?>
<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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="no"
default-lazy-init="true">
<bean id="loggingAdvice" class="com.xyz.aop.LoggingAdvice" />
<aop:config>
<aop:aspect id="loggingAspect" ref="loggingAdvice">
<aop:pointcut id="loggingPointcut"
expression="execution(* com.xyz.FooServiceImpl.foo(..))"/>
<aop:around pointcut-ref="loggingPointcut" method="log" />
</aop:aspect>
</aop:config>
<context:component-scan base-package="com.xyz.controllers" />
</beans>
// Advice
package com.xyz.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
public class LoggingAdvice {
public Object log(final ProceedingJoinPoint pjp) throws Throwable {
log.info("Started!");
try {
return pjp.proceed();
} finally {
log.info("Ended!");
}
}
}
// Advised Method
package com.xyz;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class FooServiceImpl implements FooService {
private static final Log log = LogFactory.getLog(FooServiceImpl.class);
#Override
public void foo() {
log.info("Foo!");
}
}
}
// Output
Started!
Started!
Foo!
Ended!
Ended!
// EDIT 1: Added more spring configuration info. Not using any Spring AOP annotations at all. I attached a debugger and saw that the aspect/log statements were being executed twice as well. So I doubt that it has anything to do with log statement printing the string twice.
Well, it seems like this is actually an issue with the logger. Same problem I encountered long time back and found that everything is being logged twice. When I replaced logger calls with regular sysout calls, everything worked fine.
Because the <aop:around...> is telling this to do work both before and after the method. You could use <aop:before...> or <aop:after...> instead for running only once.
I have a web application in which I'm using spring MVC. I have defined few constants in sample.properties file. spring-servlet is the servlet that gets initialized for all urls in my app. spring-servlet:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<context:property-placeholder location="classpath:sample.properties"/>
</beans>
In one of my java classes I access the value of one of the properties like this:
package com.sample;
import com.google.gson.JsonArray;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class Validator {
#Value("${credit}")
String credits;
private static final Logger LOG = Logger.getLogger(Validator.class);
public void checkRating() {
LOG.debug(credits);
}
}
sample.properties:
credit=[{"duration":15,"credit":10},{"duration":30,"credit":20}]
When Validator is called from a controller, it just logs it as ${credit} in my log file. I dont get its value. Similarly, if I put an integer / floating point number in the properties file, I get an error saying it cannot be cast into integer / float. Am I missing any configuration?
The reason for this is because propertyplaceholder configurer is a BeanFactoryPostProcessor and it processess only the beans defined in the context in which the propertyplaceholder is configured. In a web application typically there is a heirarchy of context as explained here. Hence you need to declare this at appropriate place.
I have a scenario where I need to access spring managed beans in my domain object(i.e. object created with new operator). I searched a lot and found that it can be done using Load Time Weaving provided by aspectJ. I've done all configurations for the above to the best of my knowledge. I'm new to aspectJ. Following are my code and the configuration files.
Domain class,
package test.components;
import hibSERVICES.NounHeader.NounHeaderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable
public class TestLoadTimeWeaving {
#Autowired
private NounHeaderService nounHeaderService;
public void hello(){
nounHeaderService.findByPrimaryKey(0L);
}
}
Controller,
package test.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping(value = "/testController.do")
public class TestController{
#RequestMapping(params = "todo=onLoad", method = {RequestMethod.POST, RequestMethod.GET})
public void onLoad(HttpServletRequest request, HttpServletResponse response){
TestLoadTimeWeaving testLoadTimeWeaving = new TestLoadTimeWeaving();
testLoadTimeWeaving.hello();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="test" />
<context:load-time-weaver aspectj-weaving="on"/>
<bean lass="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" factory-method="aspectOf"/>
aop.xml,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN"
"http://www.aspectj.org/dtd/aspectj_1_5_0.dtd">
<aspectj>
<weaver>
<exclude within="*..*CGLIB*" />
</weaver>
</aspectj>
I've written -javaagent:c:\spring-agent-2.5.6.jar as the VM argument
Using following jars to support LTW and aspectJ,
aspectjrt-1.5.4.jar
spring-agent-2.5.6.jar
spring-aspect.jar
aspectjWeaver-1.5.4.jar
spring-2.5.6.jar
All other spring dependencies are working fine, only the dependencies which are injected in the domain objects( i.e. object created with new operator) are not working i.e. I'm getting null for those depedencies.
Kindly help. Thanks in advance.