提交 881b548c 编写于 作者: N Nikita Koksharov

Feature - Quarkus extension for Redis #3530

上级 7c3a4bf4
......@@ -22,6 +22,7 @@
<javadoc.version>8</javadoc.version>
<release.version>8</release.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<scm>
......@@ -60,6 +61,7 @@
<module>redisson-mybatis</module>
<module>redisson-hibernate</module>
<module>redisson-helidon</module>
<module>redisson-quarkus</module>
</modules>
<profiles>
......
# Quarkus extension for Redis
Integrates Redisson with [Quarkus](https://quarkus.io/) framework.
Supports Quarkus 1.6.x - 2.0.x
## Usage
### 1. Add `redisson-quarkus` dependency into your project:
Maven
```xml
<dependency>
<groupId>org.redisson</groupId>
<!-- for Quarkus v1.6.x - v1.13.x -->
<artifactId>redisson-quarkus-16</artifactId>
<!-- for Quarkus v2.0.x -->
<artifactId>redisson-quarkus-20</artifactId>
<version>3.16.0</version>
</dependency>
```
Gradle
```groovy
// for Quarkus v1.6.x - v1.13.x
compile 'org.redisson:redisson-quarkus-16:3.16.0'
// for Quarkus v2.0.x
compile 'org.redisson:redisson-quarkus-20:3.16.0'
```
### 2. Add settings into `application.properties` file
Config structure is a flat Redisson YAML configuration -
[single mode](https://github.com/redisson/redisson/wiki/2.-Configuration#262-single-instance-yaml-config-format),
[replicated mode](https://github.com/redisson/redisson/wiki/2.-Configuration#252-replicated-yaml-config-format),
[cluster mode](https://github.com/redisson/redisson/wiki/2.-Configuration#242-cluster-yaml-config-format),
[sentinel mode](https://github.com/redisson/redisson/wiki/2.-Configuration#272-sentinel-yaml-config-format),
[proxy mode](https://github.com/redisson/redisson/wiki/2.-Configuration#292-proxy-mode-yaml-config-format)
NOTE: Setting names in camel case should be joined with hyphens (-).
Below is the configuration for Redisson in single mode.
```
quarkus.redisson.single-server-config.address=redis://localhost:6379
quarkus.redisson.single-server-config.password=null
quarkus.redisson.threads=16
quarkus.redisson.netty-threads=32
```
### 3. Use Redisson
```java
@Inject
RedissonClient redisson;
```
Consider __[Redisson PRO](https://redisson.pro)__ version for **ultra-fast performance** and **support by SLA**.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus</artifactId>
<packaging>pom</packaging>
<name>Redisson/Quarkus integration</name>
<modules>
<module>redisson-quarkus-16</module>
<module>redisson-quarkus-20</module>
</modules>
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
<failsafe-plugin.version>${surefire-plugin.version}</failsafe-plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
<maven.repo>${settings.localRepository}</maven.repo>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
<maven.repo>${settings.localRepository}</maven.repo>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-16-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-16-deployment</artifactId>
<name>Redisson/Quarkus v1.6.x - 1.13.x deployment</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-16</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
package io.quarkus.redisson.client.deployment;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.redisson.client.runtime.RedissonClientProducer;
import io.quarkus.redisson.client.runtime.RedissonClientRecorder;
import io.quarkus.runtime.Quarkus;
import org.eclipse.microprofile.config.ConfigProvider;
import org.redisson.config.PropertiesConvertor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
/**
*
* @author Nikita Koksharov
*
*/
class QuarkusRedissonClientProcessor {
private static final String FEATURE = "redisson";
@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}
@BuildStep
ExtensionSslNativeSupportBuildItem sslNativeSupport() {
return new ExtensionSslNativeSupportBuildItem(FEATURE);
}
@BuildStep
AdditionalBeanBuildItem addProducer() {
return AdditionalBeanBuildItem.unremovableOf(RedissonClientProducer.class);
}
@BuildStep
void addConfig(BuildProducer<NativeImageResourceBuildItem> nativeResources,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles,
BuildProducer<RuntimeInitializedClassBuildItem> staticItems,
BuildProducer<ReflectiveClassBuildItem> reflectiveItems) {
nativeResources.produce(new NativeImageResourceBuildItem("redisson.yaml"));
nativeResources.produce(new NativeImageResourceBuildItem("META-INF/services/org.jboss.marshalling.ProviderDescriptor"));
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("redisson.yaml"));
if (Quarkus.class.getPackage().getImplementationVersion().startsWith("1.")) {
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhost4LazyHolder"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhost6LazyHolder"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhostLazyHolder"));
}
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.HostsFileEntriesResolver"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DnsNameResolver"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder"));
reflectiveItems.produce(new ReflectiveClassBuildItem(false, false, "org.redisson.codec.MarshallingCodec"));
reflectiveItems.produce(new ReflectiveClassBuildItem(false, false, "org.jboss.marshalling.river.RiverProviderDescriptor"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, false, "org.redisson.executor.RemoteExecutorService"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, false, "org.redisson.executor.RemoteExecutorServiceAsync"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.Config"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.BaseConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.BaseMasterSlaveServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.SingleServerConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.ReplicatedServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.SentinelServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.ClusterServersConfig"));
}
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
RedissonClientItemBuild build(RedissonClientRecorder recorder) throws IOException {
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("redisson.yaml");
if (stream != null) {
byte[] array = new byte[stream.available()];
stream.read(array);
recorder.configureRedisson(new String(array, StandardCharsets.UTF_8));
} else {
String yaml = PropertiesConvertor.toYaml("quarkus.redisson.", ConfigProvider.getConfig().getPropertyNames(), prop -> {
return ConfigProvider.getConfig().getValue(prop, String.class);
});
recorder.configureRedisson(yaml);
}
return new RedissonClientItemBuild();
}
}
package io.quarkus.redisson.client.deployment;
import io.quarkus.builder.item.SimpleBuildItem;
/**
* @author Nikita Koksharov
*/
public final class RedissonClientItemBuild extends SimpleBuildItem {
}
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-16-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-16-integration-tests</artifactId>
<name>Redisson/Quarkus v1.6.x - 1.13.x integration Tests</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-16</artifactId>
<version>${project.version}</version>
</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>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${native.surefire.skip}</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
<quarkus.native.additional-build-args>--allow-incomplete-classpath</quarkus.native.additional-build-args>
</properties>
</profile>
</profiles>
</project>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson.quarkus.client.it;
import org.redisson.api.*;
import org.redisson.api.redisnode.RedisNodes;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@Path("/quarkus-redisson-client")
public class QuarkusRedissonClientResource {
@Inject
RedissonClient redisson;
@GET
@Path("/map")
public String map() {
RMap<String, Integer> m = redisson.getMap("test");
m.put("1", 2);
return m.get("1").toString();
}
@GET
@Path("/pingAll")
public String pingAll() {
redisson.getRedisNodes(RedisNodes.SINGLE).pingAll();
return "OK";
}
@GET
@Path("/executeTask")
public String executeTask() throws ExecutionException, InterruptedException {
RScheduledExecutorService t = redisson.getExecutorService("test");
t.registerWorkers(WorkerOptions.defaults());
RExecutorFuture<String> r = t.submit(new Task());
return r.get();
}
}
package org.redisson.quarkus.client.it;
import java.io.Serializable;
import java.util.concurrent.Callable;
/**
* @author Nikita Koksharov
*/
public class Task implements Callable<String>, Serializable {
@Override
public String call() throws Exception {
return "hello";
}
}
quarkus.redisson.single-server-config.address=redis://localhost:6379
quarkus.redisson.single-server-config.password=null
#quarkus.redisson.cluster-servers-config.nodeAddresses=redis://127.0.0.1:7004,redis://127.0.0.1:7001
#quarkus.redisson.cluster-servers-config.password=null
quarkus.redisson.threads=16
quarkus.redisson.codec=org.redisson.codec.MarshallingCodec
\ No newline at end of file
package org.redisson.quarkus.client.it;
import io.quarkus.test.junit.NativeImageTest;
@NativeImageTest
public class NativeQuarkusRedissonClientResourceIT extends QuarkusRedissonClientResourceTest {
}
package org.redisson.quarkus.client.it;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class QuarkusRedissonClientResourceTest {
@Test
public void testMap() {
given()
.when().get("/quarkus-redisson-client/map")
.then()
.statusCode(200)
.body(is("2"));
}
@Test
public void testPingAll() {
given()
.when().get("/quarkus-redisson-client/pingAll")
.then()
.statusCode(200)
.body(is("OK"));
}
// @Test
// public void testExecuteTask() {
// given()
// .when().get("/quarkus-redisson-client/executeTask")
// .then()
// .statusCode(200)
// .body(is("hello"));
// }
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-16-parent</artifactId>
<packaging>pom</packaging>
<name>Redisson/Quarkus v1.6.x - 1.13.x integration</name>
<modules>
<module>deployment</module>
<module>runtime</module>
<module>integration-tests</module>
</modules>
<properties>
<quarkus.version>1.13.6.Final</quarkus.version>
</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>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-16-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-16</artifactId>
<name>Redisson/Quarkus v1.6.x - 1.13.x runtime</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>extension-descriptor</goal>
</goals>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
package io.quarkus.redisson.client.runtime;
import io.quarkus.arc.DefaultBean;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Singleton;
import java.io.IOException;
/**
*
* @author Nikita Koksharov
*
*/
@ApplicationScoped
public class RedissonClientProducer {
private String config;
private RedissonClient redisson;
@Produces
@Singleton
@DefaultBean
public RedissonClient create() throws IOException {
if (config != null){
Config c = Config.fromYAML(config);
redisson = Redisson.create(c);
} else {
redisson = Redisson.create();
}
return redisson;
}
public void setConfig(String config) {
this.config = config;
}
@PreDestroy
public void close() {
if (redisson != null) {
redisson.shutdown();
}
}
}
package io.quarkus.redisson.client.runtime;
import io.quarkus.arc.Arc;
import io.quarkus.runtime.annotations.Recorder;
/**
*
* @author Nikita Koksharov
*
*/
@Recorder
public class RedissonClientRecorder {
public void configureRedisson(String config) {
RedissonClientProducer producer = Arc.container().instance(RedissonClientProducer.class).get();
producer.setConfig(config);
}
}
package io.quarkus.redisson.client.runtime;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import java.util.Map;
import java.util.Optional;
/**
*
* @author Nikita Koksharov
*
*/
//@ConfigRoot(name = "redisson", phase = ConfigPhase.RUN_TIME)
public class RedissonConfig {
/**
* Redis uri
*/
// @ConfigItem
public Optional<String> codec;
/**
* Redis cluster config
*/
// @ConfigItem
public Optional<Map<String, String>> clusterServersConfig;
}
package io.quarkus.redisson.client.runtime.graal;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import java.lang.reflect.AnnotatedElement;
@TargetClass(className = "net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType$OfFormalTypeVariable")
final class OfFormalTypeVariableSubstitute {
@Substitute
public AnnotatedElement resolve() {
return null;
}
}
@TargetClass(className = "net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType")
final class ForTypeVariableBoundTypeSubstitute {
@Substitute
protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
return null;
}
}
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.quarkus.redisson.client.runtime.graal;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.util.NetUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SocketUtils;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.quarkus.runtime.Quarkus;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.function.BooleanSupplier;
@TargetClass(InternetProtocolFamily.class)
final class InternetProtocolFamilySubstitutions {
@Substitute
public InetAddress localhost() {
if (toString().equals("IPv4")) {
return NetUtil.LOCALHOST4;
} else if (toString().equals("IPv6")) {
return NetUtil.LOCALHOST6;
} else {
throw new IllegalStateException("Unsupported internet protocol family: " + this);
}
}
}
final class Quarkus1Condition implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
System.out.println("getAsBoolean " + Quarkus.class.getPackage().getImplementationVersion());
return Quarkus.class.getPackage().getImplementationVersion().startsWith("1.");
}
}
@TargetClass(value = NetUtil.class, onlyWith = Quarkus1Condition.class)
final class NetUtilSubstitutions {
private NetUtilSubstitutions() {
}
@Alias
@InjectAccessors(NetUtilLocalhost4Accessor.class)
public static Inet4Address LOCALHOST4;
@Alias
@InjectAccessors(NetUtilLocalhost6Accessor.class)
public static Inet6Address LOCALHOST6;
@Alias
@InjectAccessors(NetUtilLocalhostAccessor.class)
public static InetAddress LOCALHOST;
private static final class NetUtilLocalhost4Accessor {
static Inet4Address get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhost4LazyHolder.LOCALHOST4;
}
static void set(Inet4Address ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhost4LazyHolder {
private static final Inet4Address LOCALHOST4 = NetUtilInitializations.createLocalhost4();
}
private static final class NetUtilLocalhost6Accessor {
static Inet6Address get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhost6LazyHolder.LOCALHOST6;
}
static void set(Inet6Address ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhost6LazyHolder {
private static final Inet6Address LOCALHOST6 = NetUtilInitializations.createLocalhost6();
}
private static final class NetUtilLocalhostAccessor {
static InetAddress get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhostLazyHolder.LOCALHOST;
}
static void set(InetAddress ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhostLazyHolder {
private static final InetAddress LOCALHOST = NetUtilInitializations
.determineLoopback(NetUtilLocalhost4LazyHolder.LOCALHOST4, NetUtilLocalhost6LazyHolder.LOCALHOST6)
.address();
}
}
final class NetUtilInitializations {
/**
* The logger being used by this class
*/
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NetUtilInitializations.class);
private NetUtilInitializations() {
}
static Inet4Address createLocalhost4() {
byte[] LOCALHOST4_BYTES = {127, 0, 0, 1};
Inet4Address localhost4 = null;
try {
localhost4 = (Inet4Address) InetAddress.getByAddress("localhost", LOCALHOST4_BYTES);
} catch (Exception e) {
// We should not get here as long as the length of the address is correct.
PlatformDependent.throwException(e);
}
return localhost4;
}
static Inet6Address createLocalhost6() {
byte[] LOCALHOST6_BYTES = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
Inet6Address localhost6 = null;
try {
localhost6 = (Inet6Address) InetAddress.getByAddress("localhost", LOCALHOST6_BYTES);
} catch (Exception e) {
// We should not get here as long as the length of the address is correct.
PlatformDependent.throwException(e);
}
return localhost6;
}
static NetworkIfaceAndInetAddress determineLoopback(Inet4Address localhost4, Inet6Address localhost6) {
// Retrieve the list of available network interfaces.
List<NetworkInterface> ifaces = new ArrayList<NetworkInterface>();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces != null) {
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
// Use the interface with proper INET addresses only.
if (SocketUtils.addressesFromNetworkInterface(iface).hasMoreElements()) {
ifaces.add(iface);
}
}
}
} catch (SocketException e) {
logger.warn("Failed to retrieve the list of available network interfaces", e);
}
// Find the first loopback interface available from its INET address (127.0.0.1 or ::1)
// Note that we do not use NetworkInterface.isLoopback() in the first place because it takes long time
// on a certain environment. (e.g. Windows with -Djava.net.preferIPv4Stack=true)
NetworkInterface loopbackIface = null;
InetAddress loopbackAddr = null;
loop: for (NetworkInterface iface: ifaces) {
for (Enumeration<InetAddress> i = SocketUtils.addressesFromNetworkInterface(iface); i.hasMoreElements();) {
InetAddress addr = i.nextElement();
if (addr.isLoopbackAddress()) {
// Found
loopbackIface = iface;
loopbackAddr = addr;
break loop;
}
}
}
// If failed to find the loopback interface from its INET address, fall back to isLoopback().
if (loopbackIface == null) {
try {
for (NetworkInterface iface: ifaces) {
if (iface.isLoopback()) {
Enumeration<InetAddress> i = SocketUtils.addressesFromNetworkInterface(iface);
if (i.hasMoreElements()) {
// Found the one with INET address.
loopbackIface = iface;
loopbackAddr = i.nextElement();
break;
}
}
}
if (loopbackIface == null) {
logger.warn("Failed to find the loopback interface");
}
} catch (SocketException e) {
logger.warn("Failed to find the loopback interface", e);
}
}
if (loopbackIface != null) {
// Found the loopback interface with an INET address.
logger.debug(
"Loopback interface: {} ({}, {})",
loopbackIface.getName(), loopbackIface.getDisplayName(), loopbackAddr.getHostAddress());
} else {
// Could not find the loopback interface, but we can't leave LOCALHOST as null.
// Use LOCALHOST6 or LOCALHOST4, preferably the IPv6 one.
if (loopbackAddr == null) {
try {
if (NetworkInterface.getByInetAddress(localhost6) != null) {
logger.debug("Using hard-coded IPv6 localhost address: {}", localhost6);
loopbackAddr = localhost6;
}
} catch (Exception e) {
// Ignore
} finally {
if (loopbackAddr == null) {
logger.debug("Using hard-coded IPv4 localhost address: {}", localhost4);
loopbackAddr = localhost4;
}
}
}
}
return new NetworkIfaceAndInetAddress(loopbackIface, loopbackAddr);
}
static final class NetworkIfaceAndInetAddress {
private final NetworkInterface iface;
private final InetAddress address;
NetworkIfaceAndInetAddress(NetworkInterface iface, InetAddress address) {
this.iface = iface;
this.address = address;
}
public NetworkInterface iface() {
return iface;
}
public InetAddress address() {
return address;
}
}
}
---
artifact: ${project.groupId}:${project.artifactId}:${project.version}
name: Quarkus Redisson extension
metadata:
keywords:
- "redis"
- "redis-client"
guide: "https://github.com/redisson/redisson/blob/master/redisson-quarkus/README.md"
categories:
- "data"
status: "preview"
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-20-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-20-deployment</artifactId>
<name>Redisson/Quarkus v2.0.x deployment</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-20</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
package io.quarkus.redisson.client.deployment;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.redisson.client.runtime.RedissonClientProducer;
import io.quarkus.redisson.client.runtime.RedissonClientRecorder;
import io.quarkus.runtime.Quarkus;
import org.eclipse.microprofile.config.ConfigProvider;
import org.redisson.config.PropertiesConvertor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
/**
*
* @author Nikita Koksharov
*
*/
class QuarkusRedissonClientProcessor {
private static final String FEATURE = "redisson";
@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}
@BuildStep
ExtensionSslNativeSupportBuildItem sslNativeSupport() {
return new ExtensionSslNativeSupportBuildItem(FEATURE);
}
@BuildStep
AdditionalBeanBuildItem addProducer() {
return AdditionalBeanBuildItem.unremovableOf(RedissonClientProducer.class);
}
@BuildStep
void addConfig(BuildProducer<NativeImageResourceBuildItem> nativeResources,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles,
BuildProducer<RuntimeInitializedClassBuildItem> staticItems,
BuildProducer<ReflectiveClassBuildItem> reflectiveItems) {
nativeResources.produce(new NativeImageResourceBuildItem("redisson.yaml"));
nativeResources.produce(new NativeImageResourceBuildItem("META-INF/services/org.jboss.marshalling.ProviderDescriptor"));
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("redisson.yaml"));
if (Quarkus.class.getPackage().getImplementationVersion().startsWith("1.")) {
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhost4LazyHolder"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhost6LazyHolder"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.quarkus.redisson.client.runtime.graal.NetUtilSubstitutions$NetUtilLocalhostLazyHolder"));
}
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.HostsFileEntriesResolver"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DnsNameResolver"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider"));
staticItems.produce(new RuntimeInitializedClassBuildItem("io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder"));
reflectiveItems.produce(new ReflectiveClassBuildItem(false, false, "org.redisson.codec.MarshallingCodec"));
reflectiveItems.produce(new ReflectiveClassBuildItem(false, false, "org.jboss.marshalling.river.RiverProviderDescriptor"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, false, "org.redisson.executor.RemoteExecutorService"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, false, "org.redisson.executor.RemoteExecutorServiceAsync"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.Config"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.BaseConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.BaseMasterSlaveServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.SingleServerConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.ReplicatedServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.SentinelServersConfig"));
reflectiveItems.produce(new ReflectiveClassBuildItem(true, true, "org.redisson.config.ClusterServersConfig"));
}
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
RedissonClientItemBuild build(RedissonClientRecorder recorder) throws IOException {
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("redisson.yaml");
if (stream != null) {
byte[] array = new byte[stream.available()];
stream.read(array);
recorder.configureRedisson(new String(array, StandardCharsets.UTF_8));
} else {
String yaml = PropertiesConvertor.toYaml("quarkus.redisson.", ConfigProvider.getConfig().getPropertyNames(), prop -> {
return ConfigProvider.getConfig().getValue(prop, String.class);
});
recorder.configureRedisson(yaml);
}
return new RedissonClientItemBuild();
}
}
package io.quarkus.redisson.client.deployment;
import io.quarkus.builder.item.SimpleBuildItem;
/**
* @author Nikita Koksharov
*/
public final class RedissonClientItemBuild extends SimpleBuildItem {
}
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-20-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-20-integration-tests</artifactId>
<name>Redisson/Quarkus v2.0.x integration Tests</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-20</artifactId>
<version>${project.version}</version>
</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>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${native.surefire.skip}</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
<quarkus.native.additional-build-args>--allow-incomplete-classpath</quarkus.native.additional-build-args>
</properties>
</profile>
</profiles>
</project>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson.quarkus.client.it;
import org.redisson.api.*;
import org.redisson.api.redisnode.RedisNodes;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@Path("/quarkus-redisson-client")
public class QuarkusRedissonClientResource {
@Inject
RedissonClient redisson;
@GET
@Path("/map")
public String map() {
RMap<String, Integer> m = redisson.getMap("test");
m.put("1", 2);
return m.get("1").toString();
}
@GET
@Path("/pingAll")
public String pingAll() {
redisson.getRedisNodes(RedisNodes.SINGLE).pingAll();
return "OK";
}
@GET
@Path("/executeTask")
public String executeTask() throws ExecutionException, InterruptedException {
RScheduledExecutorService t = redisson.getExecutorService("test");
t.registerWorkers(WorkerOptions.defaults());
RExecutorFuture<String> r = t.submit(new Task());
return r.get();
}
}
package org.redisson.quarkus.client.it;
import java.io.Serializable;
import java.util.concurrent.Callable;
/**
* @author Nikita Koksharov
*/
public class Task implements Callable<String>, Serializable {
@Override
public String call() throws Exception {
return "hello";
}
}
quarkus.redisson.single-server-config.address=redis://localhost:6379
quarkus.redisson.single-server-config.password=null
#quarkus.redisson.cluster-servers-config.nodeAddresses=redis://127.0.0.1:7004,redis://127.0.0.1:7001
#quarkus.redisson.cluster-servers-config.password=null
quarkus.redisson.threads=16
quarkus.redisson.codec=org.redisson.codec.MarshallingCodec
\ No newline at end of file
package org.redisson.quarkus.client.it;
import io.quarkus.test.junit.NativeImageTest;
@NativeImageTest
public class NativeQuarkusRedissonClientResourceIT extends QuarkusRedissonClientResourceTest {
}
package org.redisson.quarkus.client.it;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class QuarkusRedissonClientResourceTest {
@Test
public void testMap() {
given()
.when().get("/quarkus-redisson-client/map")
.then()
.statusCode(200)
.body(is("2"));
}
@Test
public void testPingAll() {
given()
.when().get("/quarkus-redisson-client/pingAll")
.then()
.statusCode(200)
.body(is("OK"));
}
// @Test
// public void testExecuteTask() {
// given()
// .when().get("/quarkus-redisson-client/executeTask")
// .then()
// .statusCode(200)
// .body(is("hello"));
// }
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-20-parent</artifactId>
<packaging>pom</packaging>
<name>Redisson/Quarkus v2.0.x integration</name>
<modules>
<module>deployment</module>
<module>runtime</module>
<module>integration-tests</module>
</modules>
<properties>
<quarkus.version>2.0.0.CR3</quarkus.version>
</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>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<release>11</release>
<optimize>true</optimize>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>
<parent>
<groupId>org.redisson</groupId>
<artifactId>redisson-quarkus-20-parent</artifactId>
<version>3.15.7-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>redisson-quarkus-20</artifactId>
<name>Redisson/Quarkus v2.0.x runtime</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>extension-descriptor</goal>
</goals>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
package io.quarkus.redisson.client.runtime;
import io.quarkus.arc.DefaultBean;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Singleton;
import java.io.IOException;
/**
*
* @author Nikita Koksharov
*
*/
@ApplicationScoped
public class RedissonClientProducer {
private String config;
private RedissonClient redisson;
@Produces
@Singleton
@DefaultBean
public RedissonClient create() throws IOException {
if (config != null){
Config c = Config.fromYAML(config);
redisson = Redisson.create(c);
} else {
redisson = Redisson.create();
}
return redisson;
}
public void setConfig(String config) {
this.config = config;
}
@PreDestroy
public void close() {
if (redisson != null) {
redisson.shutdown();
}
}
}
package io.quarkus.redisson.client.runtime;
import io.quarkus.arc.Arc;
import io.quarkus.runtime.annotations.Recorder;
/**
*
* @author Nikita Koksharov
*
*/
@Recorder
public class RedissonClientRecorder {
public void configureRedisson(String config) {
RedissonClientProducer producer = Arc.container().instance(RedissonClientProducer.class).get();
producer.setConfig(config);
}
}
package io.quarkus.redisson.client.runtime;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import java.util.Map;
import java.util.Optional;
/**
*
* @author Nikita Koksharov
*
*/
//@ConfigRoot(name = "redisson", phase = ConfigPhase.RUN_TIME)
public class RedissonConfig {
/**
* Redis uri
*/
// @ConfigItem
public Optional<String> codec;
/**
* Redis cluster config
*/
// @ConfigItem
public Optional<Map<String, String>> clusterServersConfig;
}
package io.quarkus.redisson.client.runtime.graal;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import java.lang.reflect.AnnotatedElement;
@TargetClass(className = "net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType$OfFormalTypeVariable")
final class OfFormalTypeVariableSubstitute {
@Substitute
public AnnotatedElement resolve() {
return null;
}
}
@TargetClass(className = "net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType")
final class ForTypeVariableBoundTypeSubstitute {
@Substitute
protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
return null;
}
}
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.quarkus.redisson.client.runtime.graal;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.util.NetUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SocketUtils;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.quarkus.runtime.Quarkus;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.function.BooleanSupplier;
@TargetClass(InternetProtocolFamily.class)
final class InternetProtocolFamilySubstitutions {
@Substitute
public InetAddress localhost() {
if (toString().equals("IPv4")) {
return NetUtil.LOCALHOST4;
} else if (toString().equals("IPv6")) {
return NetUtil.LOCALHOST6;
} else {
throw new IllegalStateException("Unsupported internet protocol family: " + this);
}
}
}
final class Quarkus1Condition implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
System.out.println("getAsBoolean " + Quarkus.class.getPackage().getImplementationVersion());
return Quarkus.class.getPackage().getImplementationVersion().startsWith("1.");
}
}
@TargetClass(value = NetUtil.class, onlyWith = Quarkus1Condition.class)
final class NetUtilSubstitutions {
private NetUtilSubstitutions() {
}
@Alias
@InjectAccessors(NetUtilLocalhost4Accessor.class)
public static Inet4Address LOCALHOST4;
@Alias
@InjectAccessors(NetUtilLocalhost6Accessor.class)
public static Inet6Address LOCALHOST6;
@Alias
@InjectAccessors(NetUtilLocalhostAccessor.class)
public static InetAddress LOCALHOST;
private static final class NetUtilLocalhost4Accessor {
static Inet4Address get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhost4LazyHolder.LOCALHOST4;
}
static void set(Inet4Address ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhost4LazyHolder {
private static final Inet4Address LOCALHOST4 = NetUtilInitializations.createLocalhost4();
}
private static final class NetUtilLocalhost6Accessor {
static Inet6Address get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhost6LazyHolder.LOCALHOST6;
}
static void set(Inet6Address ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhost6LazyHolder {
private static final Inet6Address LOCALHOST6 = NetUtilInitializations.createLocalhost6();
}
private static final class NetUtilLocalhostAccessor {
static InetAddress get() {
// using https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
return NetUtilLocalhostLazyHolder.LOCALHOST;
}
static void set(InetAddress ignored) {
// a no-op setter to avoid exceptions when NetUtil is initialized at run-time
}
}
private static final class NetUtilLocalhostLazyHolder {
private static final InetAddress LOCALHOST = NetUtilInitializations
.determineLoopback(NetUtilLocalhost4LazyHolder.LOCALHOST4, NetUtilLocalhost6LazyHolder.LOCALHOST6)
.address();
}
}
final class NetUtilInitializations {
/**
* The logger being used by this class
*/
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NetUtilInitializations.class);
private NetUtilInitializations() {
}
static Inet4Address createLocalhost4() {
byte[] LOCALHOST4_BYTES = {127, 0, 0, 1};
Inet4Address localhost4 = null;
try {
localhost4 = (Inet4Address) InetAddress.getByAddress("localhost", LOCALHOST4_BYTES);
} catch (Exception e) {
// We should not get here as long as the length of the address is correct.
PlatformDependent.throwException(e);
}
return localhost4;
}
static Inet6Address createLocalhost6() {
byte[] LOCALHOST6_BYTES = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
Inet6Address localhost6 = null;
try {
localhost6 = (Inet6Address) InetAddress.getByAddress("localhost", LOCALHOST6_BYTES);
} catch (Exception e) {
// We should not get here as long as the length of the address is correct.
PlatformDependent.throwException(e);
}
return localhost6;
}
static NetworkIfaceAndInetAddress determineLoopback(Inet4Address localhost4, Inet6Address localhost6) {
// Retrieve the list of available network interfaces.
List<NetworkInterface> ifaces = new ArrayList<NetworkInterface>();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces != null) {
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
// Use the interface with proper INET addresses only.
if (SocketUtils.addressesFromNetworkInterface(iface).hasMoreElements()) {
ifaces.add(iface);
}
}
}
} catch (SocketException e) {
logger.warn("Failed to retrieve the list of available network interfaces", e);
}
// Find the first loopback interface available from its INET address (127.0.0.1 or ::1)
// Note that we do not use NetworkInterface.isLoopback() in the first place because it takes long time
// on a certain environment. (e.g. Windows with -Djava.net.preferIPv4Stack=true)
NetworkInterface loopbackIface = null;
InetAddress loopbackAddr = null;
loop: for (NetworkInterface iface: ifaces) {
for (Enumeration<InetAddress> i = SocketUtils.addressesFromNetworkInterface(iface); i.hasMoreElements();) {
InetAddress addr = i.nextElement();
if (addr.isLoopbackAddress()) {
// Found
loopbackIface = iface;
loopbackAddr = addr;
break loop;
}
}
}
// If failed to find the loopback interface from its INET address, fall back to isLoopback().
if (loopbackIface == null) {
try {
for (NetworkInterface iface: ifaces) {
if (iface.isLoopback()) {
Enumeration<InetAddress> i = SocketUtils.addressesFromNetworkInterface(iface);
if (i.hasMoreElements()) {
// Found the one with INET address.
loopbackIface = iface;
loopbackAddr = i.nextElement();
break;
}
}
}
if (loopbackIface == null) {
logger.warn("Failed to find the loopback interface");
}
} catch (SocketException e) {
logger.warn("Failed to find the loopback interface", e);
}
}
if (loopbackIface != null) {
// Found the loopback interface with an INET address.
logger.debug(
"Loopback interface: {} ({}, {})",
loopbackIface.getName(), loopbackIface.getDisplayName(), loopbackAddr.getHostAddress());
} else {
// Could not find the loopback interface, but we can't leave LOCALHOST as null.
// Use LOCALHOST6 or LOCALHOST4, preferably the IPv6 one.
if (loopbackAddr == null) {
try {
if (NetworkInterface.getByInetAddress(localhost6) != null) {
logger.debug("Using hard-coded IPv6 localhost address: {}", localhost6);
loopbackAddr = localhost6;
}
} catch (Exception e) {
// Ignore
} finally {
if (loopbackAddr == null) {
logger.debug("Using hard-coded IPv4 localhost address: {}", localhost4);
loopbackAddr = localhost4;
}
}
}
}
return new NetworkIfaceAndInetAddress(loopbackIface, loopbackAddr);
}
static final class NetworkIfaceAndInetAddress {
private final NetworkInterface iface;
private final InetAddress address;
NetworkIfaceAndInetAddress(NetworkInterface iface, InetAddress address) {
this.iface = iface;
this.address = address;
}
public NetworkInterface iface() {
return iface;
}
public InetAddress address() {
return address;
}
}
}
---
artifact: ${project.groupId}:${project.artifactId}:${project.version}
name: Quarkus Redisson extension
metadata:
keywords:
- "redis"
- "redis-client"
guide: "https://github.com/redisson/redisson/blob/master/redisson-quarkus/README.md"
categories:
- "data"
status: "preview"
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册