Link to home
Avatar of faihandhope
faihandhope

asked on

spring, quartz, jpa, hibernate

Hello experts, I hope you can help me.

I am using quartz to run jobs in a web application.  Works fine if the job is to just print "say hello", and will trigger every 5 seconds.

But when I modified the job, and added a call to the EntityManager service to get the data. It does not run at all.

Below is the code.  Also the applicatonContext.xml file where spring is referencing the job.

Any help, is appreciated.
My job is called TestQuartz.java
 
public class TestQuartz extends QuartzJobBean   {
	   private Collection<EmailEntity> emails;
	   private EmailEntity email;
                   	   private EmailService es;
 
	    public void setEs(EmailService es) {
		this.es = es;
	}
 
    protected void executeInternal(JobExecutionContext ctx)  throws JobExecutionException {
	//this does not work at all
   	emails = es.findAll(); 
   	if (emails.size() > 0) {
   		System.out.println("got data");
   	}
 
	 System.out.println("Hello from Spring and Quartz");
	  }
  }
 
 
applicatonContext.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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
    <bean
       class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
 
 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceSQL"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false"/>
                <property name="generateDdl" value="true"/>
             </bean>
        </property>
    </bean>
 
    <bean id="dataSourceSQL"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:hsql://localhost/xdb"/>
        <property name="username" value="sa"/>
     </bean>
 
    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
 
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="TestQuartz"/>
  <property name="jobDataAsMap">
    <map>
      <entry key="timeout" value="5"/>
      <entry key="es" value="com.vaannila.service.admin.EmailService"/>
    </map>
  </property>
</bean>
 
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <context:annotation-config/>
    <context:component-scan base-package="com.vaannila"/>
  </beans>

Open in new window

Avatar of Sathish David  Kumar N
Sathish David Kumar N
Flag of India image

is any erorr came??
can u paste  ur DAO also ??
Avatar of faihandhope
faihandhope

ASKER

no error in the console.

DAO is

/**
 * DAO for the domain object
 */
@Transactional
@Service
@SuppressWarnings("unchecked")
public class myServiceImpl extends ServiceParentImpl<myEntity>
    impljapEments myService {
      @Transactional(readOnly=true)
      @Override
      public List<myEntity> findAll() {
          return getjpaEntityManager().createQuery(
                "from myEntity").getResultList();
          }      
}

ServiceParentImpl class:

@Transactional
public abstract class ServiceParentImpl<T extends modelDriven> impljapEments ServiceParent<T>{

      private Class<?> entity;

      protected jpaEntityManager japEm;

      protected jpaEntityManager getjpaEntityManager() {
            return japEm;
      }

      @PersistenceContext
      public void setjpaEntityManager(jpaEntityManager japEm) {
            this.japEm = japEm;
      }

     public ServiceParentImpl() {
        Type type = getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType ptype = (ParameterizedType)type;
            Type[] t = ptype.getActualTypeArguments();
            if (t.length != 1) {
                throw new RuntimeException("Expected single T argument);
            }
            entity = (Class<?>)t[0];
        } else {

            throw new RuntimeException("Expected ParameterizedType);
        }
      }

       @Transactional(readOnly = true)
       public List<T> getRecords() {
        Query query = getjpaEntityManager().createQuery(
                "from " + entity.getSimpleName());
        return query.getResultList();
      }
     
         
}

<Edited by SouthMod 11/28/2009>

      
u where used collections in Controller calls

<<<<<<<<<   private Collection<EmailEntity> emails;


but in DAO u used as
List<T> check that .....

so that only the values are not coming to controller !!

I had tried that as well List<EmailEntity> emails = findAll();    but nothing works.

I think the problem is with the quartz (TestQuartz.java) not able to get the entitymanager injection.
Try moving the job execution logic to a separate bean, then using Spring's MethodInvokingJobDetailFactoryBean to call that method.  You might also want to surround your execution code with a try/catch block and log any exceptions before passing them on.  I've seen tasks die without any error messages because of uncaught exceptions that Spring/Quartz handle behind the scenes.  Something like below:
public class MyTask {
    private Collection<EmailEntity> emails;
    private EmailEntity email;
    private EmailService es;
 
    public void setEs(EmailService es) {
        this.es = es;
    }
 
