【问题标题】:How to inject spring resources into Apache Ignite classes?如何将spring资源注入Apache Ignite类?
【发布时间】:2017-07-23 20:18:48
【问题描述】:

我在将 spring bean 注入某些 ignite 的类时遇到问题。我正在尝试创建这个:客户端-> Apache Ignite-> Spring-Data-> 数据库 也许是错的,我不确定。

所以,此时我的课程看起来像: 应用配置

@Configuration
@ComponentScan(basePackages = arrayOf("com.ignite.cache"))
open class AppConfiguration : Serializable {
    private val logger: Logger = Logger.getLogger(AppConfiguration::class.java)

    @Bean
    open fun igniteInstance(): Ignite {
        val cfg = IgniteConfiguration()

        cfg.igniteInstanceName = "springDataNode"

        cfg.isPeerClassLoadingEnabled = true


        var clientCache: CacheConfiguration<Long, Client> = CacheConfiguration("ClientCache")
        clientCache.apply {
            setIndexedTypes(Long::class.java, Client::class.java)
            setCacheStoreFactory(FactoryBuilder.factoryOf(ClientStore::class.java))
            isReadThrough = true
            isWriteThrough = true
        }

        cfg.setCacheConfiguration(clientCache)

        return Ignition.start(cfg)
    }
}

数据源配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = arrayOf("com.ignite.cache.model.repositories.springdatarepository"))
@EnableIgniteRepositories(basePackages = arrayOf("com.ignite.cache.model.repositories.igniterepository"))
@ComponentScan(basePackages = arrayOf("com.ignite.cache.model"))
open class DataSourceConfiguration : Serializable {

    @Bean
    open fun entityManagerFactory(): LocalContainerEntityManagerFactoryBean {
        var entityManagerFactory: LocalContainerEntityManagerFactoryBean = LocalContainerEntityManagerFactoryBean()

        entityManagerFactory.apply {
            dataSource = dataSource()
            setPackagesToScan("com.ignite.cache.model")

            var vendorAdapter: HibernateJpaVendorAdapter = HibernateJpaVendorAdapter()

            vendorAdapter.apply {
                setGenerateDdl(true)
                setShowSql(true)
            }

            var properties: Properties = Properties()

            properties.apply {
                put("database.dialet", "org.hibernate.dialect.PostgreSQL95Dialect")
                put("database.globally_quoted_identifiers", "false")
                put("database.enable_lazy_load_no_trans", "true")
                put("database.show_sql", "true")
            }

            jpaVendorAdapter = vendorAdapter
            setJpaProperties(properties)
        }

        return entityManagerFactory
    }

    @Bean
    open fun dataSource(): DataSource {
        var source: ComboPooledDataSource = ComboPooledDataSource()

        source.apply {
            driverClass = "org.postgresql.Driver"
            jdbcUrl = "jdbc:postgresql://localhost:5432/ignite"
            user = "postgres"
            password = "1111"
            acquireIncrement = 5
            idleConnectionTestPeriod = 60
            maxPoolSize = 20
            minPoolSize = 10
            initialPoolSize = 10
        }

        return source
    }

    @Bean
    open fun transactionManager() : PlatformTransactionManager {
        var manager: JpaTransactionManager = JpaTransactionManager()

        manager.apply {
            entityManagerFactory = entityManagerFactory().nativeEntityManagerFactory
        }

        return manager
    }

    @Bean
    open fun exceptionTranslator(): PersistenceExceptionTranslationPostProcessor = PersistenceExceptionTranslationPostProcessor()
}

实体:

@Entity
@Table(name = "client")
data class Client
(
        @Id
        @Column(name = "id")
        @GeneratedValue(generator = "increment")
        @GenericGenerator(name = "increment", strategy = "increment")
        var id: Long = 0,
        @Column(name = "email", nullable = false, unique = true)
        var email: String = "",
        @Column(name = "login", nullable = false, unique = true)
        var login: String = ""
) : Serializable

存储库:

@RepositoryConfig(cacheName = "ClientCache")
interface IgniteClientRepository : IgniteRepository<Client, Long> {
}
@Repository
interface ClientRepository : CrudRepository<Client, Long>

服务类和 CacheStore 的标准实现:

public class ClientStore implements CacheStore<Long, Client>, Serializable {
    private Logger logger = Logger.getLogger(ClientStore.class);

    @SpringResource
    private IClientService clientRepository; // <- error is here (NPE)

    @Override
    public void loadCache(IgniteBiInClosure<Long, Client> igniteBiInClosure, @Nullable Object... objects) throws CacheLoaderException {
        Iterable<Client> clients = clientRepository.findAll();

        for(Client client : clients) {
            igniteBiInClosure.apply(client.getId(), client);
        }
    }
...
}

主要:

public class Main {
    private static Logger logger = Logger.getLogger(Main.class);

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class, DataSourceConfiguration.class);
        Ignite ignite = context.getBean(Ignite.class);

        (ignite.getOrCreateCache("ClientCache")).loadCache(null);

        IgniteClientRepository clientRepository = context.getBean(IgniteClientRepository.class);

        Iterable<Client> clients = clientRepository.findAll();
        for(Client client : clients) {
            logger.info(client);
        }

        logger.info("Finish");
    }
}

但是当我尝试将一些数据从数据库加载到缓存中时,我收到错误 NPE:

