首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹簧计划任务

弹簧计划任务
EN

Stack Overflow用户
提问于 2014-03-30 14:17:44
回答 3查看 3.1K关注 0票数 2

我正在尝试用Spring创建一个预定的任务,但我可能没有正确地在配置中公开@Bean。我的代码如下:

代码语言:javascript
复制
@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. . .");
    }
}

类别回购

代码语言:javascript
复制
public interface CategoryRepo extends JpaRepository<Category, String> {

}

可运行

代码语言:javascript
复制
@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();
        }
    }
}

另外,如果我不使用调度程序,我只需要

代码语言:javascript
复制
myRunnable.run(); 

它正常执行。

有没有人知道我做错了什么,或者有别的办法做这件事?

编辑:我的pom.xml依赖关系如下(正如您在属性标记中看到的那样,Spring为4.0.2 ):

代码语言:javascript
复制
    <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循环,那么一切都将正常执行。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-08 17:25:07

不幸的是,我没有找到令人满意的答案。我发现的唯一非正统解决方案(我认为)是执行一个不允许程序退出的无限循环,如下所示:

代码语言:javascript
复制
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();
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2014-03-30 16:25:40

根本原因是

代码语言:javascript
复制
Caused by: java.lang.NoSuchMethodError: org.app.config.JpaConfiguration.setBeanFactory(Lorg/springframework/beans/factory/BeanFactory;)V

NoSuchMethodError几乎总是表示您的构建存在版本控制问题。应用程序尝试执行在编译时可用的方法,但在运行时不执行。换句话说,编译时的类路径不同于运行时的类路径。

spring-data-jpa版本的1.5.1.RELEASE是用Spring3.2.8编译的,但是您提供的是4.0.2.RELEASE的Spring库。但是,它的构建方式将委托给项目的实际依赖项(如果存在的话)。在当前的设置中,它将使用以下内容

代码语言:javascript
复制
<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一起使用,但它将使用

代码语言:javascript
复制
<artifactId>spring-core</artifactId>
<artifactId>spring-beans</artifactId>

这些通常是具有相同版本的spring-context的依赖项,但在这里,它们似乎会被spring-data-jpa覆盖。

最简单但可能不完整的(取决于您配置的其余部分)是具体声明这两个依赖项。

代码语言:javascript
复制
<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库。

票数 2
EN

Stack Overflow用户

发布于 2014-03-30 14:26:18

它似乎是spring引导或Spring 4. https://github.com/spring-projects/spring-boot/issues/253上已知的一个bug。

看起来,调度程序通过这个奇怪的错误掩盖了真正的问题。

在您的例子中,正如调度程序所发生的那样,我将尝试创建一个异常断点,以找出在这种情况下正在隐藏的异常被抛出的类型。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22745054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档