/ / Impossible d'utiliser la classe Repository de Spring Data jpa sur une méthode de classe dans Quartz, pourquoi ? - printemps, quartz-scheduler, spring-data-jpa

Impossible d'utiliser la classe Repository des données de printemps jpa sur une méthode de classe dans Quartz pourquoi? - spring, quartz-scheduler, spring-data-jpa

Je suis en développement multiple-jobs-in-quartz-spring-example qui est une combinaison de Spring + Quartz + Spring Data JPA. Je cherche à développer un code qui s'exécutera en 5 secondes, il atteindra la base de données et récupèrera un enregistrement de la base de données. Dans mon JobA.class, je ne reçois pas d'instance de CustomerRepository.java pourquoi ? C'est toujours nul et c'est pourquoi le code ne peut pas atteindre la base de données. S'il vous plaît guider comment résoudre ce problème?

Code source sur :http://www.github.com/test512/multiple-jobs-in-quartz-spring-example.gi​t.

JobA.java

@Service
public class JobA extends QuartzJobBean {

private CustomerRepository customerRepository = null;

@Autowired
public JobA(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
public JobA() { }

@Override
protected void executeInternal(JobExecutionContext executionContext) throws JobExecutionException {
System.out.println("~~~~~~~ Job A is runing ~~~~~~~~");
Trigger trigger = executionContext.getTrigger();
System.out.println(trigger.getPreviousFireTime());
System.out.println(trigger.getNextFireTime());
getCustomerList();
}

private List<Customer> getCustomerList(){
List<Customer> customers = customerRepository.findAll();
for (Customer customer : customers) {
System.out.println("------------------------------");
System.out.println("ID : "+customer.getId());
System.out.println("NAME : "+customer.getName());
System.out.println("STATUS : "+customer.getStatus());
}
return customers;
}
}

Customer.java

@Entity
@Table(name="customer")
public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Long id;

@Column(name="NAME")
private String name;

@Column(name="STATUS")
private String status;


public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

CustomerRepository.java

public interface CustomerRepository extends JpaRepository<Customer, Long>{

}

dataSourceContext.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:jdbc="http://www.springframework.org/schema/jdbc"
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.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

<context:property-placeholder location="classpath:database.properties"/>

<!-- <jdbc:initialize-database data-source="dataSource" enabled="true">
<jdbc:script location="classpath:db-schema.sql" />
<jdbc:script location="classpath:db-test-data.sql" />
</jdbc:initialize-database> -->

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${mysql.driver.class.name}" />
<property name="url" value="${mysql.url}" />
<property name="username" value="${mysql.username}" />
<property name="password" value="${mysql.username}" />
</bean>

<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="database" value="MYSQL"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes-->
<property name="packagesToScan" value="com.mkyong.*"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
</beans>

Spring-Quartz.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:repository="http://www.springframework.org/schema/data/repository"
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.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd">

<import resource="classpath:dataSourceContext.xml"/>

<jpa:repositories base-package="com.mkyong.repository" />
<context:component-scan base-package="com.mkyong.*" />
<context:annotation-config />

<bean id="jobA" class="com.mkyong.job.JobA" />
<bean id="jobB" class="com.mkyong.job.JobB" />
<bean id="jobC" class="com.mkyong.job.JobC" />
<bean id="autowiredA" class="com.mkyong.job.JobASpringBeanJobFactory" />

<!-- ~~~~~~~~~ Quartz Job ~~~~~~~~~~ -->
<bean name="JobA" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mkyong.job.JobA" />
</bean>

<bean name="JobB" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mkyong.job.JobB" />
</bean>

<bean name="JobC" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mkyong.job.JobC" />
</bean>

<!-- ~~~~~~~~~~~ Cron Trigger, run every 5 seconds ~~~~~~~~~~~~~ -->
<bean id="cronTriggerJobA" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="JobA" />
<property name="cronExpression" value="0/5 * * * * ?" />
</bean>

<bean id="cronTriggerJobB" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="JobB" />
<property name="cronExpression" value="0/5 * * * * ?" />
</bean>

<bean id="cronTriggerJobC" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="JobC" />
<property name="cronExpression" value="0/5 * * * * ?" />
</bean>

<!-- ~~~~~~~~~~~~~~~~  Scheduler bean Factory   ~~~~~~~~~~~~~~~~ -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="autowiredA"/>
<property name="triggers">
<list>
<ref bean="cronTriggerJobA" />
<!-- <ref bean="cronTriggerJobB" />
<ref bean="cronTriggerJobC" /> -->
</list>
</property>
</bean>
</beans>

JobASpringBeanJobFactory.java

public class JobASpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

private transient AutowireCapableBeanFactory beanFactory;

@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}

@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}

App.java

public class App {
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Quartz.xml");
}
}

entrer la description de l'image ici

Réponses:

0 pour la réponse № 1

En passant par le lien suivant http://codrspace.com/Khovansa/spring-quartz-with-a-database/ devrait aider.

Citant le lien ci-dessus,

Quartz crée une nouvelle instance de tâche sur chaqueinvocation. Cela signifie que les travaux Quartz ne sont pas des beans Spring réguliers et nous ne pouvons pas nous attendre à ce que la magie Spring prenne effet automatiquement (et "JobDetailFactoryBean" Spring n'est pas assez intelligent pour le faire pour nous). Nous devrons donc implémenter notre propre usine de tâches qui écraserait la SpringBeanJobFactory par défaut.

Il faut donc avoir un custom SpringBeanJobFactory par extending SpringBeanJobFactory & implementing ApplicationContextAware et enfin invoquer beanFactory.autowireBean(job)


0 pour la réponse № 2

Ouvrons la discussion ici maintenant. Et attendez-vous à ce que tous les experts soient guidés / aidés ici.

Dans l'exemple ci-dessus, j'ai modifié JobA.java class pour obtenir une instance de l'instance de référentiel CustomerRepository à l'aide de l'injection de constructeur comme ci-dessous :

@Service
public class JobA extends QuartzJobBean {

private CustomerRepository customerRepository = null;

@Autowired
public JobA(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
getCustomerList();
}
public JobA() { }

@Override
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("~~~~~~~ Job A is runing ~~~~~~~~");
}

private List<Customer> getCustomerList(){
List<Customer> customers = customerRepository.findAll();
for (Customer customer : customers) {
System.out.println("------------------------------");
System.out.println("ID : "+customer.getId());
System.out.println("NAME : "+customer.getName());
System.out.println("STATUS : "+customer.getStatus());
}
return customers;
}
}

Mais le problème est que lorsque nous utilisons l'instance customerRepository dans la méthode executeInternal(), cela l'annule pourquoi ? Pourquoi ? Si d'une manière ou d'une autre l'instance n'est pas annulée, nous avons terminé !!!!