Exception in thread "main" javax.cache.integration.CacheLoaderException: java.lang.NullPointerException
    at org.apache.ignite.internal.processors.cache.store.GridCacheStoreManagerAdapter.loadCache(GridCacheStoreManagerAdapter.java:528)
    at org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter.localLoadCache(GridDhtCacheAdapter.java:486)
    at org.apache.ignite.internal.processors.cache.GridCacheProxyImpl.localLoadCache(GridCacheProxyImpl.java:217)
    at org.apache.ignite.internal.processors.cache.GridCacheAdapter$LoadCacheJob.localExecute(GridCacheAdapter.java:5439)
    at org.apache.ignite.internal.processors.cache.GridCacheAdapter$LoadCacheJobV2.localExecute(GridCacheAdapter.java:5488)
    at org.apache.ignite.internal.processors.cache.GridCacheAdapter$TopologyVersionAwareJob.execute(GridCacheAdapter.java:6103)
    at org.apache.ignite.compute.ComputeJobAdapter.call(ComputeJobAdapter.java:132)
    at org.apache.ignite.internal.processors.closure.GridClosureProcessor$C2.execute(GridClosureProcessor.java:1842)
    at org.apache.ignite.internal.processors.job.GridJobWorker$2.call(GridJobWorker.java:566)
    at org.apache.ignite.internal.util.IgniteUtils.wrapThreadLoader(IgniteUtils.java:6621)
    at org.apache.ignite.internal.processors.job.GridJobWorker.execute0(GridJobWorker.java:560)
    at org.apache.ignite.internal.processors.job.GridJobWorker.body(GridJobWorker.java:489)
    at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
    at org.apache.ignite.internal.processors.job.GridJobProcessor.processJobExecuteRequest(GridJobProcessor.java:1114)
    at org.apache.ignite.internal.processors.task.GridTaskWorker.sendRequest(GridTaskWorker.java:1379)
    at org.apache.ignite.internal.processors.task.GridTaskWorker.processMappedJobs(GridTaskWorker.java:640)
    at org.apache.ignite.internal.processors.task.GridTaskWorker.body(GridTaskWorker.java:532)
    at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
    at org.apache.ignite.internal.processors.task.GridTaskProcessor.startTask(GridTaskProcessor.java:743)
    at org.apache.ignite.internal.processors.task.GridTaskProcessor.execute(GridTaskProcessor.java:443)
    at org.apache.ignite.internal.processors.closure.GridClosureProcessor.callAsync(GridClosureProcessor.java:447)
    at org.apache.ignite.internal.processors.closure.GridClosureProcessor.callAsync(GridClosureProcessor.java:418)
    at org.apache.ignite.internal.processors.closure.GridClosureProcessor.callAsync(GridClosureProcessor.java:402)
    at org.apache.ignite.internal.processors.cache.GridCacheAdapter.globalLoadCacheAsync(GridCacheAdapter.java:3681)
    at org.apache.ignite.internal.processors.cache.GridCacheAdapter.globalLoadCache(GridCacheAdapter.java:3657)
    at org.apache.ignite.internal.processors.cache.IgniteCacheProxy.loadCache(IgniteCacheProxy.java:387)
    at com.ignite.cache.Main.main(Main.java:22)
Caused by: java.lang.NullPointerException
    at com.ignite.cache.model.service.ClientStore.loadCache(ClientStore.java:30)
    at org.apache.ignite.internal.processors.cache.store.GridCacheStoreManagerAdapter.loadCache(GridCacheStoreManagerAdapter.java:502)
    ... 26 more

我仍然无法弄清楚为什么我的客户端服务没有注入到 CacheStore 类中。也许我应该使用 xml 配置而不是 java-class 配置来点燃?

【问题讨论】:

  • 您使用 Java 标记了问题,但您的大部分代码不是 Java。
  • 您指出的行不可能抛出 NPE。 Main 的第 22 行是哪一行?
  • @JensSchauder 是的,如果是我的错的话。编程语言是 kotlin 和一些 java。 main 中的第 22 行是(ignite.getOrCreateCache("ClientCache")).loadCache(null);(另外几行已被评论,我删除了它们,抱歉误导)

标签: spring spring-data spring-data-jpa kotlin ignite


【解决方案1】:

当您使用 Ignition#startIgniteConfiguration 对象启动 Ignite 时,它​​根本不知道 Spring 上下文。您需要使用 IgniteSpring#start 方法来显式提供上下文。另一种选择是利用已经实现ApplicationContextAwareIgniteSpringBean 并正确启动Ignite 实例。

另请注意,您需要将 bean 名称或 bean 类作为参数提供给 @SpringResource 注释。

【讨论】:

  • 谢谢!我还想通了,ignite 不知道 spring 上下文,但我不知道 IgniteSpring.start(...)!
【解决方案2】:

我不知道 Ignite,也不知道您使用的编程语言,但看起来 Ignite 而不是 Spring 正在创建您的 ClientStore 实例。因此,您需要手动注入依赖项。

我不太熟悉那里使用的 FactoryBuilder,因此如果您可以使用带参数的构造函数甚至 lambda,可能会有很好的解决方案,但如果这不起作用,您可以将存储库的引用存储在静态字段并在 ClientStore 的构造函数中从那里获取它。

【讨论】:

  • 问题是 ignite 创建了自己的 spring 上下文,而我的应用程序也创建了另一个上下文,当我尝试将 ClientService 注入 ClientStore 时,ignite 的上下文没有看到它的任何实现(这就是我想出的全部)。当我为 ignite 创建一个 xml 配置并在那里声明 bean 时,它工作正常,直到我需要无法创建的 ClientRepository。
猜你喜欢
  • 2013-04-05
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多