在OSGi Blueprint中使用Camel JCachePolicy和Caffeine

ulydmbyx  于 12个月前  发布在  Apache
关注(0)|答案(1)|浏览(212)

我想在OSGi Blueprint中使用Caffeine缓存来应用camel-jcache路由策略。该策略允许使用缓存设施来封装Camel路由或路由的一部分,这确保路由策略中发生的任何事情的结果都将被缓存。考虑以下路由:

<route id="my-konfig">
    <from uri="direct:my-konfig"/>
    <policy ref="jCachePolicy">
        <toD uri="... some enrichment call..."/>
        <transform>
            ... expensive transformation...
        </transform>
    </policy>
</route>

字符集
然而,当我像这样向蓝图添加缓存配置时:

<reference id="cachingProvider" interface="javax.cache.spi.CachingProvider"/>
<bean id="caffeineCacheManager" factory-ref="cachingProvider" factory-method="getCacheManager"/>
<bean id="caffeineCache" factory-ref="caffeineCacheManager" factory-method="getCache">
    <!-- see src/main/resources/application.conf for cache expiration policy -->
    <argument value="konfig-cache"/>
</bean>
<bean id="jCachePolicy" class="org.apache.camel.component.jcache.policy.JCachePolicy">
    <property name="cache" ref="caffeineCache"/>
    <property name="keyExpression">
        <bean class="org.apache.camel.model.language.SimpleExpression">
            <property name="expression" value="${exchangeProperty.typNr}"/>
        </bean>
    </property>
</bean>


则蓝图束不能在BeanRecipe.setProperties处以NullPointerException开始。
我可以追踪到一个类加载器问题。我请求一个名为konfig-cache的缓存,但该缓存的配置位于bundle资源中的一个文件 application.conf 中(Typesafe Config中自定义配置的默认位置)。OSGi运行时无法使用默认的类加载器加载该文件。
我如何定义Caffeine的底层Typesafe Config应该使用的类加载器,以在Blueprint bundle的资源中定位配置文件?

  • pom.xml* 中的相关依赖:
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jsonpath</artifactId>
    <version>${camel.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jcache</artifactId>
    <version>${camel.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-caffeine</artifactId>
    <version>${camel.version}</version>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</g
    <artifactId>jcache</artifactId>
    <version>2.9.2</version>
</dependency>


在我的Karaf feature.xml 中:

<feature version="${camel.version}">camel-jcache</feature>
<feature version="${camel.version}">camel-caffeine</feature>
<bundle>mvn:com.github.ben-manes.caffeine/jcache/2.9.2</bundle>
<bundle>mvn:com.typesafe/config/1.4.2</bundle>


最后,我的 src/main/resources/application.conf

# Configuration for camel-caffeine in HOCON format
# see https://github.com/lightbend/config/blob/master/HOCON.md#hocon-human-optimized-config-object-notation
# see https://github.com/lightbend/config#standard-behavior
# see https://github.com/ben-manes/caffeine/blob/master/jcache/src/main/resources/reference.conf
# see example https://github.com/ben-manes/caffeine/blob/master/jcache/src/test/resources/application.conf
caffeine.jcache {

  konfig-cache {
    key-type = java.lang.String
    value-type = java.lang.Object

    # The eviction policy for automatically removing entries from the cache
    policy {
      # The expiration threshold before lazily evicting an entry. This single threshold is reset on
      # every operation where a duration is specified. As expected by the specification, if an entry
      # expires but is not accessed and no resource constraints force eviction, then the expired
      # entry remains in place.
      lazy-expiration {
        # The duration before a newly created entry is considered expired. If set to 0 then the
        # entry is considered to be already expired and will not be added to the cache. May be
        # a time duration or "eternal" to indicate no expiration.
        creation = 60m
        # The duration before a updated entry is considered expired. If set to 0 then the entry is
        # considered immediately expired. May be a time duration, null to indicate no change, or
        # "eternal" to indicate no expiration.
        update = 60m
        # The duration before a read of an entry is considered expired. If set to 0 then the entry
        # is considered immediately expired. May be a time duration, null to indicate no change, or
        # "eternal" to indicate no expiration.
        access = null
      }

      # The expiration thresholds before eagerly evicting an entry. These settings correspond to the
      # expiration supported natively by Caffeine where expired entries are collected during
      # maintenance operations.
      #eager-expiration {
      # Specifies that each entry should be automatically removed from the cache once a fixed
      # duration has elapsed after the entry's creation, or the most recent replacement of its
      # value. This setting cannot be combined with the variable configuration.
      #after-write = null

      # Specifies that each entry should be automatically removed from the cache once a fixed
      # duration has elapsed after the entry's creation, the most recent replacement of its value,
      # or its last read. Access time is reset by all cache read and write operation. This setting
      # cannot be combined with the variable configuration.
      #after-access = null

      # The expiry class to use when calculating the expiration time of cache entries. This
      # setting cannot be combined with after-write or after-access configurations.
      #variable = null
    }

    # The threshold before an entry is eligible to be automatically refreshed when the first stale
    # request for an entry occurs. This setting is honored only when combined with the
    # read-through configuration.
    #refresh {
    # Specifies that active entries are eligible for automatic refresh once a fixed duration has
    # elapsed after the entry's creation or the most recent replacement of its value.
    #after-write = 30s
    #}

    # The maximum bounding of the cache based upon its logical size
    maximum {
      # The maximum number of entries that can be held by the cache. This setting cannot be
      # combined with the weight configuration.
      size = 10
    }
  }
}

ccrfmcuu

ccrfmcuu1#

CaffeineCachingProvider允许将类加载器传递给CachingProvider.getCacheManager(URI uri, ClassLoader classLoader)
预期的URI只是CaffeineCachingProvider的URL CN。
现在来看看classloader。在OSGi blueprint中,我们可以确定blueprint bundle的classloader并将其传递给getCacheManager。blueprint规范定义了许多具有预定义引用名称的环境管理器,其中包括blueprint bundle本身,其名称为blueprintBundle。由于我们无论如何都要使用Camel,因此我们可以使用Camel的BundleDelegatingClassLoader来简化对bundle的classloader的访问:

<bean id="caffeineCacheManager" factory-ref="cachingProvider" factory-method="getCacheManager">
    <argument value="com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider"/>
    <argument>
        <bean class="org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader">
            <argument ref="blueprintBundle"/>
        </bean>
    </argument>
</bean>

字符集

相关问题