简体   繁体   English

如何使用Quarkus解决Infinispan JCache拦截器中的异常“拦截器没有绑定”?

[英]How to solve exception “Interceptor has no bindings” in Infinispan JCache interceptors using Quarkus?

When using Infinispan Embedded and Infinispan jCache in Quarkus is throwed : 在Quarkus中使用Infinispan Embedded和Infinispan jCache时会抛出:

build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DefinitionException: Interceptor has no bindings: org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor 构建步骤io.quarkus.arc.deployment.ArcAnnotationProcessor#build抛出异常:javax.enterprise.inject.spi.DefinitionException:拦截器没有绑定:org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor

I tried to use hazelcast but with no success and the same problem. 我尝试使用hazelcast,但没有成功,也遇到了同样的问题。

My pom.xml: 我的pom.xml:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.foo</groupId>
    <artifactId>bar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <jersey-common.version>2.22.2</jersey-common.version>
        <javac.version>1.8.0-u20</javac.version>
        <surefire-plugin.version>2.22.0</surefire-plugin.version>
        <quarkus.version>0.14.0</quarkus.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <lombok.version>1.18.6</lombok.version>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-bom</artifactId>
                <version>${quarkus.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jsonb</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-smallrye-rest-client</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-smallrye-openapi</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-smallrye-opentracing</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit5</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.21</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>${jersey-common.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.google.errorprone</groupId>
            <artifactId>javac</artifactId>
            <version>${javac.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-smallrye-fault-tolerance</artifactId>
        </dependency>

        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-cdi-embedded</artifactId>
            <version>9.4.9.Final</version>
        </dependency>

        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-jcache</artifactId>
            <version>9.4.9.Final</version>
        </dependency>

        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
            <version>1.0.0</version>
        </dependency>


    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <uberJar>true</uberJar>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surefire-plugin.version}</version>
                <configuration>
                    <systemProperties>
                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                    </systemProperties>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>native</id>
            <activation>
                <property>
                    <name>native</name>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.quarkus</groupId>
                        <artifactId>quarkus-maven-plugin</artifactId>
                        <version>${quarkus.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>native-image</goal>
                                </goals>
                                <configuration>
                                    <enableHttpUrlHandler>true</enableHttpUrlHandler>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>${surefire-plugin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                                <configuration>
                                    <systemProperties>
                                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                                    </systemProperties>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

My service.java 我的service.java

@ApplicationScoped
public class Service  {

    @CacheResult
    public String getString(final String key) {

        return new String(key + " - " + System.currentTimeMillis());
    }
}

And when I try to start Quarkus with 当我尝试以以下方式启动Quarkus时

./mvnw compile quarkus:dev

Occours this Exception: 发生此异常:

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------------< com.foo:bar >----------------------------
[INFO] Building bar 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ bar ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ bar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 23 source files to /home/user/git/foo-bar/foo-bar-q/target/classes
[INFO] 
[INFO] --- quarkus-maven-plugin:0.14.0:dev (default-cli) @ bar ---
Listening for transport dt_socket at address: 5005
23:40:46,376 INFO  [io.qua.dep.QuarkusAugmentor] Beginning quarkus augmentation
23:40:46,627 INFO  [org.jbo.threads] JBoss Threads version 3.0.0.Alpha4
23:40:47,094 ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
    [error]: Build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DefinitionException: Interceptor has no bindings: org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor
    at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:137)
    at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:131)
    at io.quarkus.dev.DevModeMain.main(DevModeMain.java:84)
Caused by: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
    [error]: Build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DefinitionException: Interceptor has no bindings: org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor
    at io.quarkus.builder.Execution.run(Execution.java:124)
    at io.quarkus.builder.BuildExecutionBuilder.execute(BuildExecutionBuilder.java:137)
    at io.quarkus.deployment.QuarkusAugmentor.run(QuarkusAugmentor.java:108)
    at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:102)
    ... 2 more
Caused by: javax.enterprise.inject.spi.DefinitionException: Interceptor has no bindings: org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor
    at io.quarkus.arc.processor.Interceptors.createInterceptor(Interceptors.java:47)
    at io.quarkus.arc.processor.BeanDeployment.findInterceptors(BeanDeployment.java:719)
    at io.quarkus.arc.processor.BeanDeployment.<init>(BeanDeployment.java:133)
    at io.quarkus.arc.processor.BeanProcessor.process(BeanProcessor.java:150)
    at io.quarkus.arc.deployment.ArcAnnotationProcessor.build(ArcAnnotationProcessor.java:259)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:507)
    at io.quarkus.builder.BuildContext.run(BuildContext.java:414)
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1998)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1525)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1416)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:479)

So I think the problem is that javax.cache.annotation.CacheRemove itself is not an interceptor binding. 所以我认为问题是javax.cache.annotation.CacheRemove本身不是拦截器绑定。 It's additionaly registered by Infinispan JCache extension . 它另外由Infinispan JCache扩展注册。 However, Quarkus/ArC does not support CDI portable extensions and there is currently no way to register an arbitrary annotation as an interceptor binding. 但是,Quarkus / ArC不支持CDI便携式扩展,并且目前没有办法将任意注释注册为拦截器绑定。