    public void doWork() {
        try {
            emails = es.findAll();
            if (emails.size() > 0) {
                System.out.println("got data");
            }
            System.out.println("Hello from Spring and Quartz");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
applicatonContext.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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceSQL"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false"/>
                <property name="generateDdl" value="true"/>
             </bean>
        </property>
    </bean>
 
    <bean id="dataSourceSQL" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:hsql://localhost/xdb"/>
        <property name="username" value="sa"/>
    </bean>
 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
 
    <bean name="myTask" class="MyTask">
        <property name="es" ref="com.vaannila.service.admin.EmailService"/>
    </bean>
 
    <bean id="myTaskJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="myTask"/>
        <property name="targetMethod" value="doWork"/>
    </bean>
 
    <bean id="myTaskTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="myTaskJob"/>
        <property name="startDelay" value="5000"/>
        <property name="repeatInterval" value="5000"/>
    </bean>
 
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="myTaskTrigger"/>
            </list>
        </property>
    </bean>
 
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <context:annotation-config/>
    <context:component-scan base-package="com.vaannila"/>
  </beans>

Open in new window

I am sure that bcz of ur wrong  genric list using only ...

just  put  system.out.println in DAO... thats size will zero only its return !!

ur overridding from the base class thats in different generic list  and ur implemented is different generic  lsit check that clearly !!
I followed the instructions but it did not work.  I even removed the Service reference, just to see if
the job will be called regardless, the job now does not get called at all.

web.xml file has this entry

   <servlet>
        <servlet-name>QuartzInitializer</servlet-name>
        <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
        <init-param>
            <param-name>shutdown-on-unload</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
i didnt get u clearly !!
Clear ur workseace and run !!
I am now taking a different approach,

Since all the services get called fine within a struts action. I tried to do the job in a struts action, and then be called by the Schedular.

I followed these steps:  http://struts.apache.org/2.0.14/docs/how-can-we-schedule-quartz-jobs.html
but I can get it to compile.

I am giving up!
ASKER CERTIFIED SOLUTION
Avatar of faihandhope
faihandhope

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Can u post the code then we can also know that !!
Thanks ....
Here is the code:

package com.vaannila.util;

import com.vaannila.service.admin.EmailService;

public class MyJob extends QuartzJobBean {

   private String jobName;
   private HelloService service;

 
public void setService(HelloService service) {
      this.service = service;
}


   public void setJobName(String jobName) {
      this.jobName = jobName;
    }

@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {

        
       System.out.println("Quartz Job");  
   try {                  
          ApplicationContext appCtx = getApplicationContext(context);
          EmailService dao = (EmailService) appCtx.getBean("daoAccess");
          System.out.println(dao.findAll().size());
          
    }
    catch (Exception e) {
       e.printStackTrace();
   }
      
      System.out.println("job name is " + jobName);
      if (service == null) {
            System.out.println("No service found");      
      }
      else {
            System.out.println("Freakin Service found");
            service.sayHello();
      }
      }

      
private static final String APPLICATION_CONTEXT_KEY = "applicationContext";

private ApplicationContext getApplicationContext(JobExecutionContext context )
      throws Exception {
      ApplicationContext appCtx = null;
      appCtx = (ApplicationContext)context.getScheduler().getContext().get(APPLICATION_CONTEXT_KEY);
            
      
      if (appCtx == null) {
      throw new JobExecutionException(
      "No application context available in scheduler context for key \"" + APPLICATION_CONTEXT_KEY + "\"");
      }
      return appCtx;
}

}


spring xml file should have the following:

bean id="helloService" class="com.vaannila.util.HelloServiceImpl">
  <property name="greeting" value="hello bogus!" />
 </bean>
 <bean id="daoAccess" class="com.vaannila.service.admin.EmailServiceImpl" />
<bean name="myJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.vaannila.util.MyJob" />
<property name="jobDataAsMap">
<map>
<entry key="jobName" value="slowjob" />
  </map>
  </property>
  </bean>
 
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
  <ref bean="simpleTrigger" />
  </list>
  </property>
 <property name="schedulerContextAsMap">
<map>
  <entry key="service" value-ref="helloService" />
  </map>
  </property>
<property name="applicationContextSchedulerContextKey">
  <value>applicationContext</value>
  </property>
  </bean>
Ok Thanks ....
Its helpfull for me !!
Great. Thanks