我正在尝试用Spring创建一个预定的任务,但我可能没有正确地在配置中公开@Bean。我的代码如下:
@Configuration
@PropertySource("classpath:hibernate.properties")
@EnableJpaRepositories("org.app.repository")
@ComponentScan("org.app")
@EnableTransactionManagement
@EnableScheduling
public class JpaConfiguration {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN =
"entitymanager.packages.to.scan";
@Resource
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
// will set the provider to 'org.hibernate.ejb.HibernatePersistence'
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// will set hibernate.show_sql to 'true'
vendorAdapter.setShowSql(true);
// if set to true, will set hibernate.hbm2ddl.auto to 'update'
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean emfBean = new
LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource());
emfBean.setJpaVendorAdapter(vendorAdapter);
emfBean.setPersistenceProviderClass(
org.hibernate.jpa.HibernatePersistenceProvider.class);
emfBean.setPackagesToScan(
env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
emfBean.setJpaProperties(hibProperties());
return emfBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler ts = new ThreadPoolTaskScheduler();
ts.initialize();
ts.setPoolSize(8);
ts.setWaitForTasksToCompleteOnShutdown(true);
return ts;
}
}
@Component
public class MainBean {
@Autowired
private MyRunnable myRunnable;
@Autowired
private CategoryRepo categoryRepo;
@Autowired
private ThreadPoolTaskScheduler taskScheduler;
public void start() {
//This works
categoryRepo.findAll().forEach(System.out::println);
//this throws an exception
taskScheduler.execute(myRunnable);
//if i use an infinite loop here in order to prevent
//the method from exiting everything works normal
// while(true) {
// Thread.sleep(10000000);
// }
System.out.println("Application Started. . .");
}
}类别回购
public interface CategoryRepo extends JpaRepository<Category, String> {
}可运行
@Component
public class MyRunnable implements Runnable {
@Autowired
private CategoryRepo categoryRepo;
@Override
public void run() {
try {
List<Category> list = categoryRepo.findAll();
list.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
}
}
}另外,如果我不使用调度程序,我只需要
myRunnable.run(); 它正常执行。
有没有人知道我做错了什么,或者有别的办法做这件事?
编辑:我的pom.xml依赖关系如下(正如您在属性标记中看到的那样,Spring为4.0.2 ):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<!--Hibernate Dependencies-->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.3.Final</version>
</dependency>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<!--CGLIB is required to process @Configuration classes-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
<!--Other Dependencies-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
</dependency>
</dependencies>Java是1.8,也用1.7进行了测试,结果是一样的。
编辑:
显然,我认为问题在于,这个程序正在退出,它离开了Spring上下文。因此,在执行runnable时,线程找不到实体管理器。
如果我在MainBean退出之前使用了无限的while循环,那么一切都将正常执行。
发布于 2014-04-08 17:25:07
不幸的是,我没有找到令人满意的答案。我发现的唯一非正统解决方案(我认为)是执行一个不允许程序退出的无限循环,如下所示:
public void start() {
System.out.println("Application Started. . .");
taskScheduler.scheduleAtFixedRate(myRunnable, Date.from(Instant.now()),
TimeUnit.DAYS.toMillis(1));
while (true) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}发布于 2014-03-30 16:25:40
根本原因是
Caused by: java.lang.NoSuchMethodError: org.app.config.JpaConfiguration.setBeanFactory(Lorg/springframework/beans/factory/BeanFactory;)VNoSuchMethodError几乎总是表示您的构建存在版本控制问题。应用程序尝试执行在编译时可用的方法,但在运行时不执行。换句话说,编译时的类路径不同于运行时的类路径。
spring-data-jpa版本的1.5.1.RELEASE是用Spring3.2.8编译的,但是您提供的是4.0.2.RELEASE的Spring库。但是,它的构建方式将委托给项目的实际依赖项(如果存在的话)。在当前的设置中,它将使用以下内容
<artifactId>spring-context-support</artifactId>
<artifactId>spring-context</artifactId>
<artifactId>spring-jdbc</artifactId>
<artifactId>spring-orm</artifactId>
<artifactId>spring-tx</artifactId>与版本4.0.2.RELEASE一起使用,但它将使用
<artifactId>spring-core</artifactId>
<artifactId>spring-beans</artifactId>这些通常是具有相同版本的spring-context的依赖项,但在这里,它们似乎会被spring-data-jpa覆盖。
最简单但可能不完整的(取决于您配置的其余部分)是具体声明这两个依赖项。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>因此,spring-data-jpa现在将委托给这些人。
或者,除非您正在使用Spring4.0.2.RELEASE的一些特性,否则您可以消除所有其他的Spring依赖项,而只保留spring-data-jpa。它将负责提取其他Spring 3.2.8.RELEASE库。
发布于 2014-03-30 14:26:18
它似乎是spring引导或Spring 4. https://github.com/spring-projects/spring-boot/issues/253上已知的一个bug。
看起来,调度程序通过这个奇怪的错误掩盖了真正的问题。
在您的例子中,正如调度程序所发生的那样,我将尝试创建一个异常断点,以找出在这种情况下正在隐藏的异常被抛出的类型。
https://stackoverflow.com/questions/22745054
复制相似问题