Merge branch 'master' of github.com:redisson/redisson

pull/812/head
Nikita 8 years ago
commit 22cd446d85

@ -147,30 +147,35 @@
<artifactId>lz4</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>jackson-dataformat-msgpack</artifactId>
<version>0.8.11</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<version>1.1.2.6</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>2.47</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>3.0.3</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@ -198,51 +203,60 @@
<artifactId>jackson-dataformat-cbor</artifactId>
<version>2.8.7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-smile</artifactId>
<version>2.8.7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-avro</artifactId>
<version>2.8.7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.openhft</groupId>
<artifactId>zero-allocation-hashing</artifactId>
<version>0.7</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.6.8</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-bean</artifactId>
<version>3.7.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>[3.1,)</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>[3.1,)</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.2.2.RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
@ -428,6 +442,7 @@
<useDefaultExcludes>true</useDefaultExcludes>
<mapping>
<java>JAVADOC_STYLE</java>
<xsd>XML_STYLE</xsd>
</mapping>
<strictCheck>true</strictCheck>
<useDefaultMapping>true</useDefaultMapping>

@ -357,7 +357,13 @@ public class Redisson implements RedissonClient {
}
@Override
@Deprecated
public RScheduledExecutorService getExecutorService(Codec codec, String name) {
return getExecutorService(name, codec);
}
@Override
public RScheduledExecutorService getExecutorService(String name, Codec codec) {
return new RedissonExecutorService(codec, connectionManager.getCommandExecutor(), this, name);
}