I've created this Quarkus issue . 我已经创建了Quarkus问题

I know that is not the best way, but for now it is working. 我知道这不是最好的方法,但目前它正在起作用。

I was able to use the built-in cache in quarkus like this: 我能够像这样在quarkus中使用内置缓存:

Pom.xml 的pom.xml

    <properties>
        <quarkus.version>0.14.0</quarkus.version>
        <commons-jcs-jcache.version>2.2.1</commons-jcs-jcache.version>
        <hazelcast.version>3.12</hazelcast.version>
        <cache-api.version>1.0.0</cache-api.version>
    </properties>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-jcs-jcache</artifactId>
            <version>${commons-jcs-jcache.version}</version>
            <classifier>cdi</classifier>
        </dependency>
        <dependency>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast</artifactId>
            <version>${hazelcast.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
            <version>${cache-api.version}</version>
        </dependency>

A new annotation JCache: 新的批注JCache:

@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface JCache {

}

A new Interceptor extending JCache official class: 新的Interceptor扩展了JCache官方类:

(PS: That was the only way I could get the interceptor to work.) (PS:那是我可以使拦截器正常工作的唯一方法。)

import org.apache.commons.jcs.jcache.cdi.CacheResultInterceptor;

import javax.cache.annotation.CacheResult;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Interceptor
@JCache
@CacheResult
public class JCacheCacheResultInterceptor extends CacheResultInterceptor {

    @AroundInvoke
    public Object processRequest(final InvocationContext invocationContext) throws Throwable {

        return super.cache(invocationContext);
    }

}

I needed to create a producer so I could generate some dependencies. 我需要创建一个生产者,以便可以生成一些依赖项。

import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.map.eviction.LFUEvictionPolicy;
import org.apache.commons.jcs.jcache.cdi.CDIJCacheHelper;
import org.apache.commons.jcs.jcache.cdi.MakeJCacheCDIInterceptorFriendly;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

import static com.hazelcast.config.MaxSizeConfig.MaxSizePolicy.PER_NODE;

@ApplicationScoped
public class InMemoryCacheFactory {

    HazelcastInstance instance;

    // This setup is not workink! The cache never expires regardless of this setting
    @PostConstruct
    public void afterCreate() {

        final Config config = new Config();

        final LFUEvictionPolicy mapEvictionPolicy = new LFUEvictionPolicy();

        config.getMapConfig("default")
                .setTimeToLiveSeconds(5)
                .setMaxIdleSeconds(10)
                .setMapEvictionPolicy(mapEvictionPolicy)
                .getMaxSizeConfig().setMaxSizePolicy(PER_NODE)
                .setSize(10000);

        this.instance = Hazelcast.newHazelcastInstance(config);
    }

    @PreDestroy
    public void beforeDestroy() {

        if(this.instance != null) {
            this.instance.shutdown();
        }
    }

    @Produces
    @ApplicationScoped
    public HazelcastInstance getInstance() {

        return this.instance;
    }

    @Produces
    public MakeJCacheCDIInterceptorFriendly getMakeJCacheCDIInterceptorFriendly() {

        return new MakeJCacheCDIInterceptorFriendly();
    }

    @Produces
    public CDIJCacheHelper getCDIJCacheHelper() {

        return new CDIJCacheHelper();
    }
}

Using cache: 使用缓存:

(Only works with the two annotations: @JCache and @CacheResult) (仅适用于两个注释:@JCache和@CacheResult)


import com.foo.bar.JCache;
import org.apache.commons.collections.CollectionUtils;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import javax.annotation.PostConstruct;
import javax.cache.annotation.CacheDefaults;
import javax.cache.annotation.CacheResult;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.stream.Collectors;

@ApplicationScoped
@CacheDefaults(cacheName = "default")
public class FooService {

    @JCache
    @CacheResult
    public List<String> getList() {

        System.out.println("Not using the cache...");

        List<String> strings = Arrays.asList("foo", "bar", "baz");

        return strings;
    }
}

Some points: 一些要点:

  • The cache works, but causes Quarkus hot reload to stop working in DEV mode. 缓存可以工作,但是会导致Quarkus热重装停止在DEV模式下工作。
  • The setup in InMemoryCacheFactory class at the method afterCreate is not working. 无法使用afterCreate方法在InMemoryCacheFactory类中进行设置。 The cache is never expiring! 缓存永不过期!
  • To avoid to having to use the custom JCache and JCacheCacheResultInterceptor classes, I tried to register CDI extension of JCS JCache with no success like the sample below: 为了避免不得不使用自定义JCache和JCacheCacheResultInterceptor类,我尝试注册JCS JCache的CDI扩展没有成功,如下例所示:
@BuildStep
void setupResourceInjection(BuildProducer<ResourceAnnotationBuildItem> resourceAnnotations, BuildProducer<GeneratedResourceBuildItem> resources) {
    resources.produce(new GeneratedResourceBuildItem("META-INF/services/io.quarkus.arc.ResourceReferenceProvider",
        JPAResourceReferenceProvider.class.getName().getBytes()));
    resourceAnnotations.produce(new ResourceAnnotationBuildItem(DotName.createSimple(PersistenceContext.class.getName())));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM