Purpose of this interface is to decouple lock 24 | * access from their implementing system. Registry may 25 | * return locks from different systems while {@link LockService} 26 | * is always bound to a one system. Also implementation may 27 | * choose to use {@link LockServiceLocator} to find the backing 28 | * {@link LockService} implementation. 29 | * 30 | * @author Janne Valkealahti 31 | * 32 | * @deprecated in favour of equivalent functionality in Spring Integration 4.3 33 | */ 34 | @Deprecated 35 | public interface LockRegistry { 36 | 37 | /** 38 | * Gets a {@link DistributedLock} from a registry. 39 | * 40 | * @param lockKey the locking key 41 | * @return distributed lock 42 | */ 43 | DistributedLock get(String lockKey); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/LockService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.cloud.cluster.lock; 17 | 18 | /** 19 | * {@code LockService} implementations provide low 20 | * level access to a particular locking service. This 21 | * service is always backed by a real locking service 22 | * bound to a real distributed system like zookeeper 23 | * or redis. 24 | * 25 | * @author Janne Valkealahti 26 | * 27 | * @deprecated in favour of equivalent functionality in Spring Integration 4.3 28 | */ 29 | @Deprecated 30 | public interface LockService { 31 | 32 | /** 33 | * Obtains a {@link DistributedLock} from a service. Obtaining 34 | * a lock should not do any locking operations like trying 35 | * a lock. All possible locking actions should be left to a user 36 | * to be executed via {@link DistributedLock}. 37 | * 38 | * @param lockKey the locking key 39 | * @return distributed lock 40 | */ 41 | DistributedLock obtain(String lockKey); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/LockServiceLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.cloud.cluster.lock; 17 | 18 | /** 19 | * Lock service locator defines a contract matching a lock 20 | * key to a {@link LockService}. 21 | * 22 | *
Implementation is free to implement this interface as 23 | * it wish. Possible implementation can i.e. choose to locate 24 | * different services based on path matching or any other means 25 | * which creates a consistent resolving to a service. 26 | * 27 | * @author Janne Valkealahti 28 | * 29 | * @deprecated in favour of equivalent functionality in Spring Integration 4.3 30 | */ 31 | @Deprecated 32 | public interface LockServiceLocator { 33 | 34 | /** 35 | * Locates a bound {@link LockService} for a locking key. 36 | * 37 | *
Locate algorithm has to be consistent among different
38 | * JVM's meaning that in all cases a locking key has to resolve
39 | * back to same {@link LockService} where {@link DistributedLock}
40 | * either already exists or will exist once it is created.
41 | *
42 | * @param lockKey the locking key
43 | * @return lock service or null if key is not bound to any service
44 | */
45 | LockService locate(String lockKey);
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/LockingException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.cloud.cluster.lock;
17 |
18 | import org.springframework.dao.NonTransientDataAccessException;
19 |
20 | /**
21 | * Generic runtime exception for locking system.
22 | *
23 | * @author Janne Valkealahti
24 | *
25 | */
26 | public class LockingException extends NonTransientDataAccessException {
27 |
28 | private static final long serialVersionUID = 285133760957296884L;
29 |
30 | /**
31 | * Instantiates a new locking exception.
32 | *
33 | * @param msg the msg
34 | * @param cause the cause
35 | */
36 | public LockingException(String msg, Throwable cause) {
37 | super(msg, cause);
38 | }
39 |
40 | /**
41 | * Instantiates a new locking exception.
42 | *
43 | * @param msg the msg
44 | */
45 | public LockingException(String msg) {
46 | super(msg);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/support/AbstractDistributedLock.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.cloud.cluster.lock.support;
17 |
18 | import org.springframework.cloud.cluster.lock.DistributedLock;
19 |
20 | /**
21 | * Base implementation of {@link DistributedLock}.
22 | *
23 | * @author Janne Valkealahti
24 | *
25 | */
26 | public abstract class AbstractDistributedLock implements DistributedLock {
27 |
28 | private final String lockKey;
29 |
30 | /**
31 | * Instantiates a new abstract distributed lock.
32 | *
33 | * @param lockKey the locking key
34 | */
35 | public AbstractDistributedLock(String lockKey) {
36 | this.lockKey = lockKey;
37 | }
38 |
39 | @Override
40 | public String getLockKey() {
41 | return lockKey;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/support/DefaultLockRegistry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.cloud.cluster.lock.support;
17 |
18 | import org.springframework.cloud.cluster.lock.DistributedLock;
19 | import org.springframework.cloud.cluster.lock.LockRegistry;
20 | import org.springframework.cloud.cluster.lock.LockService;
21 | import org.springframework.cloud.cluster.lock.LockServiceLocator;
22 | import org.springframework.cloud.cluster.lock.LockingException;
23 | import org.springframework.util.Assert;
24 |
25 | /**
26 | * Default implementation of a {@link LockRegistry} delegating
27 | * to a {@link LockServiceLocator}.
28 | *
29 | * @author Janne Valkealahti
30 | *
31 | */
32 | public class DefaultLockRegistry implements LockRegistry {
33 |
34 | private final LockServiceLocator lockServiceLocator;
35 |
36 | /**
37 | * Instantiates a new default lock registry.
38 | *
39 | * @param lockServiceLocator the lock service locator
40 | */
41 | public DefaultLockRegistry(LockServiceLocator lockServiceLocator) {
42 | Assert.notNull(lockServiceLocator, "Lock service locator must be set");
43 | this.lockServiceLocator = lockServiceLocator;
44 | }
45 |
46 | @Override
47 | public DistributedLock get(String lockKey) {
48 | LockService service = lockServiceLocator.locate(lockKey);
49 | if (service == null) {
50 | throw new LockingException("Unable to find lockservice for key=["
51 | + lockKey + "]");
52 | }
53 | return service.obtain(lockKey);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/spring-cloud-cluster-core/src/main/java/org/springframework/cloud/cluster/lock/support/DefaultLockServiceLocator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.cloud.cluster.lock.support;
17 |
18 | import java.util.List;
19 | import java.util.concurrent.CopyOnWriteArrayList;
20 |
21 | import org.springframework.cloud.cluster.lock.LockService;
22 | import org.springframework.cloud.cluster.lock.LockServiceLocator;
23 | import org.springframework.util.AntPathMatcher;
24 | import org.springframework.util.Assert;
25 | import org.springframework.util.PathMatcher;
26 |
27 | /**
28 | * Default implementation of a {@link LockServiceLocator} which uses a set of
29 | * {@link LockService}s where matching happens using a simple {@link PathMatcher}.
30 | *
31 | * @author Janne Valkealahti
32 | *
33 | */
34 | public class DefaultLockServiceLocator implements LockServiceLocator {
35 |
36 | private final List This implementation delegates to {@link RedisLockRegistry} from Spring
30 | * Integration.
31 | *
32 | * @author Janne Valkealahti
33 | *
34 | */
35 | public class RedisLockService implements LockService {
36 |
37 | public static final String DEFAULT_REGISTRY_KEY = "spring-cloud";
38 |
39 | private final RedisLockRegistry redisLockRegistry;
40 |
41 | /**
42 | * Instantiates a new redis lock service.
43 | *
44 | * @param connectionFactory the redis connection factory
45 | */
46 | public RedisLockService(RedisConnectionFactory connectionFactory) {
47 | this(connectionFactory, DEFAULT_REGISTRY_KEY);
48 | }
49 |
50 | /**
51 | * Instantiates a new redis lock service.
52 | *
53 | * @param connectionFactory the redis connection factory
54 | * @param registryKey The key prefix for locks.
55 | */
56 | public RedisLockService(RedisConnectionFactory connectionFactory, String registryKey) {
57 | this.redisLockRegistry = new RedisLockRegistry(connectionFactory, registryKey);
58 | }
59 |
60 | /**
61 | * Instantiates a new redis lock service.
62 | *
63 | * @param connectionFactory the redis connection factory
64 | * @param expireAfter The expiration in milliseconds.
65 | */
66 | public RedisLockService(RedisConnectionFactory connectionFactory, long expireAfter) {
67 | this.redisLockRegistry = new RedisLockRegistry(connectionFactory, DEFAULT_REGISTRY_KEY, expireAfter);
68 | }
69 |
70 | /**
71 | * Instantiates a new redis lock service.
72 | *
73 | * @param connectionFactory the redis connection factory
74 | * @param registryKey The key prefix for locks.
75 | * @param expireAfter The expiration in milliseconds.
76 | */
77 | public RedisLockService(RedisConnectionFactory connectionFactory, String registryKey, long expireAfter) {
78 | this.redisLockRegistry = new RedisLockRegistry(connectionFactory, registryKey, expireAfter);
79 | }
80 |
81 | @Override
82 | public DistributedLock obtain(String lockKey) {
83 | Lock lock = redisLockRegistry.obtain(lockKey);
84 | return new DelegatingDistributedLock(lockKey, lock);
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/spring-cloud-cluster-redis/src/test/java/org/springframework/cloud/cluster/redis/lock/RedisIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.cloud.cluster.redis.lock;
17 |
18 | import static org.hamcrest.CoreMatchers.is;
19 | import static org.junit.Assert.assertThat;
20 |
21 | import java.util.Set;
22 |
23 | import org.junit.After;
24 | import org.junit.Before;
25 | import org.junit.Test;
26 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
27 | import org.springframework.boot.test.EnvironmentTestUtils;
28 | import org.springframework.cloud.cluster.lock.DistributedLock;
29 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
30 | import org.springframework.data.redis.connection.RedisConnectionFactory;
31 | import org.springframework.data.redis.core.RedisTemplate;
32 | import org.springframework.data.redis.serializer.StringRedisSerializer;
33 |
34 | /**
35 | * Integration tests for redis locking using external redis server.
36 | *
37 | * @author Janne Valkealahti
38 | *
39 | */
40 | public class RedisIT {
41 |
42 | private AnnotationConfigApplicationContext context;
43 | private RedisConnectionFactory connectionFactory;
44 | private RedisTemplate