schedule task with spring mvc - java

I want to run the following method every specific time in spring mvc project it works fine and print first output
but it doesn't access the database so it doesn't display list
the method
public class ScheduleService {
#Autowired
private UserDetailService userDetailService;
public void performService() throws IOException {
System.out.println("first output");
List<UserDetail> list=userDetailService.getAll();
System.out.println(list);
}
config file
<!-- Spring's scheduling support -->
<task:scheduled-tasks scheduler="taskScheduler">
<task:scheduled ref="ScheduleService" method="performService" fixed-delay="2000"/>
</task:scheduled-tasks>
<!-- The bean that does the actual work -->
<bean id="ScheduleService" class="com.ctbllc.ctb.scheduling.ScheduleService" />
<!-- Defines a ThreadPoolTaskScheduler instance with configurable pool size. -->
<task:scheduler id="taskScheduler" pool-size="1"/>

try this (and remove bean definition from xml file):
#Component
public class ScheduleService {
#Autowired
private UserDetailService userDetailService;
#Scheduled(fixedDelay = 2000L) // in msec
public void performService() throws IOException {
System.out.println("first output");
List<UserDetail> list=userDetailService.getAll();
System.out.println(list);
}
}

Write an integration test for that specific service and see if the service method calls returns anything at all. Manually testing always leads to such problems. Start with tests and debug if necessary.

Related

Autowiring against Interface returns null - Spring MVC

I am working on this Spring MVC project where I have trouble getting this Dao class auto wired in the controller through an Interface that is implemented by the Dao. This is portion of my spring-config.xml. I am using aspectJ, Annotation and TX management.
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.simulator" />
<context:annotation-config />
<tx:annotation-driven />
<context:property-placeholder
location="classpath*:config.properties" />
<bean id="oidDao" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Dao class:
#Component
public class OidDao implements OidManager {
#Autowired
private SessionFactory sessionFactory;
private String ipaddressNC;
private String ipaddressOM;
public String getIpaddressNC() {
return this.ipaddressNC;
}
public void setIpaddressNC(String ipaddressNC) {
this.ipaddressNC = ipaddressNC;
}
public String getIpaddressOM() {
return ipaddressOM;
}
public void setIpaddressOM(String ipaddressOM) {
this.ipaddressOM = ipaddressOM;
}
OidManager:
public interface OidManager {
public String getIpaddressNC();
public String getIpaddressOM();
}
Controller:
#Controller
public class HomeController {
#Autowired
OidManager oim;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String indexpage(ModelMap modelMap) {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"});
o = (OidManager)context.getBean("oidDao");
o.getIpaddressNC(); // ---> this returns data read from ext properties file and works fine
oim.getIpaddressNC(); // ---> this returns null`
I am trying to re-use the Dao, hence I dont want to call the ApplicationContext multiple times from each method. What am I doing wrong? If I make the variables getIpaddressNC, getIpaddressOM static, then auto wiring works, if not oim returns null though the variables are initialized via setters on application load.
You used both Component Scanning and Manual Wiring for OidDao. You defined oidDao in xml config, as follows:
<bean id="oidDao" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Then, added a Component annotation on OidDao, as follows:
#Component
public class OidDao implements OidManager {
...
}
Drop the Component annotation and you'll be fine, i guess! Because otherwise, <context:component-scan base-package="com.simulator" /> will pick OidDao and instantiate an instance from it with default constructor and without calling your setters.
You are using #Component annotation + you have also defined a bean. Therefore actually two beans are created. One created due to use of #Component would have the properties set to 'null'. This is expected since you are not setting the properties to any value. Either remove #Component annotation and use 'autowire-candidate="true"' property on bean definition or else remove the bean definition in XML and use relevant annotation on the class to set properties to correct values from property file.
Change your bean definition to:
<bean id="oim" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Let this create bean with id oim which can be set to the property oim in your Controller.

Testing RabbitMQ with Spring and Mockito

Attempting to have Spring JUnit runner run test with RabbitTemplate and the listener injected with a Mockito stubbed service class. Trying to verify interaction with the Mock. With the examples I've seen I thought this would be possible. RabbitMQ is working. When logging into the dashboard, I can see the messages there. Am able to consume messages also with standalone console application.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/spring/servlet-context.xml", "classpath:/spring/root-context.xml", "classpath:rabbitlistener-context-test.xml"})
public class ReceiveOrderQueueListenerTest {
#Mock
private ReceiveOrderRepository mockRepos;
#Autowired
RabbitTemplate rabbitTemplate;
#Autowired
SimpleMessageListenerContainer listenerContainer;
#InjectMocks
#Autowired
ReceiveOrderQueueListener receiveOrderQueueListener;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testAbleToReceiveMessage() {
RequestForService rfs = new RequestForService();
rfs.setClaimNumber("a claim");
rabbitTemplate.convertAndSend("some.queue", rfs);
verify(mockRepos).save(new OrderRequest());
}
}
then the rabbit-listener config
<?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:rabbit="http://www.springframework.org/schema/rabbit"
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-3.2.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
<rabbit:connection-factory id="rabbitConnectionFactory" host="XXXXXXXXX.com" username="test" password="test" />
<!-- <rabbit:connection-factory id="rabbitConnectionFactory" host="localhost" username="guest" password="guest" /> -->
<rabbit:admin connection-factory="rabbitConnectionFactory" auto-startup="true" />
<rabbit:template id="tutorialTemplate" connection-factory="rabbitConnectionFactory" exchange="TUTORIAL-EXCHANGE"/>
<rabbit:queue name="some.queue" id="some.queue"></rabbit:queue>
<bean id="receiveOrderListener" class="XXXXXXXXXX.connect.message.ReceiveOrderQueueListenerImpl"></bean>
<rabbit:topic-exchange id="myExchange" name="TUTORIAL-EXCHANGE">
<rabbit:bindings>
<rabbit:binding queue="some.queue" pattern="some.queue"></rabbit:binding>
</rabbit:bindings>
</rabbit:topic-exchange>
<rabbit:listener-container connection-factory="rabbitConnectionFactory">
<!-- <rabbit:listener queues="some.queue" ref="receiveOrderListener" method="handleMessage"/> -->
<rabbit:listener queues="some.queue" ref="receiveOrderListener" />
</rabbit:listener-container>
</beans>
Tried injecting in the MessgeListenerAdaptor as well thinking the test needed that to wire the listener correct as well. With the adaptor injected in, I am able to verify the delegate gets injected in and with the stub.
Test fails on no zero interactions with mock. I can log into rabbitmq and the messages are there. The injected listener object is not consuming messages from the queue during the run of this test.
Almost forgot, the said listener. Tried default signature and tried the designate method.
public class ReceiveOrderQueueListenerImpl implements ReceiveOrderQueueListener {
#Autowired
ReceiveOrderRepository receiveOrderRepository;
#Override
public void handleMessage(RequestForService rfs) {
System.out.println("receive a message");
receiveOrderRepository.save(new OrderRequest());
}
public void onMessage(Message message) {
receiveOrderRepository.save(new OrderRequest());
}
}
Any suggestions would be helpful and I appreciate your help ahead of time.
I can't see any synchronization in your test. Messaging is asynchronous by nature (meaning that your test can finish before the message arrives).
Try using a Latch concept, which blocks until the message arrives or until the timeout expires.
First you need a test listener bean for your queue:
#Bean
#lombok.RequiredArgsContructor
#lombok.Setter
public class TestListener {
private final ReceiveOrderQueueListener realListener;
private CountDownLatch latch;
public void onMessage(Message message) {
realListener.onMessage(message);
latch.countDown();
}
}
Make sure to configure it to be used in place of your original listener in the test context.
Then in your test you can set the latch:
public class ReceiveOrderQueueListenerTest {
#Autowired
private TestListener testListener;
#Test
public void testAbleToReceiveMessage() {
RequestForService rfs = new RequestForService();
rfs.setClaimNumber("a claim");
// Set latch for 1 message.
CountDownLatch latch = new CountDownLatch(1);
testListener.setLatch(latch);
rabbitTemplate.convertAndSend("some.queue", rfs);
// Wait max 5 seconds, then do assertions.
latch.await(5, TimeUnit.SECONDS);
verify(mockRepos).save(new OrderRequest());
}
}
Note that there are better ways how to use latches (e.g. channel interceptors or LatchCountDownAndCallRealMethodAnswer with Mockito), but this is the basic idea. See Spring AMQP testing reference for more info.

How can I customize the AuditingHandler injected by Spring-Data when using Auditing?

I'm using Spring Data 1.5 and Auditing. Part of the AuditingEntityListener has a setAuditingHandler method.
How can I customize the AuditingHandler and instruct Spring-Data to inject my custom handler instead of the default org.springframework.data.auditing.AuditingHandler?
I've tried instantiating my own AuditingEntityListener in which I inject my own Handler, but that is not doing the job. The default handler is still being injected. I've tried both via XML configuration and JavaConfig to see if one worked better than the other, but neither way works.
JavaConfig:
#Configuration
#EnableJpaAuditing(auditorAwareRef="auditorProvider")
public class AppConfig {
#Bean
public AuditorAware<User> auditorProvider(){
return new SpringSecurityAuditorAware();
}
#Bean
public AuditingEntityListener auditingEntityListener(){
AuditingEntityListener listener = new AuditingEntityListener();
listener.setAuditingHandler(new com.ia.persistence.AuditingHandler());
return listener;
}
}
My custom handler:
#Component
public class AuditingHandler extends org.springframework.data.auditing.AuditingHandler {
// SLF4J logger
private static final Logger logger = LoggerFactory.getLogger(AuditingHandler.class);
/* (non-Javadoc)
* #see org.springframework.data.auditing.AuditingHandler#markCreated(java.lang.Object)
*/
#Override
public void markCreated(Object source) {
logger.info("Custom handler");
super.markCreated(source);
}
/* (non-Javadoc)
* #see org.springframework.data.auditing.AuditingHandler#markModified(java.lang.Object)
*/
#Override
public void markModified(Object source) {
logger.info("Custom handler");
super.markModified(source);
}
}
What am I doing wrong? With my JavaConfig, I do not even see Spring instantiating the listener using my configuration. Alternatively, I've tried using XML configuration to configure the listener, but the default listener is still the one that is used.
<!-- enable Spring data-JPA repositories -->
<jpa:repositories base-package="com.ia" />
<bean id="auditingEntityListener" class="org.springframework.data.jpa.domain.support.AuditingEntityListener">
<property name="auditingHandler" ref="auditingHandler"/>
</bean>
Any suggestions would be helpful.
I met the same question.
The short version
You have to register jpaAuditingHandler bean definition using BeanDefinitionRegistry.
The long version
the org.springframework.data.jpa.domain.support.AuditingEntityListener is a special class which mixed in with aspectj when compiling. see here
It need a bean definition to work. see the spring framework document.
the org.springframework.data.jpa.repository.config.EnableJpaAuditing you are using will register the bean definition with auditingHandler bind to a jpaAuditingHandler bean. It also will register the jpaAuditingHandler bean definition.
If you add a jpaAuditingHandler using #Component, it won't work because Spring prefer another one. see org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
So you have to register your bean definition using BeanDefinitionRegistry.
public class jpaAuditingHandlerRegistrar implements ImportBeanDefinitionRegistrar {
#Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("jpaAuditingHandler", BeanDefinitionBuilder
.rootBeanDefinition(JpaAuditingHandler.class)
.addConstructorArgReference("jpaMappingContext")
.getBeanDefinition());
}
}
and add #Import(JpaAuditingHandlerRegistrar.class) to your Configuration class
#SpringBootApplication
#EnableJpaAuditing
#Import(JpaAuditingHandlerRegistrar.class)
public class Application {
I put sample code https://github.com/macdao/customize-auditing-handler

How to conditionally enable or disable scheduled jobs in Spring?

I am defining scheduled jobs with cron style patterns in Spring, using the #Scheduled annotation.
The cron pattern is stored in a config properties file. Actually there are two properties files: one default config, and one profile config that is environment dependent (e.g. dev, test, prod customer 1, prod customer 2 etc.) and overrides some of the default values.
I configured a property placeholder bean in my spring context which allows me to use ${} style placeholders to import values from my properties files.
The job beans looks like this:
#Component
public class ImagesPurgeJob implements Job {
private Logger logger = Logger.getLogger(this.getClass());
#Override
#Transactional(readOnly=true)
#Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
public void execute() {
//Do something
//can use DAO or other autowired beans here
}
}
Relevant parts of my context XML :
<!-- Enable configuration of scheduled tasks via annotations -->
<task:annotation-driven/>
<!-- Load configuration files and allow '${}' style placeholders -->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/default-config.properties</value>
<value>classpath:config/environment-config.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="false"/>
</bean>
I really like this. It's quite simple and clean with minimal XML.
However I have one more requirement: some of these jobs can be totally disabled in some cases.
So, before I used Spring to manage them I created them manually and there is a boolean parameter along with the cron parameter in the config files, to specify if the job has to be enabled or not:
jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?
How can I use this parameter in Spring to conditionally create or just plainly ignore the bean, depending on this config parameter?
One obvious workaround would be to define a cron pattern that would never evaluate, so the job is never executed. But the bean would still be created and the config would be a bit obscure, so I feel there must be a better solution.
The most efficient way to disable #Scheduled in Spring is to set cron expression to -
#Scheduled(cron = "-")
public void autoEvictAllCache() {
LOGGER.info("Refresing the Cache Start :: " + new Date());
activeMQUtility.sendToTopicCacheEviction("ALL");
LOGGER.info("Refresing the Cache Complete :: " + new Date());
}
From the docs:
CRON_DISABLED
public static final String CRON_DISABLED
A special cron
expression value that indicates a disabled trigger: "-". This is
primarily meant for use with ${...} placeholders, allowing for
external disabling of corresponding scheduled methods.
Since:
5.1 See Also: ScheduledTaskRegistrar.CRON_DISABLED
#Component
public class ImagesPurgeJob implements Job {
private Logger logger = Logger.getLogger(this.getClass());
#Value("${jobs.mediafiles.imagesPurgeJob.enable}")
private boolean imagesPurgeJobEnable;
#Override
#Transactional(readOnly=true)
#Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
public void execute() {
//Do something
//can use DAO or other autowired beans here
if(imagesPurgeJobEnable){
Do your conditional job here...
}
}
}
You can group schedule methods by conditions into number of services and init them like this:
#Service
#ConditionalOnProperty("yourConditionPropery")
public class SchedulingService {
#Scheduled
public void task1() {...}
#Scheduled
public void task2() {...}
}
Spring Boot provides #ConditionalOnProperty, which would be perfect if you were using Spring Boot. This annotation is a specialization of #Conditional, introduced with Spring 4.0.0.
Assuming you're just using "regular" spring and not Spring Boot, you could create your own Condition implementation for use with #Conditional that would mimic Spring Boot's #ConditionalOnProperty.
If you are looking to toggle #EnableScheduling from a property you can do this in Spring Boot by moving the #EnableScheduling annotation to a configuration class and use #ConditionalOnProperty as follows:
#Configuration
#EnableScheduling
#ConditionalOnProperty(prefix = "com.example.scheduling", name="enabled", havingValue="true", matchIfMissing = true)
public class SchedulingConfiguration {
}
This will disable scheduling for the application. This may be useful in a situation where you want to be able to run the application once or scheduled depending on how it's being started.
From wilkinsona's comment on here: https://github.com/spring-projects/spring-boot/issues/12682
Your question states to condition the actual creation of the bean. You can do this easily with this parameter by using #Profile if you are using at least Spring 3.1.
See the documentation here: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html
You can also create a Bean based on condition and that Bean can have a Scheduled method.
#Component
#Configuration
#EnableScheduling
public class CustomCronComponent {
#Bean
#ConditionalOnProperty(value = "my.cron.enabled", matchIfMissing = true, havingValue = "true")
public MyCronTask runMyCronTask() {
return new MyCronTask();
}
}
and
#Component
public class MyCronTask {
#Scheduled(cron = "${my.cron.expression}")
public void run() {
String a = "";
}
}
#Component
public class CurrencySyncServiceImpl implements CurrencySyncService {
private static Boolean isEnableSync;
/**
* Currency Sync FixedDelay in minutes
*/
private static Integer fixedDelay;
#Transactional
#Override
#Scheduled(fixedDelayString = "#{${currency.sync.fixedDelay}*60*1000}")
public void sync() {
if(CurrencySyncServiceImpl.isEnableSync) {
//Do something
//you can use DAO or other autowired beans here.
}
}
#Value("${currency.sync.fixedDelay}")
public void setFixedDelay(Integer fixedDelay) {
CurrencySyncServiceImpl.fixedDelay = fixedDelay;
}
#Value("${currency.sync.isEnable}")
public void setIsEnableSync(Boolean isEnableSync) {
CurrencySyncServiceImpl.isEnableSync = isEnableSync;
}
}
Please see my answer in another question. I think this is the best way to solve it.
How to stop a scheduled task that was started using #Scheduled annotation?
Define a custom annotation like below.
#Documented
#Retention (RUNTIME)
#Target(ElementType.TYPE)
public #interface ScheduledSwitch {
// do nothing
}
Define a class implements org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.
public class ScheduledAnnotationBeanPostProcessorCustom
extends ScheduledAnnotationBeanPostProcessor {
#Value(value = "${prevent.scheduled.tasks:false}")
private boolean preventScheduledTasks;
private Map<Object, String> beans = new HashMap<>();
private final ReentrantLock lock = new ReentrantLock(true);
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
ScheduledSwitch switch = AopProxyUtils.ultimateTargetClass(bean)
.getAnnotation(ScheduledSwitch.class);
if (null != switch) {
beans.put(bean, beanName);
if (preventScheduledTasks) {
return bean;
}
}
return super.postProcessAfterInitialization(bean, beanName);
}
public void stop() {
lock.lock();
try {
for (Map.Entry<Object, String> entry : beans.entrySet()) {
postProcessBeforeDestruction(entry.getKey(), entry.getValue());
}
} finally {
lock.unlock();
}
}
public void start() {
lock.lock();
try {
for (Map.Entry<Object, String> entry : beans.entrySet()) {
if (!requiresDestruction(entry.getKey())) {
super.postProcessAfterInitialization(
entry.getKey(), entry.getValue());
}
}
} finally {
lock.unlock();
}
}
}
Replace ScheduledAnnotationBeanPostProcessor bean by the custom bean in configuration.
#Configuration
public class ScheduledConfig {
#Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
#Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationBeanPostProcessor() {
return new ScheduledAnnotationBeanPostProcessorCustom();
}
}
Add #ScheduledSwitch annotation to the beans that you want to prevent or stop #Scheduled tasks.
I know my answer is a hack, but giving a valid cron expression that never executes may fix the issue (in the environment specific configuration), Quartz: Cron expression that will never execute
We can disable the bean creation of the class having that scheduled methods using #Conditional annotation. This is very similar to #ConditionalOnProperty. This is used to conditionally spin up a bean on to the spring context. If we set the value to false, then the bean will not be spun up and loaded to spring. Below is the code.
application.properties:
com.boot.enable.scheduling=enable
Condition:
public class ConditionalBeans implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return "enabled".equalsIgnoreCase(context.getEnvironment().getProperty("com.boot.enable.scheduling"));
}
}
My schedule class
#Service
#Conditional(ConditionalSchedules.class)
public class PrintPeriodicallyService {
#Scheduled(fixedRate = 3000)
public void runEvery3Seconds() {
System.out.println("Current time : " + new Date().getTime());
}
}
This approach has a lot of flexibility where the condition generation is totally under our control.