@ -742,12 +742,28 @@ public interface RedissonClient {
* Returns ScheduledExecutorService by name
* using provided codec for task, response and request serialization
*
* Please use getExecutorService(String name, Codec codec) method instead.
*
* @deprecated - use {@link #getExecutorService(String, Codec)} instead.
*
* @param name - name of object
* @param codec - codec for task, response and request
* @return ScheduledExecutorService object
*/
@Deprecated
RScheduledExecutorService getExecutorService(Codec codec, String name);
/**
* Returns ScheduledExecutorService by name
* using provided codec for task, response and request serialization
*
* @param name - name of object
* @param codec - codec for task, response and request
* @return ScheduledExecutorService object
* @since 2.8.2
*/
RScheduledExecutorService getExecutorService(String name, Codec codec);
/**
* Returns object for remote operations prefixed with the default name (redisson_remote_service)
*

@ -0,0 +1,44 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.misc;
import java.lang.reflect.InvocationTargetException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class BeanMethodInvoker extends ArgumentConvertingMethodInvoker
implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
prepare();
try {
invoke();
} catch (InvocationTargetException ex) {
if (ex.getTargetException() instanceof Exception) {
throw (Exception) ex.getTargetException();
}
if (ex.getTargetException() instanceof Error) {
throw (Error) ex.getTargetException();
}
throw ex;
}
}
}

@ -0,0 +1,84 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public abstract class AbstractRedissonNamespaceDefinitionParser
extends AbstractSingleBeanDefinitionParser {
protected final RedissonNamespaceParserSupport helper;
private final RedissonNamespaceDecorator decorator;
private final String parentRefAttribute;
protected AbstractRedissonNamespaceDefinitionParser(RedissonNamespaceParserSupport helper, String parentRefAttribute) {
this.helper = helper;
this.parentRefAttribute = parentRefAttribute;
this.decorator = new RedissonNamespaceDefaultDecorator();
}
public AbstractRedissonNamespaceDefinitionParser(RedissonNamespaceParserSupport helper, String parentRefAttribute, RedissonNamespaceDecorator decorator) {
this.helper = helper;
this.parentRefAttribute = parentRefAttribute;
this.decorator = decorator;
}
@Override
protected final void doParse(Element element, BeanDefinitionBuilder builder) {
}
@Override
protected final void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
Assert.state(helper.isRedissonNS(element),
"Illegal state. "
+ this.getClass().getName()
+ " can only parse "
+ RedissonNamespaceParserSupport.REDISSON_NAMESPACE
+ " namespace elements");
Assert.state(element.hasAttribute(parentRefAttribute),
"Illegal state. property \"" + parentRefAttribute
+ "\" is required in the \""
+ helper.getName(element)
+ "\" element.");
helper.populateIdAttribute(element, builder, parserContext);
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
parseNested(element, parserContext, builder, bd);
decorator.decorate(element, parserContext, builder, helper);
parserContext.getDelegate().parseQualifierElements(element, bd);
if (parserContext.isNested()) {
helper.registerBeanDefinition(builder, element, parserContext);
}
}
protected abstract void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd);
@Override
protected final boolean shouldGenerateIdAsFallback() {
return true;
}
}

@ -0,0 +1,44 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.api.RQueue;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class DelayedQueueDecorator implements RedissonNamespaceDecorator {
private static final String DESTINATION_QUEUE_REF = "destination-queue-ref";
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
Assert.state(element.hasAttribute(DESTINATION_QUEUE_REF),
"Illegal state. property \"" + DESTINATION_QUEUE_REF
+ "\" is required in the \""
+ helper.getName(element)
+ "\" element.");
helper.addConstructorArgs(new RuntimeBeanReference(
helper.getAttribute(element, DESTINATION_QUEUE_REF)),
RQueue.class, builder);
}
}

@ -0,0 +1,95 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.api.LocalCachedMapOptions;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.util.Assert;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class LocalCachedMapOptionsDecorator implements RedissonNamespaceDecorator {
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
NodeList list = element.getElementsByTagNameNS(
RedissonNamespaceParserSupport.REDISSON_NAMESPACE,
RedissonNamespaceParserSupport.LOCAL_CACHED_MAP_OPTIONS_ELEMENT);
Element options = null;
String id;
if (list.getLength() == 1) {
options = (Element) list.item(0);
id = invokeOptions(options, parserContext, helper);
for (int i = 0; i < options.getAttributes().getLength(); i++) {
Attr item = (Attr) options.getAttributes().item(i);
if (helper.isEligibleAttribute(item)
&& !RedissonNamespaceParserSupport.TIME_TO_LIVE_UNIT_ATTRIBUTE
.equals(item.getLocalName())
&& !RedissonNamespaceParserSupport.MAX_IDLE_UNIT_ATTRIBUTE
.equals(item.getLocalName())) {
helper.invoker(id,
helper.getName(item),
new Object[]{item.getValue()},
parserContext);
}
}
invokeTimeUnitOptions(options, id, parserContext, helper,
RedissonNamespaceParserSupport.TIME_TO_LIVE_ATTRIBUTE,
RedissonNamespaceParserSupport.TIME_TO_LIVE_UNIT_ATTRIBUTE);
invokeTimeUnitOptions(options, id, parserContext, helper,
RedissonNamespaceParserSupport.MAX_IDLE_ATTRIBUTE,
RedissonNamespaceParserSupport.MAX_IDLE_UNIT_ATTRIBUTE);
} else {
id = invokeOptions(options, parserContext, helper);
}
helper.addConstructorArgs(new RuntimeBeanReference(id),
LocalCachedMapOptions.class, builder);
}
private String invokeOptions(Element element, ParserContext parserContext, RedissonNamespaceParserSupport helper) {
BeanComponentDefinition defaultOption
= helper.factoryInvoker(element, LocalCachedMapOptions.class,
"defaults", null, parserContext);
return defaultOption.getName();
}
private void invokeTimeUnitOptions(Element element, String id, ParserContext parserContext, RedissonNamespaceParserSupport helper, String timeAttrubute, String timeUnitAttribute) {
if (helper.hasAttribute(element, timeUnitAttribute)) {
Assert.state(
helper.hasAttribute(element, timeAttrubute),
"Missing \"" + timeAttrubute + "\" attribute in \""
+ RedissonNamespaceParserSupport.LOCAL_CACHED_MAP_OPTIONS_ELEMENT
+ "\" element.");
helper.invoker(id,
Conventions.attributeNameToPropertyName(timeAttrubute),
new Object[]{
Integer.parseInt(
helper.getAttribute(element, timeAttrubute)),
helper.getAttribute(element, timeUnitAttribute)},
parserContext);
}
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class ReadWriteLockDecorator implements RedissonNamespaceDecorator {
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
parseNested(element, RedissonNamespaceParserSupport.READ_LOCK_ELEMENT, parserContext, builder, helper);
parseNested(element, RedissonNamespaceParserSupport.WRITE_LOCK_ELEMENT, parserContext, builder, helper);
}
private void parseNested(Element element, String eltType, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
NodeList list = element.getElementsByTagNameNS(
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, eltType);
if (list.getLength() == 1) {
Element elt = (Element) list.item(0);
helper.setAttribute(elt, RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE,
helper.getAttribute(element,
RedissonNamespaceParserSupport.ID_ATTRIBUTE));
parserContext.getDelegate()
.parseCustomElement(elt, builder.getRawBeanDefinition());
}
}
}

@ -0,0 +1,78 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.client.RedisClient;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public final class RedisDefinitionParser
extends AbstractSimpleBeanDefinitionParser {
private static final String HOST_ATTRIBUTE = "host";
private static final String PORT_ATTRIBUTE = "port";
private static final String CONNECTION_TIMEOUT_ATTRIBUTE = "connectionTimeout";
private static final String COMMAND_TIMEOUT_ATTRIBUTE = "commandTimeout";
private final RedissonNamespaceParserSupport helper;
public RedisDefinitionParser(RedissonNamespaceParserSupport helper) {
this.helper = helper;
}
@Override
protected Class<RedisClient> getBeanClass(Element element) {
return RedisClient.class;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
builder.getRawBeanDefinition().setBeanClass(RedisClient.class);
helper.addConstructorArgs(element,
HOST_ATTRIBUTE, String.class, builder);
helper.addConstructorArgs(element,
PORT_ATTRIBUTE, int.class, builder);
helper.addConstructorArgs(element,
CONNECTION_TIMEOUT_ATTRIBUTE, int.class, builder);
helper.addConstructorArgs(element,
COMMAND_TIMEOUT_ATTRIBUTE, int.class, builder);
builder.setDestroyMethodName("shutdown");
parserContext.getDelegate().parseQualifierElements(element,
builder.getRawBeanDefinition());
}
@Override
protected boolean shouldGenerateIdAsFallback() {
return true;
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return helper.isEligibleAttribute(attributeName);
}
@Override
protected boolean isEligibleAttribute(Attr attribute, ParserContext parserContext) {
return helper.isEligibleAttribute(attribute);
}
}

@ -0,0 +1,203 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import java.util.List;
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public final class RedissonDefinitionParser
implements BeanDefinitionParser {
public static final String ID_ATTRIBUTE = "id";
public static final String NAME_ATTRIBUTE = "name";
private static final String REF_SUFFIX = "-ref";
private static final String REDISSON_REF = "redisson-ref";
static enum ConfigType {
singleServer,
sentinelServers,
replicatedServers,
masterSlaveServers,
clusterServers;
public static boolean contains(String type) {
try {
valueOf(type);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
static enum AddressType {
slaveAddress,
sentinelAddress,
nodeAddress;
public static boolean contains(String type) {
try {
valueOf(type);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
private final RedissonNamespaceParserSupport helper;
RedissonDefinitionParser(RedissonNamespaceParserSupport helper) {
this.helper = helper;
}
private void parseChildElements(Element element, String parentId, String redissonRef, ParserContext parserContext) {
if (element.hasChildNodes()) {
CompositeComponentDefinition compositeDef
= new CompositeComponentDefinition(parentId,
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt : childElts) {
if(BeanDefinitionParserDelegate
.QUALIFIER_ELEMENT.equals(elt.getLocalName())) {
continue;//parsed elsewhere
}
String localName = parserContext.getDelegate().getLocalName(elt);
localName = Conventions.attributeNameToPropertyName(localName);
if (ConfigType.contains(localName)) {
parseConfigTypes(elt, localName, parserContext);
} else if (AddressType.contains(localName)) {
parseAddressTypes(elt, localName, parserContext);
} else if (helper.isRedissonNS(elt)) {
elt.setAttribute(REDISSON_REF, redissonRef);
parserContext.getDelegate().parseCustomElement(elt);
}
}
parserContext.popContainingComponent();
}
}
private void parseConfigTypes(Element element, String configType, ParserContext parserContext) {
BeanDefinitionBuilder builder
= helper.createBeanDefinitionBuilder(element,
parserContext, null);
//Use factory method on the Config bean
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
bd.setFactoryMethodName("use" + StringUtils.capitalize(configType));
bd.setFactoryBeanName(parserContext.getContainingComponent().getName());
String id = parserContext.getReaderContext().generateBeanName(bd);
helper.registerBeanDefinition(builder, id,
helper.parseAliase(element), parserContext);
parseAttributes(element, parserContext, builder);
parseChildElements(element, id, null, parserContext);
parserContext.getDelegate().parseQualifierElements(element, bd);
}
private void parseAddressTypes(Element element, String addressType, ParserContext parserContext) {
helper.invoker(element,
parserContext.getContainingComponent().getName(),
"add" + StringUtils.capitalize(addressType),
new String[]{element.getAttribute("value")},
parserContext);
}
private void parseAttributes(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
NamedNodeMap attributes = element.getAttributes();
for (int x = 0; x < attributes.getLength(); x++) {
Attr attribute = (Attr) attributes.item(x);
if (helper.isEligibleAttribute(attribute)) {
String propertyName
= attribute.getLocalName().endsWith(REF_SUFFIX)
? attribute.getLocalName()
.substring(0, attribute.getLocalName()
.length() - REF_SUFFIX.length())
: attribute.getLocalName();
propertyName = Conventions
.attributeNameToPropertyName(propertyName);
Assert.state(StringUtils.hasText(propertyName),
"Illegal property name returned from"
+ " 'extractPropertyName(String)': cannot be"
+ " null or empty.");
if (attribute.getLocalName().endsWith(REF_SUFFIX)) {
builder.addPropertyReference(propertyName,
attribute.getValue());
} else {
String value = attribute.getValue();
String localName = parserContext.getDelegate()
.getLocalName(element);
localName = Conventions
.attributeNameToPropertyName(localName);
if ("masterAddress".equals(propertyName)
&& ConfigType.masterSlaveServers.name()
.equals(localName)) {
value = "redis://" + value;
}
builder.addPropertyValue(propertyName, value);
}
}
}
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
//Sort out the Config Class
BeanDefinitionBuilder configBuilder
= helper.createBeanDefinitionBuilder(element, parserContext,
Config.class);
String configId = helper.getId(null, configBuilder, parserContext);
parseAttributes(element, parserContext, configBuilder);
helper.registerBeanDefinition(configBuilder, configId,
null, parserContext);
//Do the main Redisson bean
BeanDefinitionBuilder builder
= helper.createBeanDefinitionBuilder(element, parserContext,
Redisson.class);
builder.setFactoryMethod("create");
builder.setDestroyMethodName("shutdown");
builder.addConstructorArgReference(configId);
parserContext.getDelegate().parseQualifierElements(element,
builder.getRawBeanDefinition());
String id = helper.getId(element, builder, parserContext);
parseAttributes(element, parserContext, configBuilder);
//Sort out all the nested elements
parseChildElements(element, configId, id, parserContext);
helper.registerBeanDefinition(builder, id,
helper.parseAliase(element), parserContext);
return builder.getBeanDefinition();
}
}

@ -0,0 +1,90 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.api.RDestroyable;
import org.redisson.client.codec.Codec;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonGenericObjectDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
private final static String KEY_ATTRIBUTE = "key";
private final static String TOPIC_ATTRIBUTE = "topic";
private final static String PATTERN_ATTRIBUTE = "pattern";
private final static String SERVICE_ATTRIBUTE = "service";
private final static String CODEC_REF_ATTRIBUTE = "codec-ref";
private final static String FAIL_LOCK = "fairLock";
RedissonGenericObjectDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper, RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE);
}
RedissonGenericObjectDefinitionParser(RedissonNamespaceParserSupport helper, RedissonNamespaceDecorator decorator) {
super(helper,
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
decorator);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
bd.setFactoryBeanName(element.getAttribute(
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
String typeName
= Conventions.attributeNameToPropertyName(element.getLocalName());
bd.setFactoryMethodName("get" + StringUtils.capitalize(typeName));
helper.addConstructorArgs(element, KEY_ATTRIBUTE,
String.class, builder);
helper.addConstructorArgs(element, TOPIC_ATTRIBUTE,
String.class, builder);
helper.addConstructorArgs(element, PATTERN_ATTRIBUTE,
String.class, builder);
helper.addConstructorArgs(element, SERVICE_ATTRIBUTE,
String.class, builder);
helper.addConstructorArgs(element, CODEC_REF_ATTRIBUTE,
Codec.class, builder);
if (RDestroyable.class.isAssignableFrom(getBeanClass(element))) {
((AbstractBeanDefinition) bd).setDestroyMethodName("destroy");
}
}
@Override
protected Class<?> getBeanClass(Element element) {
String elementName
= Conventions.attributeNameToPropertyName(
element.getLocalName());
try {
return Class.forName(RedissonNamespaceParserSupport.API_CLASS_PATH_PREFIX
+ (StringUtils.capitalize(FAIL_LOCK.equals(elementName)
? "lock"
: elementName)));
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(ex);
}
}
}

@ -0,0 +1,87 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import reactor.core.support.Assert;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonLiveObjectDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonLiveObjectDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper, RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
Class<?> apiClass;
try {
apiClass = Class.forName(helper.getAttribute(element,
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE));
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
"The class [" + helper.getAttribute(element,
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE)
+ "] specified in \"api-class\" attribute has not "
+ "found. Please check the class path.", ex);
}
Assert.state(helper.hasAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE)
|| helper.hasAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE),
"One of \""
+ RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE
+ "\" or \""
+ RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE
+ "\" attribute is required in the \""
+ RedissonNamespaceParserSupport.LIVE_OBJECT_ELEMENT
+ "\" element.");
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE)));
builder.addPropertyValue("targetMethod", "get");
ManagedList args = new ManagedList();
args.add(apiClass);
if (helper.hasAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE)) {
args.add(helper.getAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE));
}
if (helper.hasAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE)) {
args.add(new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE)));
}
builder.addPropertyValue("arguments", args);
}
@Override
protected Class<?> getBeanClass(Element element) {
return MethodInvokingFactoryBean.class;
}
}

@ -0,0 +1,62 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.spring.misc.BeanMethodInvoker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonLiveObjectRegistrationDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonLiveObjectRegistrationDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper,
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
Class<?> apiClass;
try {
apiClass = Class.forName(helper.getAttribute(element,
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE));
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
"The class [" + helper.getAttribute(element,
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE)
+ "] specified in \"api-class\" attribute has not "
+ "found. Please check the class path.", ex);
}
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE)));
builder.addPropertyValue("targetMethod", "registerClass");
builder.addPropertyValue("arguments", new Object[] {apiClass});
}
@Override
protected Class<?> getBeanClass(Element element) {
return BeanMethodInvoker.class;
}
}

@ -0,0 +1,103 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonMultiLockDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonMultiLockDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper,
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
bd.setDependsOn(element.getAttribute(
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
bd.setLazyInit(true);
List<Element> childElements = DomUtils.getChildElements(element);
for (Element elt : childElements) {
String localName = elt.getLocalName();
if (BeanDefinitionParserDelegate
.QUALIFIER_ELEMENT.equals(localName)) {
continue;//parsed elsewhere
}
String id;
if (BeanDefinitionParserDelegate.REF_ELEMENT.equals(localName)){
id = elt.getAttribute(
BeanDefinitionParserDelegate.BEAN_REF_ATTRIBUTE);
} else {
if (!elt.hasAttribute(
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE)) {
helper.setAttribute(elt,
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
element.getAttribute(
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
}
helper.populateIdAttribute(elt, builder, parserContext);
parserContext.getDelegate().parseCustomElement(elt, bd);
id = elt.getAttribute(
RedissonNamespaceParserSupport.ID_ATTRIBUTE);
}
ConstructorArgumentValues args
= builder.getRawBeanDefinition()
.getConstructorArgumentValues();
if (args.getArgumentCount() > 0) {
ConstructorArgumentValues.ValueHolder value
= args.getIndexedArgumentValues().get(0);
ManagedList list;
if (value.getValue() instanceof ManagedList) {
list = (ManagedList) value.getValue();
} else {
list = new ManagedList();
list.add(value.getValue());
value.setValue(list);
value.setType(ManagedList.class.getName());
}
list.add(new RuntimeBeanReference(id));
} else {
builder.addConstructorArgReference(id);
}
}
}
@Override
protected String getBeanClassName(Element element) {
String elementName
= Conventions.attributeNameToPropertyName(
element.getLocalName());
return RedissonNamespaceParserSupport.IMPL_CLASS_PATH_PREFIX
+ StringUtils.capitalize(elementName);
}
}

@ -0,0 +1,29 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public interface RedissonNamespaceDecorator {
void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper);
}

@ -0,0 +1,33 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonNamespaceDefaultDecorator implements RedissonNamespaceDecorator {
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
//default is no decoration;
}
}

@ -0,0 +1,144 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonNamespaceHandlerSupport extends NamespaceHandlerSupport {
@Override
public void init() {
RedissonNamespaceParserSupport helper
= new RedissonNamespaceParserSupport();
RedissonGenericObjectDefinitionParser defaultParser
= new RedissonGenericObjectDefinitionParser(helper);
RedissonReadAndWriteLockDefinitionParser readAndWriteLockParser
= new RedissonReadAndWriteLockDefinitionParser(helper);
RedissonMultiLockDefinitionParser nestedParser
= new RedissonMultiLockDefinitionParser(helper);
RedissonNestedElementAwareDecorator readWriteLockDecorator
= new RedissonNestedElementAwareDecorator(
new String[]{
RedissonNamespaceParserSupport.READ_LOCK_ELEMENT,
RedissonNamespaceParserSupport.WRITE_LOCK_ELEMENT
},
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE);
RedissonGenericObjectDefinitionParser readWriteLockParser
= new RedissonGenericObjectDefinitionParser(helper,
readWriteLockDecorator);
RedissonNestedElementAwareDecorator remoteServiceDecorator
= new RedissonNestedElementAwareDecorator(
new String[]{
RedissonNamespaceParserSupport.RPC_SERVER_ELEMENT,
RedissonNamespaceParserSupport.RPC_CLIENT_ELEMENT
},
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE);
RedissonGenericObjectDefinitionParser remoteServiceParser
= new RedissonGenericObjectDefinitionParser(helper,
remoteServiceDecorator);
RedissonNestedElementAwareDecorator liveObjectServiceDecorator
= new RedissonNestedElementAwareDecorator(
new String[]{
RedissonNamespaceParserSupport.LIVE_OBJECT_ELEMENT,
RedissonNamespaceParserSupport.LIVE_OBJECT_REGISTRATION_ELEMENT
},
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
RedissonGenericObjectDefinitionParser liveObjectServiceParser
= new RedissonGenericObjectDefinitionParser(helper,
liveObjectServiceDecorator);
//root beans
registerBeanDefinitionParser("client",
new RedissonDefinitionParser(helper));
registerBeanDefinitionParser("redis", new RedisDefinitionParser(helper));
//object parsers
registerBeanDefinitionParser("binary-stream", defaultParser);
registerBeanDefinitionParser("geo", defaultParser);
registerBeanDefinitionParser("set-cache", defaultParser);
registerBeanDefinitionParser("map-cache", defaultParser);
registerBeanDefinitionParser("bucket", defaultParser);
registerBeanDefinitionParser("buckets", defaultParser);
registerBeanDefinitionParser("hyper-log-log", defaultParser);
registerBeanDefinitionParser("list", defaultParser);
registerBeanDefinitionParser("list-multimap", defaultParser);
registerBeanDefinitionParser("list-multimap-cache", defaultParser);
registerBeanDefinitionParser("local-cached-map",
new RedissonGenericObjectDefinitionParser(helper,
new LocalCachedMapOptionsDecorator()));
registerBeanDefinitionParser("map", defaultParser);
registerBeanDefinitionParser("set-multimap", defaultParser);
registerBeanDefinitionParser("set-multimap-cache", defaultParser);
registerBeanDefinitionParser("semaphore", defaultParser);
registerBeanDefinitionParser("permit-expirable-semaphore", defaultParser);
registerBeanDefinitionParser("lock", defaultParser);
registerBeanDefinitionParser("fair-lock", defaultParser);
registerBeanDefinitionParser("read-write-lock",readWriteLockParser);
registerBeanDefinitionParser("read-lock", readAndWriteLockParser);
registerBeanDefinitionParser("write-lock", readAndWriteLockParser);
registerBeanDefinitionParser("multi-lock", nestedParser);
registerBeanDefinitionParser("red-lock", nestedParser);
registerBeanDefinitionParser("set", defaultParser);
registerBeanDefinitionParser("sorted-set", defaultParser);
registerBeanDefinitionParser("scored-sorted-set", defaultParser);
registerBeanDefinitionParser("lex-sorted-set", defaultParser);
registerBeanDefinitionParser("topic", defaultParser);
registerBeanDefinitionParser("pattern-topic", defaultParser);
registerBeanDefinitionParser("blocking-fair-queue", defaultParser);
registerBeanDefinitionParser("queue", defaultParser);
registerBeanDefinitionParser("delayed-queue",
new RedissonGenericObjectDefinitionParser(helper,
new DelayedQueueDecorator()));
registerBeanDefinitionParser("priority-queue", defaultParser);
registerBeanDefinitionParser("priority-deque", defaultParser);
registerBeanDefinitionParser("blocking-queue", defaultParser);
registerBeanDefinitionParser("bounded-blocking-queue", defaultParser);
registerBeanDefinitionParser("deque", defaultParser);
registerBeanDefinitionParser("blocking-deque", defaultParser);
registerBeanDefinitionParser("atomic-long", defaultParser);
registerBeanDefinitionParser("atomic-double", defaultParser);
registerBeanDefinitionParser("count-down-latch", defaultParser);
registerBeanDefinitionParser("bit-set", defaultParser);
registerBeanDefinitionParser("bloom-filter", defaultParser);
registerBeanDefinitionParser("script", defaultParser);
registerBeanDefinitionParser("executor-service", defaultParser);//nested unfinished
registerBeanDefinitionParser("remote-service", remoteServiceParser);
registerBeanDefinitionParser("rpc-server",
new RedissonRPCServerDefinitionParser(helper));
registerBeanDefinitionParser("rpc-client",
new RedissonRPCClientDefinitionParser(helper,
new RemoteInvocationOptionDecorator()));
registerBeanDefinitionParser("keys", defaultParser);
registerBeanDefinitionParser("live-object-service", liveObjectServiceParser);
registerBeanDefinitionParser("live-object",
new RedissonLiveObjectDefinitionParser(helper));
registerBeanDefinitionParser("live-object-registration",
new RedissonLiveObjectRegistrationDefinitionParser(helper));
}
}

@ -0,0 +1,300 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.spring.misc.BeanMethodInvoker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.util.StringUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonNamespaceParserSupport {
public final static String REDISSON_NAMESPACE
= "http://redisson.org/schema/redisson";
static final String API_CLASS_PATH_PREFIX = "org.redisson.api.R";
static final String IMPL_CLASS_PATH_PREFIX = "org.redisson.Redisson";
static final String ID_ATTRIBUTE = "id";
static final String NAME_ATTRIBUTE = "name";
static final String REDISSON_REF_ATTRIBUTE = "redisson-ref";
static final String READ_WRITE_LOCK_REF_ATTRIBUTE = "read-write-lock-ref";
static final String EXECUTOR_REF_ATTRIBUTE = "executor-ref";
static final String REMOTE_SERVICE_REF_ATTRIBUTE = "remote-service-ref";
static final String LIVE_OBJECT_SERVICE_REF_ATTRIBUTE
= "live-object-service-ref";
static final String OBJECT_ID_REF_ATTRIBUTE = "object-id-ref";
static final String MAX_IDLE_ATTRIBUTE = "max-idle";
static final String TIME_TO_LIVE_ATTRIBUTE = "time-to-live";
static final String MAX_IDLE_UNIT_ATTRIBUTE = "max-idle-unit";
static final String TIME_TO_LIVE_UNIT_ATTRIBUTE = "time-to-live-unit";
static final String CONCURRENT_WORKERS_ATTRIBUTE = "concurrent-workers";
static final String WITHIN_ATTRIBUTE = "within";
static final String TIME_UNIT_ATTRIBUTE = "time-unit";
static final String API_CLASS_ATTRIBUTE = "api-class";
static final String CLASS_ATTRIBUTE = "class";
static final String OBJECT_ID_ATTRIBUTE = "object-id";
static final String READ_LOCK_ELEMENT = "read-lock";
static final String WRITE_LOCK_ELEMENT = "write-lock";
static final String RPC_SERVER_ELEMENT = "rpc-server";
static final String RPC_CLIENT_ELEMENT = "rpc-client";
static final String REMOTE_INVOCATION_OPTIONS_ELEMENT
= "remote-invocation-options";
static final String REMOTE_NO_ACK_ELEMENT = "remote-no-ack";
static final String REMOTE_ACK_ELEMENT = "remote-ack";
static final String REMOTE_NO_RESULT_ELEMENT = "remote-no-result";
static final String REMOTE_RESULT_ELEMENT = "remote-result";
static final String LOCAL_CACHED_MAP_OPTIONS_ELEMENT
= "local-cached-map-options";
static final String LIVE_OBJECT_ELEMENT
= "live-object";
static final String LIVE_OBJECT_REGISTRATION_ELEMENT
= "live-object-registration";
public String[] parseAliase(Element element) {
if (element == null) {
return null;
}
String[] aliases = null;
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(
StringUtils.commaDelimitedListToStringArray(name));
}
return aliases;
}
public BeanDefinitionBuilder createBeanDefinitionBuilder(Element element, ParserContext parserContext, Class<?> cls) {
BeanDefinitionBuilder builder
= BeanDefinitionBuilder.genericBeanDefinition();
builder.getRawBeanDefinition().setBeanClass(cls);
builder.getRawBeanDefinition()
.setSource(parserContext.extractSource(element));
if (parserContext.isNested()) {
builder.setScope(parserContext.getContainingBeanDefinition()
.getScope());
}
if (parserContext.isDefaultLazyInit()) {
builder.setLazyInit(true);
}
return builder;
}
public BeanComponentDefinition registerBeanDefinition(BeanDefinitionBuilder builder, String id, String[] aliases, ParserContext parserContext) {
BeanDefinitionHolder holder
= new BeanDefinitionHolder(builder.getBeanDefinition(), id,
aliases);
BeanDefinitionReaderUtils
.registerBeanDefinition(holder, parserContext.getRegistry());
BeanComponentDefinition componentDefinition
= new BeanComponentDefinition(holder);
parserContext.registerComponent(componentDefinition);
return componentDefinition;
}
public BeanComponentDefinition registerBeanDefinition(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
BeanDefinitionHolder holder
= new BeanDefinitionHolder(builder.getBeanDefinition(),
getId(element, builder, parserContext),
parseAliase(element));
BeanDefinitionReaderUtils
.registerBeanDefinition(holder, parserContext.getRegistry());
BeanComponentDefinition componentDefinition
= new BeanComponentDefinition(holder);
parserContext.registerComponent(componentDefinition);
return componentDefinition;
}
public void addConstructorArgs(Element element, String attribute, Class type, BeanDefinition bd) {
if (element.hasAttribute(attribute)) {
addConstructorArgs(element.getAttribute(attribute), type, bd);
}
}
public void addConstructorArgs(Object value, Class type, BeanDefinition bd) {
ConstructorArgumentValues.ValueHolder vHolder
= new ConstructorArgumentValues.ValueHolder(value, type.getName());
ConstructorArgumentValues args
= bd.getConstructorArgumentValues();
args.addIndexedArgumentValue(args.getArgumentCount(), vHolder);
}
public void addConstructorArgs(Element element, String attribute, Class type, BeanDefinitionBuilder builder) {
addConstructorArgs(element, attribute, type, builder.getRawBeanDefinition());
}
public void addConstructorArgs(Object value, Class type, BeanDefinitionBuilder builder) {
addConstructorArgs(value, type, builder.getRawBeanDefinition());
}
public String getName(Node node) {
return Conventions.attributeNameToPropertyName(node.getLocalName());
}
public String getId(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
String id = element != null
? element.getAttribute(ID_ATTRIBUTE)
: null;
if (!StringUtils.hasText(id)) {
id = generateId(builder, parserContext);
}
return id;
}
public String generateId(BeanDefinitionBuilder builder, ParserContext parserContext) {
return parserContext.getReaderContext()
.generateBeanName(builder.getRawBeanDefinition());
}
public void populateIdAttribute(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
if (element == null) {
return;
}
if (!StringUtils.hasText(element.getAttribute(ID_ATTRIBUTE))) {
element.setAttribute(ID_ATTRIBUTE,
generateId(builder, parserContext));
}
}
public BeanComponentDefinition factoryInvoker(Element element, String bean, String method, Object[] args, ParserContext parserContext) {
BeanDefinitionBuilder builder
= preInvoke(element, bean, method, args, parserContext, true);
builder.addPropertyReference("targetObject", bean);
return doInvoke(element, builder, parserContext);
}
public BeanComponentDefinition factoryInvoker(Element element, Object obj, String method, Object[] args, ParserContext parserContext) {
BeanDefinitionBuilder builder
= preInvoke(element, obj, method, args, parserContext, true);
builder.addPropertyValue("targetObject", obj);
return doInvoke(element, builder, parserContext);
}
public BeanComponentDefinition factoryInvoker(String bean, String method, Object[] args, ParserContext parserContext) {
return factoryInvoker(null, bean, method, args, parserContext);
}
public BeanComponentDefinition factoryInvoker(Object obj, String method, Object[] args, ParserContext parserContext) {
return factoryInvoker(null, obj, method, args, parserContext);
}
public BeanComponentDefinition invoker(Element element, String bean, String method, Object[] args, ParserContext parserContext) {
BeanDefinitionBuilder builder
= preInvoke(element, bean, method, args, parserContext, false);
builder.addPropertyReference("targetObject", bean);
return doInvoke(element, builder, parserContext);
}
public BeanComponentDefinition invoker(Element element, Object obj, String method, Object[] args, ParserContext parserContext) {
BeanDefinitionBuilder builder
= preInvoke(element, obj, method, args, parserContext, false);
builder.addPropertyValue("targetObject", obj);
return doInvoke(element, builder, parserContext);
}
public BeanComponentDefinition invoker(String bean, String method, Object[] args, ParserContext parserContext) {
return invoker(null, bean, method, args, parserContext);
}
public BeanComponentDefinition invoker(Object obj, String method, Object[] args, ParserContext parserContext) {
return invoker(null, obj, method, args, parserContext);
}
private BeanDefinitionBuilder preInvoke(Element element, Object obj, String method, Object[] args, ParserContext parserContext, boolean factory) {
BeanDefinitionBuilder builder
= createBeanDefinitionBuilder(element, parserContext,
factory
? MethodInvokingFactoryBean.class
: BeanMethodInvoker.class);
if (obj instanceof Class) {
builder.addPropertyValue("staticMethod",
((Class) obj).getName() + "." + method);
} else {
builder.addPropertyValue("targetMethod", method);
}
builder.addPropertyValue("arguments", args);
if (element != null) {
parserContext.getDelegate().parseQualifierElements(element,
builder.getRawBeanDefinition());
}
return builder;
}
private BeanComponentDefinition doInvoke(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
String id = getId(element, builder, parserContext);
return registerBeanDefinition(builder, id,
parseAliase(element), parserContext);
}
public boolean isEligibleAttribute(String attributeName) {
return !attributeName.equals("xmlns")
&& !attributeName.startsWith("xmlns:")
&& !ID_ATTRIBUTE.equals(attributeName)
&& !NAME_ATTRIBUTE.equals(attributeName);
}
public boolean isEligibleAttribute(Attr attribute) {
return isEligibleAttribute(attribute.getName());
}
public boolean isRedissonNS(Node node) {
return node != null
&& REDISSON_NAMESPACE.equals(node.getNamespaceURI());
}
public String getAttribute(Element element, String attribute) {
return element.getAttribute(attribute);
}
public void setAttribute(Element element, String attribute, String value) {
element.setAttribute(attribute, value);
}
public boolean hasAttribute(Element element, String attribute) {
return element.hasAttribute(attribute);
}
public boolean hasElement(Element element, String tagName) {
return element.getElementsByTagNameNS(
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, tagName)
.getLength() > 0;
}
public Element getSingleElement(Element element, String tagName) {
return (Element) element.getElementsByTagNameNS(
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, tagName)
.item(0);
}
}

@ -0,0 +1,62 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonNestedElementAwareDecorator implements RedissonNamespaceDecorator {
private final String[] nestedElements;
private final String referenceAttribute;
public RedissonNestedElementAwareDecorator(String[] nestedElements, String referenceAttribute) {
this.nestedElements = nestedElements;
this.referenceAttribute = referenceAttribute;
}
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
for (String nestedElement : nestedElements) {
parseNested(element, nestedElement, parserContext, builder, helper);
}
}
private void parseNested(Element element, String eltType, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
NodeList list = element.getElementsByTagNameNS(
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, eltType);
if (list.getLength() == 1) {
Element elt = (Element) list.item(0);
if (StringUtils.hasText(referenceAttribute)) {
helper.setAttribute(elt, referenceAttribute,
helper.getAttribute(element,
RedissonNamespaceParserSupport.ID_ATTRIBUTE));
helper.setAttribute(elt, RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
helper.getAttribute(element,
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
}
parserContext.getDelegate()
.parseCustomElement(elt, builder.getRawBeanDefinition());
}
}
}

@ -0,0 +1,65 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonRPCClientDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonRPCClientDefinitionParser(RedissonNamespaceParserSupport helper, RedissonNamespaceDecorator decorator) {
super(helper,
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE,
decorator);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
Class<?> apiClass;
try {
apiClass = Class.forName(helper.getAttribute(element,
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE));
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
"The class [" + helper.getAttribute(element,
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE)
+ "] specified in \""
+ RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE
+ "\" attribute has not "
+ "found. Please check the class path.", ex);
}
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE)));
builder.addPropertyValue("targetMethod", "get");
builder.addPropertyValue("arguments", new Object[] {apiClass});
}
@Override
protected Class<?> getBeanClass(Element element) {
return MethodInvokingFactoryBean.class;
}
}

@ -0,0 +1,96 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.redisson.spring.misc.BeanMethodInvoker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import reactor.core.support.Assert;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonRPCServerDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonRPCServerDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper, RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
Class<?> apiClass;
try {
apiClass = Class.forName(helper.getAttribute(element,
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE));
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
"The class [" + helper.getAttribute(element,
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE)
+ "] specified in \""
+ RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE
+ "\" attribute has not "
+ "found. Please check the class path.", ex);
}
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE)));
builder.addPropertyValue("targetMethod", "register");
ManagedList args = new ManagedList();
args.add(apiClass);
args.add(new RuntimeBeanReference(
helper.getAttribute(element,
BeanDefinitionParserDelegate.BEAN_REF_ATTRIBUTE)));
String workers = null;
if (helper.hasAttribute(element,
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE)) {
workers = helper.getAttribute(element,
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE);
}
if (StringUtils.hasText(workers)) {
args.add(Integer.parseInt(workers));
}
if (helper.hasAttribute(element,
RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE)) {
Assert.state(helper.hasAttribute(element,
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE),
"The \""
+ RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE
+ "\" attribute in \""
+ RedissonNamespaceParserSupport.RPC_SERVER_ELEMENT
+ "\" element is required when \""
+ RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE
+ "\" attribute is specified.");
args.add(new RuntimeBeanReference(
helper.getAttribute(element,
RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE)));
}
builder.addPropertyValue("arguments", args);
}
@Override
protected Class<?> getBeanClass(Element element) {
return BeanMethodInvoker.class;
}
}

@ -0,0 +1,55 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.w3c.dom.Element;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonReadAndWriteLockDefinitionParser
extends AbstractRedissonNamespaceDefinitionParser {
public RedissonReadAndWriteLockDefinitionParser(RedissonNamespaceParserSupport helper) {
super(helper,
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE);
}
@Override
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
bd.setFactoryBeanName(element.getAttribute(
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE));
String typeName
= Conventions.attributeNameToPropertyName(element.getLocalName());
bd.setFactoryMethodName(typeName);
}
@Override
protected Class<?> getBeanClass(Element element) {
try {
return Class.forName(RedissonNamespaceParserSupport.API_CLASS_PATH_PREFIX
+ "Lock");
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(ex);
}
}
}

@ -0,0 +1,116 @@
/**
* Copyright 2016 Nikita Koksharov
*
* Licensed 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.spring.support;
import java.util.ArrayList;
import java.util.Arrays;
import org.redisson.api.RemoteInvocationOptions;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import reactor.core.support.Assert;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RemoteInvocationOptionDecorator implements RedissonNamespaceDecorator {
@Override
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
if (helper.hasElement(element,
RedissonNamespaceParserSupport.REMOTE_INVOCATION_OPTIONS_ELEMENT)) {
Element options = helper.getSingleElement(element,
RedissonNamespaceParserSupport.REMOTE_INVOCATION_OPTIONS_ELEMENT);
String optionBeanId = invokeOptions(options, parserContext, helper);
if (helper.hasElement(element,
RedissonNamespaceParserSupport.REMOTE_NO_ACK_ELEMENT)) {
helper.invoker(optionBeanId, "noAck", null, parserContext);
}
if (helper.hasElement(element,
RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT)) {
Element remoteAck = helper.getSingleElement(element,
RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT);
Assert.state(helper.hasAttribute(remoteAck,
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE),
"Missing \""
+ RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE
+ "\" attribute in \""
+ RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT
+ "\" element.");
ArrayList args = new ArrayList(2);
args.add(helper.getAttribute(remoteAck,
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE));
if (helper.hasAttribute(remoteAck,
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE)) {
args.add(helper.getAttribute(remoteAck,
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE));
}
helper.invoker(optionBeanId, "expectAckWithin", args.toArray(),
parserContext);
}
if (helper.hasElement(element,
RedissonNamespaceParserSupport.REMOTE_NO_RESULT_ELEMENT)) {
helper.invoker(optionBeanId, "noResult", null, parserContext);
}
if (helper.hasElement(element,
RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT)) {
Element remoteResult = helper.getSingleElement(element,
RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT);
Assert.state(helper.hasAttribute(remoteResult,
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE),
"Missing \""
+ RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE
+ "\" attribute in \""
+ RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT
+ "\" element.");
ArrayList args = new ArrayList(2);
args.add(helper.getAttribute(remoteResult,
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE));
if (helper.hasAttribute(remoteResult,
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE)) {
args.add(helper.getAttribute(remoteResult,
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE));
}
helper.invoker(optionBeanId, "expectResultWithin", args.toArray(),
parserContext);
}
MutablePropertyValues properties = builder.getRawBeanDefinition()
.getPropertyValues();
PropertyValue propertyValue
= properties.getPropertyValue("arguments");
ManagedList<Object> args = new ManagedList();
args.addAll(Arrays.asList(
(Object[]) propertyValue.getValue()));
args.add(new RuntimeBeanReference(optionBeanId));
properties.removePropertyValue("arguments");
properties.addPropertyValue("arguments", args);
}
}
private String invokeOptions(Element element, ParserContext parserContext, RedissonNamespaceParserSupport helper) {
BeanComponentDefinition defaultOption
= helper.factoryInvoker(element, RemoteInvocationOptions.class,
"defaults", null, parserContext);
return defaultOption.getName();
}
}

@ -0,0 +1 @@
http\://redisson.org/schema/redisson=org.redisson.spring.support.RedissonNamespaceHandlerSupport

@ -0,0 +1,2 @@
http\://redisson.org/schema/redisson.xsd=org/redisson/spring/support/redisson-1.0.xsd
http\://redisson.org/schema/redisson-1.0.xsd=org/redisson/spring/support/redisson-1.0.xsd

@ -0,0 +1,4 @@
# Tooling related information for the redisson namespace
http\://redisson.org/schema/redisson@name=redisson Namespace
http\://redisson.org/schema/redisson@prefix=redisson
http\://redisson.org/schema/redisson@icon=org/redisson/spring/support/redisson.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -38,7 +38,9 @@ public abstract class BaseTest {
if (redisson == null) {
redisson = defaultRedisson;
}
redisson.getKeys().flushall();
if (flushBetweenTests()) {
redisson.getKeys().flushall();
}
}
}
@ -74,4 +76,7 @@ public abstract class BaseTest {
return Redisson.create(config);
}
protected boolean flushBetweenTests() {
return true;
}
}

@ -0,0 +1,99 @@
package org.redisson;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class ClusterRunner {
private final LinkedHashMap<RedisRunner, String> nodes = new LinkedHashMap<>();
public ClusterRunner addNode(RedisRunner runner) {
nodes.put(runner, getRandomId());
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.CLUSTER_ENABLED)) {
runner.clusterEnabled(true);
}
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.CLUSTER_NODE_TIMEOUT)) {
runner.clusterNodeTimeout(5000);
}
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.PORT)) {
runner.randomPort(1);
runner.port(RedisRunner.findFreePort());
}
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.BIND)) {
runner.bind("127.0.0.1");
}
return this;
}
public List<RedisRunner.RedisProcess> run() throws IOException, InterruptedException, RedisRunner.FailedToStartRedisException {
ArrayList<RedisRunner.RedisProcess> processes = new ArrayList<>();
for (RedisRunner runner : nodes.keySet()) {
List<String> options = getClusterConfig(runner);
String confFile = runner.defaultDir() + File.pathSeparator + nodes.get(runner) + ".conf";
System.out.println("WRITING CONFIG: for " + nodes.get(runner));
try (PrintWriter printer = new PrintWriter(new FileWriter(confFile))) {
options.stream().forEach((line) -> {
printer.println(line);
System.out.println(line);
});
}
processes.add(runner.clusterConfigFile(confFile).run());
}
Thread.sleep(1000);
for (RedisRunner.RedisProcess process : processes) {
if (!process.isAlive()) {
throw new RedisRunner.FailedToStartRedisException();
}
}
return processes;
}
private List<String> getClusterConfig(RedisRunner runner) {
String me = runner.getInitialBindAddr() + ":" + runner.getPort();
List<String> nodeConfig = new ArrayList<>();
int c = 0;
for (RedisRunner node : nodes.keySet()) {
StringBuilder sb = new StringBuilder();
String nodeAddr = node.getInitialBindAddr() + ":" + node.getPort();
sb.append(nodes.get(node)).append(" ");
sb.append(nodeAddr).append(" ");
sb.append(me.equals(nodeAddr)
? "myself,"
: "").append("master -").append(" ");
sb.append("0").append(" ");
sb.append(me.equals(nodeAddr)
? "0"
: "1").append(" ");
sb.append(c + 1).append(" ");
sb.append("connected ");
sb.append(getSlots(c, nodes.size()));
c++;
nodeConfig.add(sb.toString());
}
nodeConfig.add("vars currentEpoch 0 lastVoteEpoch 0");
return nodeConfig;
}
private String getSlots(int index, int groupNum) {
final double t = 16383;
int start = index == 0 ? 0 : (int) (t / groupNum * index);
int end = index == groupNum - 1 ? (int) t : (int) (t / groupNum * (index + 1)) - 1;
return start + "-" + end;
}
private String getRandomId() {
final SecureRandom r = new SecureRandom();
return new BigInteger(160, r).toString(16);
}
}

@ -2,8 +2,10 @@ package org.redisson;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.ServerSocket;
import java.net.URL;
@ -103,7 +105,19 @@ public class RedisRunner {
CLIENT_OUTPUT_BUFFER_LIMIT$SLAVE,
CLIENT_OUTPUT_BUFFER_LIMIT$PUBSUB,
HZ,
AOF_REWRITE_INCREMENTAL_FSYNC;
AOF_REWRITE_INCREMENTAL_FSYNC,
PROTECTED_MODE,
SENTINEL,
SENTINEL$ANNOUNCE_IP,
SENTINEL$ANNOUNCE_PORT,
SENTINEL$MONITOR(true),
SENTINEL$AUTH_PASS(true),
SENTINEL$DOWN_AFTER_MILLISECONDS(true),
SENTINEL$PARALLEL_SYNCS(true),
SENTINEL$FAILOVER_TIMEOUT(true),
SENTINEL$NOTIFICATION_SCRIPT(true),
SENTINEL$CLIENT_RECONFIG_SCRIPT(true)
;
private final boolean allowMutiple;
@ -172,7 +186,7 @@ public class RedisRunner {
e,
A
}
private final LinkedHashMap<REDIS_OPTIONS, String> options = new LinkedHashMap<>();
protected static RedisRunner.RedisProcess defaultRedisInstance;
private static int defaultRedisInstanceExitCode;
@ -184,6 +198,8 @@ public class RedisRunner {
private int port = 6379;
private int retryCount = Integer.MAX_VALUE;
private boolean randomPort = false;
private String sentinelFile;
private String clusterFile;
{
this.options.put(REDIS_OPTIONS.BINARY_PATH, RedissonRuntimeEnvironment.redisBinaryPath);
@ -253,13 +269,38 @@ public class RedisRunner {
}
public RedisProcess runAndCheck() throws IOException, InterruptedException, FailedToStartRedisException {
RedisProcess rp = runWithOptions(this, options.values().toArray(new String[0]));
if (rp.redisProcess.waitFor(1000, TimeUnit.MILLISECONDS)) {
List<String> args = new ArrayList(options.values());
if (sentinelFile != null && sentinelFile.length() > 0) {
String confFile = defaultDir + File.pathSeparator + sentinelFile;
try (PrintWriter printer = new PrintWriter(new FileWriter(confFile))) {
args.stream().forEach((arg) -> {
if (arg.contains("--")) {
printer.println(arg.replace("--", "\n\r"));
}
});
}
args = args.subList(0, 1);
args.add(confFile);
args.add("--sentinel");
}
RedisProcess rp = runWithOptions(this, args.toArray(new String[0]));
if (!isCluster()
&& rp.redisProcess.waitFor(1000, TimeUnit.MILLISECONDS)) {
throw new FailedToStartRedisException();
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
rp.stop();
} catch (InterruptedException ex) {
}
}));
return rp;
}
public boolean hasOption(REDIS_OPTIONS option) {
return options.containsKey(option);
}
private void addConfigOption(REDIS_OPTIONS option, Object... args) {
StringBuilder sb = new StringBuilder("--")
.append(option.toString()
@ -306,7 +347,7 @@ public class RedisRunner {
options.remove(REDIS_OPTIONS.PORT);
return this;
}
public int getPort() {
return this.port;
}
@ -440,6 +481,11 @@ public class RedisRunner {
return this;
}
public RedisRunner slaveof(String masterip, int port) {
addConfigOption(REDIS_OPTIONS.SLAVEOF, masterip, port);
return this;
}
public RedisRunner masterauth(String masterauth) {
addConfigOption(REDIS_OPTIONS.MASTERAUTH, masterauth);
return this;
@ -582,6 +628,7 @@ public class RedisRunner {
public RedisRunner clusterConfigFile(String clusterConfigFile) {
addConfigOption(REDIS_OPTIONS.CLUSTER_CONFIG_FILE, clusterConfigFile);
this.clusterFile = clusterConfigFile;
return this;
}
@ -702,7 +749,70 @@ public class RedisRunner {
addConfigOption(REDIS_OPTIONS.AOF_REWRITE_INCREMENTAL_FSYNC, convertBoolean(aofRewriteIncrementalFsync));
return this;
}
public RedisRunner protectedMode(boolean protectedMode) {
addConfigOption(REDIS_OPTIONS.PROTECTED_MODE, convertBoolean(protectedMode));
return this;
}
public RedisRunner sentinel() {
sentinelFile = "sentinel_conf_" + UUID.randomUUID() + ".conf";
return this;
}
public RedisRunner sentinelAnnounceIP(String sentinelAnnounceIP) {
addConfigOption(REDIS_OPTIONS.SENTINEL$ANNOUNCE_IP, sentinelAnnounceIP);
return this;
}
public RedisRunner sentinelAnnouncePort(int sentinelAnnouncePort) {
addConfigOption(REDIS_OPTIONS.SENTINEL$ANNOUNCE_PORT, sentinelAnnouncePort);
return this;
}
public RedisRunner sentinelMonitor(String masterName, String ip, int port, int quorum) {
addConfigOption(REDIS_OPTIONS.SENTINEL$MONITOR, masterName, ip, port, quorum);
return this;
}
public RedisRunner sentinelAuthPass(String masterName, String password) {
addConfigOption(REDIS_OPTIONS.SENTINEL$AUTH_PASS, masterName, password);
return this;
}
public RedisRunner sentinelDownAfterMilliseconds(String masterName, long downAfterMilliseconds) {
addConfigOption(REDIS_OPTIONS.SENTINEL$DOWN_AFTER_MILLISECONDS, masterName, downAfterMilliseconds);
return this;
}
public RedisRunner sentinelParallelSyncs(String masterName, int numSlaves) {
addConfigOption(REDIS_OPTIONS.SENTINEL$PARALLEL_SYNCS, masterName, numSlaves);
return this;
}
public RedisRunner sentinelFailoverTimeout(String masterName, long failoverTimeout) {
addConfigOption(REDIS_OPTIONS.SENTINEL$FAILOVER_TIMEOUT, masterName, failoverTimeout);
return this;
}
public RedisRunner sentinelNotificationScript(String masterName, String scriptPath) {
addConfigOption(REDIS_OPTIONS.SENTINEL$NOTIFICATION_SCRIPT, masterName, scriptPath);
return this;
}
public RedisRunner sentinelClientReconfigScript(String masterName, String scriptPath) {
addConfigOption(REDIS_OPTIONS.SENTINEL$CLIENT_RECONFIG_SCRIPT, masterName, scriptPath);
return this;
}
public boolean isSentinel() {
return this.sentinelFile != null;
}
public boolean isCluster() {
return this.clusterFile != null;
}
public boolean isRandomDir() {
return this.randomDir;
}
@ -722,14 +832,32 @@ public class RedisRunner {
public boolean deleteDBfileDir() {
File f = new File(defaultDir);
if (f.exists()) {
System.out.println("REDIS RUNNER: Deleting directory " + defaultDir);
System.out.println("REDIS RUNNER: Deleting directory " + f.getAbsolutePath());
return f.delete();
}
return false;
}
public boolean deleteSentinelFile() {
File f = new File(defaultDir + File.pathSeparator + sentinelFile);
if (f.exists()) {
System.out.println("REDIS RUNNER: Deleting sentinel config file " + f.getAbsolutePath());
return f.delete();
}
return false;
}
public boolean deleteClusterFile() {
File f = new File(clusterFile);
if (f.exists()) {
System.out.println("REDIS RUNNER: Deleting cluster config file " + f.getAbsolutePath());
return f.delete();
}
return false;
}
private void makeRandomDefaultDir() {
File f = new File(RedissonRuntimeEnvironment.tempDir + "/" + UUID.randomUUID());
File f = new File(RedissonRuntimeEnvironment.tempDir + File.pathSeparator + UUID.randomUUID());
if (f.exists()) {
makeRandomDefaultDir();
} else {
@ -761,6 +889,12 @@ public class RedisRunner {
}
redisProcess.destroy();
int exitCode = redisProcess.isAlive() ? redisProcess.waitFor() : redisProcess.exitValue();
if (runner.isSentinel()) {
runner.deleteSentinelFile();
}
if (runner.isCluster()) {
runner.deleteClusterFile();
}
if (runner.isRandomDir()) {
runner.deleteDBfileDir();
}
@ -799,18 +933,16 @@ public class RedisRunner {
public String getRedisServerAddressAndPort() {
return getRedisServerBindAddress() + ":" + getRedisServerPort();
}
public boolean isAlive() {
return redisProcess.isAlive();
}
}
public static RedisRunner.RedisProcess startDefaultRedisServerInstance() throws IOException, InterruptedException, FailedToStartRedisException {
if (defaultRedisInstance == null) {
System.out.println("REDIS RUNNER: Starting up default instance...");
defaultRedisInstance = new RedisRunner().nosave().randomDir().randomPort().run();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
shutDownDefaultRedisServerInstance();
} catch (InterruptedException ex) {
}
}));
}
return defaultRedisInstance;
}
@ -853,12 +985,11 @@ public class RedisRunner {
socket = new ServerSocket(0);
socket.setReuseAddress(true);
int port = socket.getLocalPort();
try {
socket.close();
} catch (IOException e) {
// Ignore IOException on close()
if (port > 55535 && isFreePort(port - 10000)) {
return port - 10000;
} else {
return port;
}
return port;
} catch (IOException e) {
} finally {
if (socket != null) {
@ -871,9 +1002,27 @@ public class RedisRunner {
throw new IllegalStateException("Could not find a free TCP/IP port.");
}
public static boolean isFreePort(int port) {
ServerSocket socket = null;
try {
socket = new ServerSocket(port);
socket.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
return false;
}
public static class FailedToStartRedisException extends RuntimeException {
private FailedToStartRedisException() {
public FailedToStartRedisException() {
}
}

@ -1,7 +1,5 @@
package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.Serializable;
@ -133,7 +131,7 @@ public class RedissonRemoteServiceTest extends BaseTest {
}
public class RemoteImpl implements RemoteInterface {
public static class RemoteImpl implements RemoteInterface {
private AtomicInteger iterations;

@ -0,0 +1,282 @@
package org.redisson.spring.support;
import java.util.Arrays;
import java.util.Collection;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.redisson.BaseTest;
import org.redisson.RedisRunner;
import org.redisson.RedissonFairLock;
import org.redisson.RedissonLiveObjectServiceTest.TestREntity;
import org.redisson.RedissonMultiLock;
import org.redisson.RedissonReadLock;
import org.redisson.RedissonRedLock;
import org.redisson.RedissonRuntimeEnvironment;
import org.redisson.RedissonWriteLock;
import org.redisson.api.LocalCachedMapOptions;
import org.redisson.api.RAtomicDouble;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBinaryStream;
import org.redisson.api.RBitSet;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RBlockingFairQueue;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RBoundedBlockingQueue;
import org.redisson.api.RBucket;
import org.redisson.api.RBuckets;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RDeque;
import org.redisson.api.RExecutorService;
import org.redisson.api.RGeo;
import org.redisson.api.RHyperLogLog;
import org.redisson.api.RKeys;
import org.redisson.api.RLexSortedSet;
import org.redisson.api.RList;
import org.redisson.api.RListMultimap;
import org.redisson.api.RLiveObject;
import org.redisson.api.RLiveObjectService;
import org.redisson.api.RLocalCachedMap;
import org.redisson.api.RLock;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.api.RObject;
import org.redisson.api.RPatternTopic;
import org.redisson.api.RPermitExpirableSemaphore;
import org.redisson.api.RPriorityDeque;
import org.redisson.api.RPriorityQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RRemoteService;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RScript;
import org.redisson.api.RSemaphore;
import org.redisson.api.RSet;
import org.redisson.api.RSetCache;
import org.redisson.api.RSetMultimap;
import org.redisson.api.RSetMultimapCache;
import org.redisson.api.RSortedSet;
import org.redisson.api.RTopic;
import org.redisson.api.RemoteInvocationOptions;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
@RunWith(Parameterized.class)
public class SpringNamespaceObjectTest extends BaseTest {
private static ApplicationContext context;
@BeforeClass
public static void setupClass() throws Exception {
if (!RedissonRuntimeEnvironment.isTravis) {
startContext();
}
}
@AfterClass
public static void shutDownClass() {
if (!RedissonRuntimeEnvironment.isTravis) {
stopContext();
}
}
@Before
public void setup() throws Exception {
if (RedissonRuntimeEnvironment.isTravis) {
startContext();
}
}
@After
public void shutDown() {
if (RedissonRuntimeEnvironment.isTravis) {
stopContext();
}
}
@Override
protected boolean flushBetweenTests() {
return false;
}
public static void startContext() {
TestREntity entity = new TestREntity("live-object");
entity.setValue("1");
defaultRedisson.getLiveObjectService().merge(entity);
entity = new TestREntity("live-object-ext");
entity.setValue("1");
defaultRedisson.getLiveObjectService().merge(entity);
System.setProperty("redisAddress", RedisRunner.getDefaultRedisServerBindAddressAndPort());
context = new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/redisson_objects.xml");
}
public static void stopContext() {
((ConfigurableApplicationContext) context).close();
}
@Parameters(name = "{index}: key=[{0}], class=[{1}], parent=[{2}]")
public static Collection<Object[]> tests() {
return Arrays.asList(new Object[][]{
{"binary-stream", RBinaryStream.class, null},
{"geo", RGeo.class, null},
{"set-cache", RSetCache.class, null},
{"map-cache", RMapCache.class, null},
{"bucket", RBucket.class, null},
{"buckets", RBuckets.class, null},
{"hyper-log-log", RHyperLogLog.class, null},
{"list", RList.class, null},
{"list-multimap", RListMultimap.class, null},
{"local-cached-map", RLocalCachedMap.class, null},
{"local-options", LocalCachedMapOptions.class, null},
{"map", RMap.class, null},
{"set-multimap", RSetMultimap.class, null},
{"set-multimap-cache", RSetMultimapCache.class, null},
{"semaphore", RSemaphore.class, null},
{"permit-expirable-semaphore", RPermitExpirableSemaphore.class, null},
{"lock", RLock.class, null},
{"fair-lock", RedissonFairLock.class, null},
{"read-write-lock", RReadWriteLock.class, null},
{"read-lock", RedissonReadLock.class, "read-write-lock"},
{"write-lock", RedissonWriteLock.class, "read-write-lock"},
{"multi-lock", RedissonMultiLock.class, null},
{"lock-1", RLock.class, null},
{"fair-lock-1", RedissonFairLock.class, null},
{"read-lock-1", RedissonReadLock.class, "read-write-lock"},
{"write-lock-1", RedissonWriteLock.class, "read-write-lock"},
{"red-lock", RedissonRedLock.class, null},
{"lock-2", RLock.class, null},
{"fair-lock-2", RedissonFairLock.class, null},
{"read-lock-2", RedissonReadLock.class, "read-write-lock"},
{"write-lock-2", RedissonWriteLock.class, "read-write-lock"},
{"set", RSet.class, null},
{"sorted-set", RSortedSet.class, null},
{"scored-sorted-set", RScoredSortedSet.class, null},
{"lex-sorted-set", RLexSortedSet.class, null},
{"topic", RTopic.class, null},
{"pattern-topic", RPatternTopic.class, null},
{"blocking-fair-queue", RBlockingFairQueue.class, null},
{"queue", RQueue.class, null},
{"delayed-queue", RDelayedQueue.class, "queue"},
{"priority-queue", RPriorityQueue.class, null},
{"priority-deque", RPriorityDeque.class, null},
{"blocking-queue", RBlockingQueue.class, null},
{"bounded-blocking-queue", RBoundedBlockingQueue.class, null},
{"deque", RDeque.class, null},
{"blocking-deque", RBlockingDeque.class, null},
{"atomic-long", RAtomicLong.class, null},
{"atomic-double", RAtomicDouble.class, null},
{"count-down-latch", RCountDownLatch.class, null},
{"bit-set", RBitSet.class, null},
{"bloom-filter", RBloomFilter.class, null},
{"script", RScript.class, null},
{"executor-service", RExecutorService.class, null},
{"remote-service", RRemoteService.class, null},
{"rpc-client", org.redisson.RedissonRemoteServiceTest.RemoteInterface.class, null},
{"options", RemoteInvocationOptions.class, null},
{"keys", RKeys.class, null},
{"live-object-service", RLiveObjectService.class, null},
{"live-object", RLiveObject.class, null},
{"binary-stream-ext", RBinaryStream.class, null},
{"geo-ext", RGeo.class, null},
{"set-cache-ext", RSetCache.class, null},
{"map-cache-ext", RMapCache.class, null},
{"bucket-ext", RBucket.class, null},
{"buckets-ext", RBuckets.class, null},
{"hyper-log-log-ext", RHyperLogLog.class, null},
{"list-ext", RList.class, null},
{"list-multimap-ext", RListMultimap.class, null},
{"local-cached-map-ext", RLocalCachedMap.class, null},
{"local-options-ext", LocalCachedMapOptions.class, null},
{"map-ext", RMap.class, null},
{"set-multimap-ext", RSetMultimap.class, null},
{"set-multimap-cache-ext", RSetMultimapCache.class, null},
{"semaphore-ext", RSemaphore.class, null},
{"permit-expirable-semaphore-ext", RPermitExpirableSemaphore.class, null},
{"lock-ext", RLock.class, null},
{"fair-lock-ext", RedissonFairLock.class, null},
{"read-write-lock-ext", RReadWriteLock.class, null},
{"read-lock-ext", RedissonReadLock.class, "read-write-lock-ext"},
{"write-lock-ext", RedissonWriteLock.class, "read-write-lock-ext"},
{"multi-lock-ext", RedissonMultiLock.class, null},
{"lock-1-ext", RLock.class, null},
{"fair-lock-1-ext", RedissonFairLock.class, null},
{"read-lock-1-ext", RedissonReadLock.class, "read-write-lock-ext"},
{"write-lock-1-ext", RedissonWriteLock.class, "read-write-lock-ext"},
{"red-lock-ext", RedissonRedLock.class, null},
{"lock-2-ext", RLock.class, null},
{"fair-lock-2-ext", RedissonFairLock.class, null},
{"read-lock-2-ext", RedissonReadLock.class, "read-write-lock-ext"},
{"write-lock-2-ext", RedissonWriteLock.class, "read-write-lock-ext"},
{"set-ext", RSet.class, null},
{"sorted-set-ext", RSortedSet.class, null},
{"scored-sorted-set-ext", RScoredSortedSet.class, null},
{"lex-sorted-set-ext", RLexSortedSet.class, null},
{"topic-ext", RTopic.class, null},
{"pattern-topic-ext", RPatternTopic.class, null},
{"blocking-fair-queue-ext", RBlockingFairQueue.class, null},
{"queue-ext", RQueue.class, null},
{"delayed-queue-ext", RDelayedQueue.class, "queue-ext"},
{"priority-queue-ext", RPriorityQueue.class, null},
{"priority-deque-ext", RPriorityDeque.class, null},
{"blocking-queue-ext", RBlockingQueue.class, null},
{"bounded-blocking-queue-ext", RBoundedBlockingQueue.class, null},
{"deque-ext", RDeque.class, null},
{"blocking-deque-ext", RBlockingDeque.class, null},
{"atomic-long-ext", RAtomicLong.class, null},
{"atomic-double-ext", RAtomicDouble.class, null},
{"count-down-latch-ext", RCountDownLatch.class, null},
{"bit-set-ext", RBitSet.class, null},
{"bloom-filter-ext", RBloomFilter.class, null},
{"script-ext", RScript.class, null},
{"executor-service-ext", RExecutorService.class, null},
{"remote-service-ext", RRemoteService.class, null},
{"rpc-client-ext", org.redisson.RedissonRemoteServiceTest.RemoteInterface.class, null},
{"options-ext", RemoteInvocationOptions.class, null},
{"keys-ext", RKeys.class, null},
{"live-object-service-ext", RLiveObjectService.class, null},
{"live-object-ext", RLiveObject.class, null},
});
}
@Parameter
public String key;
@Parameter(1)
public Class cls;
@Parameter(2)
public String parentKey;
@Test
public void testRObjects() {
Object bean = context.getBean(key);
assertTrue(cls.isInstance(bean));
if (RObject.class.isAssignableFrom(cls)) {
assertEquals(parentKey == null ? key : parentKey, RObject.class.cast(bean).getName());
}
if (RTopic.class.isAssignableFrom(cls)) {
assertEquals(key, RTopic.class.cast(bean).getChannelNames().get(0));
}
if (RPatternTopic.class.isAssignableFrom(cls)) {
assertEquals(key, RPatternTopic.class.cast(bean).getPatternNames().get(0));
}
if (RLiveObject.class.isAssignableFrom(cls)) {
assertEquals(key, RLiveObject.class.cast(bean).getLiveObjectId());
}
}
}

@ -0,0 +1,368 @@
package org.redisson.spring.support;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.redisson.BaseTest;
import org.redisson.ClusterRunner;
import org.redisson.RedisRunner;
import org.redisson.Redisson;
import org.redisson.RedissonRuntimeEnvironment;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.codec.MsgPackJacksonCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class SpringNamespaceTest extends BaseTest {
private static ApplicationContext context;
@BeforeClass
public static void setupClass() throws Exception {
if (!RedissonRuntimeEnvironment.isTravis) {
startContext();
}
}
@AfterClass
public static void shutDownClass() throws Exception {
if (!RedissonRuntimeEnvironment.isTravis) {
stopContext();
}
}
@Before
public void setup() throws Exception {
if (RedissonRuntimeEnvironment.isTravis) {
startContext();
}
}
@After
public void shutDown() throws Exception {
if (RedissonRuntimeEnvironment.isTravis) {
stopContext();
}
}
public static void startContext() throws Exception {
System.setProperty("redisAddress", RedisRunner.getDefaultRedisServerBindAddressAndPort());
//Needs a instance running on the default port, launch it if there isn't one already
if (RedisRunner.isFreePort(6379)) {
new RedisRunner()
.nosave()
.randomDir()
.run();
}
RedisRunner.RedisProcess slave1 = new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.slaveof(
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort())
.run();
System.setProperty("slave1Address", slave1.getRedisServerAddressAndPort());
RedisRunner.RedisProcess slave2 = new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.slaveof(
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort())
.run();
System.setProperty("slave2Address", slave2.getRedisServerAddressAndPort());
RedisRunner.RedisProcess sentinel1 = new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.sentinel()
.sentinelMonitor(
"myMaster",
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
2).run();
System.setProperty("sentinel1Address", sentinel1.getRedisServerAddressAndPort());
RedisRunner.RedisProcess sentinel2 = new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.sentinel()
.sentinelMonitor(
"myMaster",
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
2).run();
System.setProperty("sentinel2Address", sentinel2.getRedisServerAddressAndPort());
RedisRunner.RedisProcess sentinel3 = new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.sentinel()
.sentinelMonitor(
"myMaster",
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
2).run();
System.setProperty("sentinel3Address", sentinel3.getRedisServerAddressAndPort());
ClusterRunner clusterRunner = new ClusterRunner()
.addNode(new RedisRunner().randomPort().randomDir().nosave())
.addNode(new RedisRunner().randomPort().randomDir().nosave())
.addNode(new RedisRunner().randomPort().randomDir().nosave());
List<RedisRunner.RedisProcess> nodes = clusterRunner.run();
nodes.stream().forEach((node) -> {
System.setProperty("node" + (nodes.indexOf(node) + 1) + "Address", node.getRedisServerAddressAndPort());
});
context = new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace.xml");
}
public static void stopContext() throws Exception {
((ConfigurableApplicationContext) context).close();
}
public static class AutowireRedisson {
@Autowired
@Qualifier("redisson1")
private Redisson redisson1;
@Autowired
@Qualifier("redisson2")
private RedissonClient redisson2;
@Autowired
@Qualifier("redisson3")
private Redisson redisson3;
@Autowired
@Qualifier("redisson4")
private RedissonClient redisson4;
@Autowired
@Qualifier("myRedisson1")
private Redisson redisson5;
@Autowired
@Qualifier("myRedisson2")
private Redisson redisson6;
@Autowired
@Qualifier("qualifier1")
private RedissonClient redisson7;
@Autowired
@Qualifier("qualifier2")
private RedissonClient redisson8;
/**
* @return the redisson1
*/
public Redisson getRedisson1() {
return redisson1;
}
/**
* @param redisson1 the redisson1 to set
*/
public void setRedisson1(Redisson redisson1) {
this.redisson1 = redisson1;
}
/**
* @return the redisson2
*/
public RedissonClient getRedisson2() {
return redisson2;
}
/**
* @param redisson2 the redisson2 to set
*/
public void setRedisson2(RedissonClient redisson2) {
this.redisson2 = redisson2;
}
/**
* @return the redisson3
*/
public Redisson getRedisson3() {
return redisson3;
}
/**
* @param redisson3 the redisson3 to set
*/
public void setRedisson3(Redisson redisson3) {
this.redisson3 = redisson3;
}
/**
* @return the redisson4
*/
public RedissonClient getRedisson4() {
return redisson4;
}
/**
* @param redisson4 the redisson4 to set
*/
public void setRedisson4(RedissonClient redisson4) {
this.redisson4 = redisson4;
}
/**
* @return the redisson5
*/
public Redisson getRedisson5() {
return redisson5;
}
/**
* @param redisson5 the redisson5 to set
*/
public void setRedisson5(Redisson redisson5) {
this.redisson5 = redisson5;
}
/**
* @return the redisson6
*/
public Redisson getRedisson6() {
return redisson6;
}
/**
* @param redisson6 the redisson6 to set
*/
public void setRedisson6(Redisson redisson6) {
this.redisson6 = redisson6;
}
/**
* @return the redisson7
*/
public RedissonClient getRedisson7() {
return redisson7;
}
/**
* @param redisson7 the redisson7 to set
*/
public void setRedisson7(RedissonClient redisson7) {
this.redisson7 = redisson7;
}
/**
* @return the redisson8
*/
public RedissonClient getRedisson8() {
return redisson8;
}
/**
* @param redisson8 the redisson8 to set
*/
public void setRedisson8(RedissonClient redisson8) {
this.redisson8 = redisson8;
}
}
@Test
public void testNamespace() {
Object bean = context.getBean("myRedisson1");
assertTrue(bean instanceof Redisson);
}
@Test
public void testAlias() {
Object origin = context.getBean("myRedisson1");
assertTrue(origin instanceof Redisson);
Object bean = context.getBean("redisson1");
assertTrue(bean instanceof Redisson);
assertEquals(origin, bean);
bean = context.getBean("redisson2");
assertTrue(bean instanceof Redisson);
assertEquals(origin, bean);
}
@Test
public void testAutowire() {
AutowireRedisson bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedisson.class);
assertNotNull(bean.getRedisson1());
assertNotNull(bean.getRedisson2());
assertNotNull(bean.getRedisson3());
assertNotNull(bean.getRedisson4());
assertNotNull(bean.getRedisson5());
assertNotNull(bean.getRedisson6());
assertNotNull(bean.getRedisson7());
assertNotNull(bean.getRedisson8());
assertEquals(bean.getRedisson1(), bean.getRedisson2());
assertEquals(bean.getRedisson1(), bean.getRedisson5());
assertNotEquals(bean.getRedisson1(), bean.getRedisson7());
assertNotEquals(bean.getRedisson1(), bean.getRedisson8());
assertEquals(bean.getRedisson3(), bean.getRedisson4());
assertEquals(bean.getRedisson3(), bean.getRedisson6());
assertNotEquals(bean.getRedisson3(), bean.getRedisson7());
assertNotEquals(bean.getRedisson3(), bean.getRedisson8());
assertNotEquals(bean.getRedisson7(), bean.getRedisson8());
}
@Test
public void testBeanRef() {
AutowireRedisson bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedisson.class);
assertTrue(bean.getRedisson1().getConfig().getCodec() instanceof MsgPackJacksonCodec);
assertFalse(bean.getRedisson3().getConfig().getCodec() instanceof MsgPackJacksonCodec);
assertFalse(bean.getRedisson7().getConfig().getCodec() instanceof MsgPackJacksonCodec);
assertFalse(bean.getRedisson8().getConfig().getCodec() instanceof MsgPackJacksonCodec);
}
public static class AutowireRedis {
@Autowired
private RedisClient redisClient;
/**
* @return the redisClient
*/
public RedisClient getRedisClient() {
return redisClient;
}
/**
* @param redisClient the redisClient to set
*/
public void setRedisClient(RedisClient redisClient) {
this.redisClient = redisClient;
}
}
@Test
public void testAutowireRedis() {
AutowireRedis bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedis.class);
RedisConnection connection = bean.getRedisClient().connect();
assertTrue(connection.isActive());
connection.closeAsync().awaitUninterruptibly();
}
}

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://redisson.org/schema/redisson classpath:org/redisson/spring/support/redisson-1.0.xsd
">
<context:annotation-config />
<context:property-placeholder system-properties-mode="OVERRIDE"/>
<redisson:client id="myRedisson1" name="redisson1,redisson2" codec-ref="myCodec" >
<redisson:single-server address="${redisAddress}" client-name="1"/>
</redisson:client>
<redisson:client id="myRedisson2" name="redisson3,redisson4">
<redisson:single-server address="${redisAddress}" client-name="2"/>
</redisson:client>
<redisson:client>
<qualifier value="qualifier1"/>
<redisson:single-server address="${redisAddress}" client-name="3"/>
</redisson:client>
<redisson:client>
<qualifier value="qualifier2"/>
<redisson:single-server address="${redisAddress}" client-name="4"/>
</redisson:client>
<!-- Minimal requirement for redisson client-->
<redisson:client>
<!-- Use default address "127.0.0.1:6379" -->
<redisson:single-server />
</redisson:client>
<redisson:client>
<redisson:sentinel-servers master-name="myMaster">
<redisson:sentinel-address value="${sentinel1Address}" />
<redisson:sentinel-address value="${sentinel2Address}" />
<redisson:sentinel-address value="${sentinel3Address}" />
</redisson:sentinel-servers>
</redisson:client>
<redisson:client>
<redisson:master-slave-servers master-address="${redisAddress}">
<redisson:slave-address value="${slave1Address}" />
<redisson:slave-address value="${slave2Address}" />
</redisson:master-slave-servers>
</redisson:client>
<redisson:client>
<redisson:cluster-servers>
<redisson:node-address value="${node1Address}" />
<redisson:node-address value="${node2Address}" />
<redisson:node-address value="${node3Address}" />
</redisson:cluster-servers>
</redisson:client>
<redisson:client>
<redisson:replicated-servers read-mode="MASTER_SLAVE" >
<redisson:node-address value="${redisAddress}" />
<redisson:node-address value="${slave1Address}" />
<redisson:node-address value="${slave2Address}" />
</redisson:replicated-servers>
</redisson:client>
<!-- Minimal requirement for redis client-->
<!-- Use default host 127.0.0.1 and port 6379 -->
<redisson:redis />
<bean id="myCodec" class="org.redisson.codec.MsgPackJacksonCodec" />
<bean class="org.redisson.spring.support.SpringNamespaceTest.AutowireRedisson" />
<bean class="org.redisson.spring.support.SpringNamespaceTest.AutowireRedis" />
</beans>

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://redisson.org/schema/redisson classpath:org/redisson/spring/support/redisson-1.0.xsd
">
<context:annotation-config/>
<context:property-placeholder system-properties-mode="OVERRIDE"/>
<redisson:client>
<redisson:single-server address="${redisAddress}"/>
<redisson:binary-stream id="binary-stream" key="binary-stream"/>
<redisson:geo id="geo" key="geo"/>
<redisson:set-cache id="set-cache" key="set-cache"/>
<redisson:map-cache id="map-cache" key="map-cache"/>
<redisson:bucket id="bucket" key="bucket"/>
<redisson:buckets id="buckets"/>
<redisson:hyper-log-log id="hyper-log-log" key="hyper-log-log"/>
<redisson:list id="list" key="list"/>
<redisson:list-multimap id="list-multimap" key="list-multimap"/>
<redisson:list-multimap-cache id="list-multimap-cache" key="list-multimap-cache"/>
<redisson:local-cached-map id="local-cached-map" key="local-cached-map">
<redisson:local-cached-map-options id="local-options" eviction-policy="LRU"
time-to-live="1" time-to-live-unit="SECONDS" />
</redisson:local-cached-map>
<redisson:map id="map" key="map"/>
<redisson:set-multimap id="set-multimap" key="set-multimap"/>
<redisson:set-multimap-cache id="set-multimap-cache" key="set-multimap-cache"/>
<redisson:semaphore id="semaphore" key="semaphore"/>
<redisson:permit-expirable-semaphore id="permit-expirable-semaphore" key="permit-expirable-semaphore"/>
<redisson:lock id="lock" key="lock"/>
<redisson:fair-lock id="fair-lock" key="fair-lock"/>
<redisson:read-write-lock id="read-write-lock" key="read-write-lock">
<redisson:read-lock id="read-lock"/>
<redisson:write-lock id="write-lock"/>
</redisson:read-write-lock>
<redisson:multi-lock id="multi-lock">
<ref bean="lock"/>
<redisson:lock id="lock-1" key="lock-1"/>
<redisson:fair-lock id="fair-lock-1" key="fair-lock-1"/>
<redisson:write-lock id="write-lock-1" read-write-lock-ref="read-write-lock"/>
<redisson:read-lock id="read-lock-1" read-write-lock-ref="read-write-lock"/>
</redisson:multi-lock>
<redisson:red-lock id="red-lock">
<ref bean="lock"/>
<redisson:lock id="lock-2" key="lock-2"/>
<redisson:fair-lock id="fair-lock-2" key="fair-lock-2"/>
<redisson:write-lock id="write-lock-2" read-write-lock-ref="read-write-lock"/>
<redisson:read-lock id="read-lock-2" read-write-lock-ref="read-write-lock"/>
</redisson:red-lock>
<redisson:set id="set" key="set"/>
<redisson:sorted-set id="sorted-set" key="sorted-set"/>
<redisson:scored-sorted-set id="scored-sorted-set" key="scored-sorted-set"/>
<redisson:lex-sorted-set id="lex-sorted-set" key="lex-sorted-set"/>
<redisson:topic id="topic" topic="topic"/>
<redisson:pattern-topic id="pattern-topic" pattern="pattern-topic"/>
<redisson:blocking-fair-queue id="blocking-fair-queue" key="blocking-fair-queue"/>
<redisson:queue id="queue" key="queue"/>
<redisson:delayed-queue id="delayed-queue" destination-queue-ref="queue"/>
<redisson:priority-queue id="priority-queue" key="priority-queue"/>
<redisson:priority-deque id="priority-deque" key="priority-deque"/>
<redisson:blocking-queue id="blocking-queue" key="blocking-queue"/>
<redisson:bounded-blocking-queue id="bounded-blocking-queue" key="bounded-blocking-queue"/>
<redisson:deque id="deque" key="deque"/>
<redisson:blocking-deque id="blocking-deque" key="blocking-deque"/>
<redisson:atomic-long id="atomic-long" key="atomic-long"/>
<redisson:atomic-double id="atomic-double" key="atomic-double"/>
<redisson:count-down-latch id="count-down-latch" key="count-down-latch"/>
<redisson:bit-set id="bit-set" key="bit-set"/>
<redisson:bloom-filter id="bloom-filter" key="bloom-filter"/>
<redisson:script id="script"/>
<redisson:executor-service id="executor-service" service="executor-service"/>
<redisson:remote-service id="remote-service" service="remote-service">
<redisson:rpc-server api-class="org.redisson.RedissonRemoteServiceTest$RemoteInterface"
bean="remoteBean"/>
<redisson:rpc-client id="rpc-client" api-class="org.redisson.RedissonRemoteServiceTest$RemoteInterface">
<redisson:remote-invocation-options id="options">
<!--one of two-->
<!--<redisson:remote-no-ack/>-->
<redisson:remote-ack within="1" time-unit="SECONDS"/>
<!--one of two-->
<!--<redisson:remote-no-result/>-->
<redisson:remote-result within="1" time-unit="SECONDS"/>
</redisson:remote-invocation-options>
</redisson:rpc-client>
</redisson:remote-service>
<redisson:keys id="keys"/>
<redisson:live-object-service id="live-object-service">
<redisson:live-object-registration class="org.redisson.RedissonLiveObjectServiceTest$TestREntity" />
<redisson:live-object id="live-object" object-id="live-object"
class="org.redisson.RedissonLiveObjectServiceTest$TestREntity" />
</redisson:live-object-service>
</redisson:client>
<redisson:client id="myRedisson">
<redisson:single-server address="${redisAddress}"/>
</redisson:client>
<redisson:client id="myRedisson1">
<redisson:single-server address="${redisAddress}"/>
</redisson:client>
<!--External definitions-->
<redisson:binary-stream id="binary-stream-ext" key="binary-stream-ext" redisson-ref="myRedisson"/>
<redisson:geo id="geo-ext" key="geo-ext" redisson-ref="myRedisson"/>
<redisson:set-cache id="set-cache-ext" key="set-cache-ext" redisson-ref="myRedisson"/>
<redisson:map-cache id="map-cache-ext" key="map-cache-ext" redisson-ref="myRedisson"/>
<redisson:bucket id="bucket-ext" key="bucket-ext" redisson-ref="myRedisson"/>
<redisson:buckets id="buckets-ext" redisson-ref="myRedisson"/>
<redisson:hyper-log-log id="hyper-log-log-ext" key="hyper-log-log-ext" redisson-ref="myRedisson"/>
<redisson:list id="list-ext" key="list-ext" redisson-ref="myRedisson"/>
<redisson:list-multimap id="list-multimap-ext" key="list-multimap-ext" redisson-ref="myRedisson"/>
<redisson:list-multimap-cache id="list-multimap-cache-ext" key="list-multimap-cache-ext" redisson-ref="myRedisson"/>
<redisson:local-cached-map id="local-cached-map-ext" key="local-cached-map-ext" redisson-ref="myRedisson">
<redisson:local-cached-map-options id="local-options-ext" eviction-policy="LRU"
time-to-live="1" time-to-live-unit="SECONDS" />
</redisson:local-cached-map>
<redisson:map id="map-ext" key="map-ext" redisson-ref="myRedisson"/>
<redisson:set-multimap id="set-multimap-ext" key="set-multimap-ext" redisson-ref="myRedisson"/>
<redisson:set-multimap-cache id="set-multimap-cache-ext" key="set-multimap-cache-ext" redisson-ref="myRedisson"/>
<redisson:semaphore id="semaphore-ext" key="semaphore-ext" redisson-ref="myRedisson"/>
<redisson:permit-expirable-semaphore id="permit-expirable-semaphore-ext" key="permit-expirable-semaphore-ext" redisson-ref="myRedisson"/>
<redisson:lock id="lock-ext" key="lock-ext" redisson-ref="myRedisson"/>
<redisson:fair-lock id="fair-lock-ext" key="fair-lock-ext" redisson-ref="myRedisson"/>
<redisson:read-write-lock id="read-write-lock-ext" key="read-write-lock-ext" redisson-ref="myRedisson">
<redisson:read-lock id="read-lock-ext"/>
<redisson:write-lock id="write-lock-ext"/>
</redisson:read-write-lock>
<redisson:multi-lock id="multi-lock-ext" redisson-ref="myRedisson">
<ref bean="lock-ext"/>
<redisson:lock id="lock-1-ext" key="lock-1-ext" redisson-ref="myRedisson1"/>
<redisson:fair-lock id="fair-lock-1-ext" key="fair-lock-1-ext" redisson-ref="myRedisson1"/>
<redisson:write-lock id="write-lock-1-ext" read-write-lock-ref="read-write-lock-ext"/>
<redisson:read-lock id="read-lock-1-ext" read-write-lock-ref="read-write-lock-ext"/>
</redisson:multi-lock>
<redisson:red-lock id="red-lock-ext" redisson-ref="myRedisson">
<ref bean="lock-ext"/>
<redisson:lock id="lock-2-ext" key="lock-2-ext"/>
<redisson:fair-lock id="fair-lock-2-ext" key="fair-lock-2-ext"/>
<redisson:write-lock id="write-lock-2-ext" read-write-lock-ref="read-write-lock-ext"/>
<redisson:read-lock id="read-lock-2-ext" read-write-lock-ref="read-write-lock-ext"/>
</redisson:red-lock>
<redisson:set id="set-ext" key="set-ext" redisson-ref="myRedisson"/>
<redisson:sorted-set id="sorted-set-ext" key="sorted-set-ext" redisson-ref="myRedisson"/>
<redisson:scored-sorted-set id="scored-sorted-set-ext" key="scored-sorted-set-ext" redisson-ref="myRedisson"/>
<redisson:lex-sorted-set id="lex-sorted-set-ext" key="lex-sorted-set-ext" redisson-ref="myRedisson"/>
<redisson:topic id="topic-ext" topic="topic-ext" redisson-ref="myRedisson"/>
<redisson:pattern-topic id="pattern-topic-ext" pattern="pattern-topic-ext" redisson-ref="myRedisson"/>
<redisson:blocking-fair-queue id="blocking-fair-queue-ext" key="blocking-fair-queue-ext" redisson-ref="myRedisson"/>
<redisson:queue id="queue-ext" key="queue-ext" redisson-ref="myRedisson"/>
<redisson:delayed-queue id="delayed-queue-ext" destination-queue-ref="queue-ext" redisson-ref="myRedisson"/>
<redisson:priority-queue id="priority-queue-ext" key="priority-queue-ext" redisson-ref="myRedisson"/>
<redisson:priority-deque id="priority-deque-ext" key="priority-deque-ext" redisson-ref="myRedisson"/>
<redisson:blocking-queue id="blocking-queue-ext" key="blocking-queue-ext" redisson-ref="myRedisson"/>
<redisson:bounded-blocking-queue id="bounded-blocking-queue-ext" key="bounded-blocking-queue-ext" redisson-ref="myRedisson"/>
<redisson:deque id="deque-ext" key="deque-ext" redisson-ref="myRedisson"/>
<redisson:blocking-deque id="blocking-deque-ext" key="blocking-deque-ext" redisson-ref="myRedisson"/>
<redisson:atomic-long id="atomic-long-ext" key="atomic-long-ext" redisson-ref="myRedisson"/>
<redisson:atomic-double id="atomic-double-ext" key="atomic-double-ext" redisson-ref="myRedisson"/>
<redisson:count-down-latch id="count-down-latch-ext" key="count-down-latch-ext" redisson-ref="myRedisson"/>
<redisson:bit-set id="bit-set-ext" key="bit-set-ext" redisson-ref="myRedisson"/>
<redisson:bloom-filter id="bloom-filter-ext" key="bloom-filter-ext" redisson-ref="myRedisson"/>
<redisson:script id="script-ext" redisson-ref="myRedisson"/>
<redisson:executor-service id="executor-service-ext" service="executor-service-ext" redisson-ref="myRedisson"/>
<redisson:remote-service id="remote-service-ext" service="remote-service-ext" redisson-ref="myRedisson">
<redisson:rpc-server api-class="org.redisson.RedissonRemoteServiceTest$RemoteInterface"
bean="remoteBean"/>
<redisson:rpc-client id="rpc-client-ext" api-class="org.redisson.RedissonRemoteServiceTest$RemoteInterface">
<redisson:remote-invocation-options id="options-ext">
<redisson:remote-ack within="1" time-unit="SECONDS"/>
<redisson:remote-result within="1" time-unit="SECONDS"/>
</redisson:remote-invocation-options>
</redisson:rpc-client>
</redisson:remote-service>
<redisson:keys id="keys-ext" redisson-ref="myRedisson"/>
<redisson:live-object-service id="live-object-service-ext" redisson-ref="myRedisson">
<redisson:live-object-registration class="org.redisson.RedissonLiveObjectServiceTest$TestREntity" />
<redisson:live-object id="live-object-ext" object-id="live-object-ext"
class="org.redisson.RedissonLiveObjectServiceTest$TestREntity" />
</redisson:live-object-service>
<bean id="remoteBean" class="org.redisson.RedissonRemoteServiceTest.RemoteImpl" />
</beans>
Loading…
Cancel
Save