I have a MultiResourceItemReader with a custom ItemReader as a delegate. The problem I'm facing is that when I launch the job, the same file is read over and over again.
This is the delegate class:
public class AllegatiReader implements ResourceAwareItemReaderItemStream<Allegato> {
#PersistenceContext
protected EntityManager em;
private Resource resource;
#Override
public void close() throws ItemStreamException {
}
#Override
public void open(ExecutionContext arg0) throws ItemStreamException {
}
#Override
public void update(ExecutionContext arg0) throws ItemStreamException {
}
#Override
public Allegato read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
// DO SOMETHING ...
byte[] fileContent = new byte[(int) resource.getFile().length()];
resource.getInputStream().read(fileContent);
resource.getInputStream().close();
allegato.getFile().setFile(fileContent);
return allegato;
}
#Override
public void setResource(Resource arg0) {
this.resource = arg0;
}
}
Here is my Spring Batch XML configuration file:
<batch:job id="allegati" incrementer="jobParametersIncrementer">
<batch:step id="allegati-import">
<batch:tasklet>
<batch:chunk reader="allegati-reader" writer="allegati-writer" commit-interval="1"/>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="allegati-reader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step">
<property name="resources" value="file:#{jobParameters['FILEPATH']}/*" />
<property name="delegate" ref="allegati-filereader" />
</bean>
<bean id="allegati-writer" class="org.springframework.batch.item.database.JpaItemWriter">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="allegati-filereader" class="it.infogroup.vertenze.porting.reader.AllegatiReader" />
How can I tell Spring Batch to move to the next file?
Your custom reader has to show Spring Batch when all is done, see http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/item/ItemReader.html#read--
Reads a piece of input data and advance to the next one.
Implementations must return null at the end of the input data set.
in your case i would use an private attribute to save* the state for the resource of this reader instance is processed, it could be the Allegato object, but that seems to be a rather large one
*) your reader is stateful by design, so another state attribute should be no problem
Related
I'm working on writing tests for the route
The problem is all my routes contain properties that described in application.properties file e.g
from("oracleQueue:{{oracle.queue.url}}").to("my.endpoint")
It works fine but when I try to write a test - seems like this route can't find application.properties file with its properties.
The error:
java.lang.IllegalArgumentException: Property with key [oracle.queue.url] not found in properties from text: oracleQueue:{{oracle.queue.url}}
My testcase:
public class RouteTest extends CamelTestSupport {
#Override
protected RoutesBuilder createRouteBuilder() {
MyRouteBulder route = new MyRouteBulder ();
ApplicationContext appContext = new ClassPathXmlApplicationContext("camel-context.xml");
PropertiesComponent pc = new PropertiesComponent();
pc.setLocation("application.properties");
CamelContext context = new SpringCamelContext(appContext);
context.addComponent("properties", pc);
route.setContext(context);
return route;
}
#Test
public void test() throws InterruptedException {
MockEndpoint mockEndpoint = resolveMandatoryEndpoint("my.endpoint", MockEndpoint.class);
mockEndpoint.expectedMessageCount(1);
template.sendBody("oracleQueue:{{oracle.queue.url}}", "hello world");
mockEndpoint.assertIsSatisfied();
}
}
How should I set up configuration file properly?
Maybe you need an absolute path for the location.
I use this to get props
<bean
class="org.apache.camel.component.properties.PropertiesComponent"
id="properties" name="properties">
<property name="cache" value="false"/>
<property name="locations">
<list>
<value>file:${CONF}/broker.properties</value>
<value>file:${CONF}/sops/domains/properties/a92fe32d-01c9-4c00-b2c0-b17a71503bbe.properties;optional=true</value>
</list>
</property>
</bean>
I managed to configure and schedule a Quartz job using JobStoreTX persistent store in Spring Boot ( version 4.2.5 ). Here is how I schedule the job.
First :
public class MyJob implements Job{
#Autowired
IService service;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
service.doSomething();
}
}
#Autowired seems like it wont work in a Quartz job implementation because it wont be instantiated by Spring. Hence, im facing the famous JavaNullPointerException.
Second, in order to get hold of Spring-managed beans in a Quartz job, I used org.springframework.scheduling.quartz.SchedulerFactoryBean to manage the Quartz lifecycle :
public class MyJob implements Job{
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext().get("applicationContext");
IService service= applicationContext.getBean(IService.class);
service.getManualMaxConfig();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
And then :
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
</bean>
The sad news is that im also facing JavaNPE.
I also try these suggestions, in vain ..
LINK
Whats wrong with what im doing?
Update 1 :
Before trying to inject service, i tried to pass some Params as #ritesh.garg suggests.
public class MyJob implements Job{
private String someParam;
private int someParam2;
public void setSomeParam(String someParam) {
this.someParam = someParam;
}
public void setSomeParam2(int someParam2) {
this.someParam2 = someParam2;
}
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("My job is running with "+someParam+' '+someParam2);
}
}
And my jobBean.xml looks like :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
</bean>
<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.quartz.service.MyJob"/>
<property name="jobDataAsMap">
<map>
<entry key="someParam" value="some value"/>
<entry key="someParam2" value="1"/>
</map>
</property>
</bean>
</beans>
I dont know why, but the parameters arent passed and it prints :
My job is running with null 0
Ps : I imported the jobBean.xml into Application.java . So i dont know what am i missing ?
Update 2 : Here is my detailed code :
#Component
public class JobScheduler{
Timer timer = new Timer();
#PostConstruct
public void distributeAutomaticConf(){
try {
timer.schedule(new ServiceImpl(), 10000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Service Impl :
#Transactional
#Component
public class ServiceImpl extends TimerTask implements IService{
#Override
public void run() {
final SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = null;
try {
scheduler = factory.getScheduler();
final JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setName("My job executed only once.. ");
jobDetail.setJobClass(MyJob.class);
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger_", "group_")
.build();
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger);
System.in.read();
if (scheduler != null) {
scheduler.shutdown();
}
} catch (final SchedulerException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
MyJob :
public class MyJob extends QuartzJobBean{
#Autowired
IService service;
#Override
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
service.doSomething();
}
}
jobBean.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
</bean>
<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.quartz.service.MyJob"/>
<property name="jobDataAsMap">
<map>
<entry key="someParam" value="some value"/>
<entry key="someParam2" value="1"/>
</map>
</property>
</bean>
</beans>
quartz.properties :
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.dataSource.myDS.driver = org.postgresql.Driver
org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost:5432/myDB
org.quartz.dataSource.myDS.user = admin
org.quartz.dataSource.myDS.password = admin
org.quartz.dataSource.myDS.maxConnections = 10
org.quartz.scheduler.skipUpdateCheck=true
console :
java.lang.NullPointerException: null
at com.quartz.service.MyJob.executeInternal(MyJob.java:27) ~[classes/:na]
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113) ~[spring-context-support-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.1.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.1.jar:na]
2016-06-05 11:35:16.839 ERROR 25452 --- [eduler_Worker-1] org.quartz.core.ErrorLogger : Job (DEFAULT.My job executed only once.. threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.2.1.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.1.jar:na]
Caused by: java.lang.NullPointerException: null
at com.quartz.service.MyJob.executeInternal(MyJob.java:27) ~[classes/:na]
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113) ~[spring-context-support-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.1.jar:na]
... 1 common frames omitted
I have experienced the same problem in past. My understanding on this issue is that beans instantiated in spring context cannot be injected in quartz context simply by using #Autowired annotation.
I managed to solve it by using setter based dependency injection. But the same is mentioned in the "LINK" you have added in the original post.
Pasting the relevant information from the link:
Update: Replaced implements Job with extends QuartzJobBean
public class MyJob extends QuartzJobBean {
private String someParam;
private int someParam2;
public void setSomeParam(String someParam) {
this.someParam = someParam;
}
public void setSomeParam2(String someParam2) {
this.someParam2 = someParam2;
}
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("My job is running with "+someParam+' '+someParam2);
}
}
Here, someParam and someParam2 are being injected via setter dependency injection. Now the other part that makes this complete is to pass someParam and someParam2 in jobDataAsMap
<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.my.MyJob"/>
<property name="jobDataAsMap">
<map>
<entry key="someParam" value="some value"/>
<entry key="someParam2" value="1"/>
</map>
</property>
</bean>
In your case, it would be a value-ref="IserviceBeanId", instead of 'value' in entry. I would be surprised as well as curious, if this did not/does not work for you.
I fix my problem implementing "InitializingBean" in my job;
public class MyJob extends QuartzJobBean implements InitializingBean {
private String someParam;
private int someParam2;
public void setSomeParam(String someParam) {
this.someParam = someParam;
}
public void setSomeParam2(String someParam2) {
this.someParam2 = someParam2;
}
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("My job is running with "+someParam+' '+someParam2);
}
#Override
public void afterPropertiesSet() throws Exception {
}
}
The correct way from the most of the examples I've seen is to make your Job interface implementation a #Component
#Component
public class MyJob implements Job{
#Autowired IService service;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException{
service.doSomething();
}
}
We can use JobDataMap to pass the objects.
example: here restTemplate is Autowired.
JobDataMap newJobDataMap = new JobDataMap();
newJobDataMap.put("restTemplate", restTemplate);
JobDetail someJobDetail = JobBuilder
.newJob(QuartzJob.class)
.withIdentity(jobName, GROUP)
.usingJobData(newJobDataMap)
.build();
Trying to implement Spring batch,but facing a strange problem,Our ItemReader class is executing only once.
Here below is the detail.
If we have 1000 rows in DB.
Our Item reader fetch 1000 rows from DB,and pass list to ItemWriter
ItemWriter successfully delete all items.
Now ItemReader again tries to fetch the data from DB,but did not find,hence returns NULL,so execution stops.
But we have configured batch to be executed with Quartz scheduler,which is every minute.
Now if we insert let say 1000 rows in DB by dump import,the batch job should pick this data in next execution,but it is not even executing,although
JobLauncher is executing.
Configuration :-
1.We have ItemReader,ItemWriter with commit interval equals to 1.
<batch:job id="csrfTokenBatchJob">
<batch:step id="step1">
<tasklet>
<chunk reader="csrfTokenReader" writer="csrfTokenWriter" commit-interval="1"></chunk>
</tasklet>
</batch:step>
</batch:job>
2.Job is scheduled to be triggered at every minute.
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 0/1 * * * ?" />
</bean>
</property>
</bean>
3.Job configuration
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.tavant.oauth.batch.job.CSRFTokenJobLauncher" />
<property name="jobDataAsMap">
<map>
<entry key="jobName" value="csrfTokenCleanUpBatchJob" />
<entry key="jobLocator" value-ref="jobRegistry" />
<entry key="jobLauncher" value-ref="jobLauncher" />
</map>
</property>
</bean>
First time it is executing successfully,but later it does not execute,but i can see in logs that JobLauncher is executing.
#Component("csrfTokenReader")
#Scope(value="step")
public class CSRFTokenReader implements ItemReader<List<CSRFToken>> {
private static final Logger logger = LoggerFactory.getLogger(CSRFTokenReader.class);
#Autowired
private CleanService cleanService;
#Override
public List<CSRFToken> read() {
List<CSRFToken> csrfTokenList = null;
try{
int keepUpto = Integer.valueOf(PropertiesContext.getInstance().getProperties().getProperty("token.keep", "1"));
Calendar calTime = Calendar.getInstance();
calTime.add(Calendar.HOUR, -keepUpto);
Date toKeep = calTime.getTime();
csrfTokenList = cleanService.getCSRFTokenByTime(toKeep);
}
catch(Throwable th){
logger.error("Exception in running job At " + new Date() + th);
}
if(CollectionUtils.isEmpty(csrfTokenList)){
return null;
}
return csrfTokenList;
}
}
EDIT:--
public class CSRFTokenJobLauncher extends QuartzJobBean {
static final String JOB_NAME = "jobName";
private JobLocator jobLocator;
private JobLauncher jobLauncher;
public void setJobLocator(JobLocator jobLocator) {
this.jobLocator = jobLocator;
}
public void setJobLauncher(JobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
#Override
protected void executeInternal(JobExecutionContext context) {
Map<String, Object> jobDataMap = context.getMergedJobDataMap();
String jobName = (String) jobDataMap.get(JOB_NAME);
log.info("Quartz trigger firing with Spring Batch jobName="+jobName);
JobParameters jobParameters = getJobParametersFromJobMap(jobDataMap);
try {
jobLauncher.run(jobLocator.getJob(jobName), jobParameters);
}
catch (JobExecutionException e) {
log.error("Could not execute job.", e);
}
}
private JobParameters getJobParametersFromJobMap(Map<String, Object> jobDataMap) {
JobParametersBuilder builder = new JobParametersBuilder();
for (Entry<String, Object> entry : jobDataMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof String && !key.equals(JOB_NAME)) {
builder.addString(key, (String) value);
}
else if (value instanceof Float || value instanceof Double) {
builder.addDouble(key, ((Number) value).doubleValue());
}
else if (value instanceof Integer || value instanceof Long) {
builder.addLong(key, ((Number)value).longValue());
}
else if (value instanceof Date) {
builder.addDate(key, (Date) value);
}
}
return builder.toJobParameters();
}
}
After hours of time wasting,the problem seems to be solved now,i have configured allow-start-if-complete="true" in tasklet.Now Batch Item Reader is executing as per schedule.
<batch:job id="csrfTokenBatchJob">
<batch:step id="step1">
<batch:tasklet allow-start-if-complete="true">
<batch:chunk reader="csrfTokenReader" writer="csrfTokenWriter" commit-interval="1"></batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
Spring batch records every job execution in database. Which is why spring batch need to differentiate every job run. It checks whether the job is already executed on the same day and it would not start again unless any job parameter varies from previous run or allow start if complete setting is enabled.
OPTION1:- As mentioned above answer we can use allow-start-if-complete="true"
OPTION2:- Always pass a job parameter which is a current date time stamp. This way job parameter value is always unique.
JobExecution jobExecution = jobLauncher.run(reportJob, new JobParametersBuilder()
.addDate("now", new Date()).build());
OPTION3:- Use an incrementor for example RunIdIncrementer so we do not need to make sure to pass unique job parameter every time.
#Bean
public Job job1(JobBuilderFactory jobs, Step s1) {
return jobs.get("job1")
.incrementer(new RunIdIncrementer())
.flow(s1)
.end()
.build();
}
I am trying to cause a job not to have BatchStatus.FAILED if a certain exception occurs.
The docs talk about using skippable-exception-classes within <chunk>, but how can I do the same within a TaskletStep? The below code does not work:
<batch:step id="sendEmailStep">
<batch:tasklet>
<bean class="com.myproject.SendEmail" scope="step" autowire="byType">
<batch:skippable-exception-classes>
<batch:include class="org.springframework.mail.MailException" />
</batch:skippable-exception-classes>
</bean>
</batch:tasklet>
</batch:step>
I implemented this functionality in the Tasklet as Michael Minella suggested:
abstract class SkippableTasklet implements Tasklet {
//Exceptions that should not cause job status to be BatchStatus.FAILED
private List<Class<?>> skippableExceptions;
public void setSkippableExceptions(List<Class<?>> skippableExceptions) {
this.skippableExceptions = skippableExceptions;
}
private boolean isSkippable(Exception e) {
if (skippableExceptions == null) {
return false;
}
for (Class<?> c : skippableExceptions) {
if (e.getClass().isAssignableFrom(c)) {
return true;
}
}
return true;
}
protected abstract void run(JobParameters jobParameters) throws Exception;
#Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
throws Exception {
StepExecution stepExecution = chunkContext.getStepContext().getStepExecution();
JobExecution jobExecution = stepExecution.getJobExecution();
JobParameters jobParameters = jobExecution.getJobParameters();
try {
run(prj);
} catch (Exception e) {
if (!isSkippable(e)) {
throw e;
} else {
jobExecution.addFailureException(e);
}
}
return RepeatStatus.FINISHED;
}
}
And the Spring XML configuration for an example SkippableTasklet:
<batch:tasklet>
<bean class="com.MySkippableTasklet" scope="step" autowire="byType">
<property name="skippableExceptions">
<list>
<value>org.springframework.mail.MailException</value>
</list>
</property>
</bean>
</batch:tasklet>
Within a Tasklet, the responsibility for exception handling is on the implementation of the Tasklet. The skip logic available in chunk oriented processing is due to the exception handling provided by the ChunkOrientedTasklet. If you want to skip exceptions in your own Tasklet implementation, you need to write the code to do so in within your own implementation.
I'm trying to add a custom save event listener for hibernate. My goal is to have hibernate set the last update and created timestamp values on certain entities. I have read from other posts that JPA annotations will do it but if you are using a Hibernate Session then you need to extend DefaultSaveOrUpdateEventListener. I did this and it hasn't worked. Every example I see is using a hibernate config file. My sessionFactory is configured with Spring.
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="myDataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.mypackages</value>
</list>
</property>
<property name="eventListeners">
<map>
<entry key="save-update">
<ref local="saveEventListener" />
</entry>
</map>
</property>
</bean>
<bean id="saveEventListener" class="com.mypackage.event.SaveOrUpdateDateListener" />
I set a breakpoint and it doesn't go through the listener. My last updated and created fields are not being set in the database.
I have worked with the similar issue and finally resolved.
I have a base pojo with properties for Auditing , Every entity extends this base pojo. on call to save or update, the methods of Event Listeners get triggered where I update the entity with auditing information.
#Component
public class EntitySaveListener implements PersistEventListener, MergeEventListener,
PreInsertEventListener {
private static final long serialVersionUID = 1L;
static final Logger logger = LoggerFactory
.getLogger(EntitySaveListener.class);
#Autowired
private LocalEntityManagerFactoryBean entityManagerFactory;
public EntitySaveListener() {
logger.info("EntitySaveListener created");
}
public void onPersist(PersistEvent event) throws HibernateException {
if (SecurityContextHolder.getContext() != null
&& SecurityContextHolder.getContext().getAuthentication() != null) {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal != null && principal instanceof V2VUserDetails) {
User user = ((V2VUserDetails) principal).getUser();
if (event.getObject() instanceof ModificationTracker &&
user != null) {
ModificationTracker entity = (ModificationTracker) event.getObject();
entity.setCreatedDate(new Date());
entity.setCreatedBy(user);
entity.setLastUpdated(new Date());
entity.setLastUpdatedBy(user);
}
}
}
}
#SuppressWarnings("rawtypes")
#Override
public void onPersist(PersistEvent event, Map arg1)
throws HibernateException {
// TODO Auto-generated method stub
}
#Override
public void onMerge(MergeEvent event) throws HibernateException {
if (SecurityContextHolder.getContext() != null
&& SecurityContextHolder.getContext().getAuthentication() != null) {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal != null && principal instanceof V2VUserDetails) {
User user = ((V2VUserDetails) principal).getUser();
if (event.getEntity() instanceof ModificationTracker
&& user != null) {
ModificationTracker entity = (ModificationTracker) event
.getEntity();
entity.setLastUpdated(new Date());
entity.setLastUpdatedBy(user);
}
}
}
}
#SuppressWarnings("rawtypes")
#Override
public void onMerge(MergeEvent arg0, Map arg1) throws HibernateException {
// TODO Auto-generated method stub
}
#Override
public boolean onPreInsert(PreInsertEvent arg0) {
// TODO Auto-generated method stub
return false;
}
}