How to rollback a database transaction when testing services with Spring in JUnit?

I have no problem testing my DAO and services, but when I test INSERTs or UPDATEs I want to rollback the transaction and not effect my database.
I'm using #Transactional inside my services to manage transactions. I want to know, is it possible to know if a transaction will be fine, but rollback it to prevent altering database?
This is my Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml")
#TransactionConfiguration(defaultRollback=true)
public class MyServiceTest extends AbstractJUnit38SpringContextTests {
#Autowired
private MyService myService;
#BeforeClass
public static void setUpClass() throws Exception {
}
#AfterClass
public static void tearDownClass() throws Exception {
}
#Test
public void testInsert(){
long id = myService.addPerson( "JUNIT" );
assertNotNull( id );
if( id < 1 ){
fail();
}
}
}
The problem is that this test will fail because transaction was rollbacked, but the insert is OK!
If I remove #TransactionConfiguration(defaultRollback=true) then the test pass but a new record will be inserted into database.
#Test
#Transactional
#Rollback(true)
public void testInsert(){
long id = myService.addPerson( "JUNIT" );
assertNotNull(id);
if( id < 1 ){
fail();
}
}
Now can test pass correctly, but rollback is ignored and the record is inserted into the database.
I have annotated the method addPerson() inside myService with #Transactional, obviously.
Why is the rollback being ignored?
You need to extend transaction boundaries to the boundaries of your test method. You can do it by annotating your test method (or the whole test class) as #Transactional:
#Test
#Transactional
public void testInsert(){
long id=myService.addPerson("JUNIT");
assertNotNull(id);
if(id<1){
fail();
}
}
You can also use this approach to ensure that data was correctly written before rollback:
#Autowired SessionFactory sf;
#Test
#Transactional
public void testInsert(){
myService.addPerson("JUNIT");
sf.getCurrentSession().flush();
sf.getCurrentSession().doWork( ... check database state ... );
}
check out
http://static.springsource.org/spring/docs/2.5.x/reference/testing.html
Section 8.3.4 in particular
Spring has some classes for testing that will wrap each test in a transaction, so the DB is not changed. You can change that functionality if you want too.
Edit -- based on your more infos, you might want to look at
AbstractTransactionalJUnit38SpringContextTests at
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html
Use Following annotation before class :
#TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
#Transactional
here txManager is application context's Transaction Manager.
Here txManager is an instance or bean id of Transaction manager from application context.
<!-- Transaction Manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
Add your code inside setUp() method, this will execute in start of the test and the last wrap up code should be put in teatDown() method that will executed at last. or you can also use #Before and #After annotation instead of it.
If your
myService.addPerson("JUNIT");
method is annotated like #Transactional you will be getting some different kind or errors trying to fix this. So you better just test DAO methods.

Categories