From e515a0d6432b782193c97f0d2387934ab495d3cd Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Thu, 28 Sep 2017 16:31:19 -0400 Subject: [PATCH] INT-4353: Let to set id for DefaultLockRepository JIRA: https://jira.spring.io/browse/INT-4353 Updated based on code review * Polishing according PR comments **Cherry-pick to 4.3.x** --- .../jdbc/lock/DefaultLockRepository.java | 25 ++++++++++++++++--- .../JdbcLockRegistryDifferentClientTests.java | 14 ++++++++--- src/reference/asciidoc/jdbc.adoc | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/DefaultLockRepository.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/DefaultLockRepository.java index 1bacca6cf3..1d23af3fdb 100644 --- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/DefaultLockRepository.java +++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/DefaultLockRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,8 @@ import org.springframework.util.Assert; * * @author Dave Syer * @author Artem Bilan + * @author Glenn Renfro + * * @since 4.3 */ @Repository @@ -57,7 +59,7 @@ public class DefaultLockRepository implements LockRepository, InitializingBean { */ public static final int DEFAULT_TTL = 10000; - private final String id = UUID.randomUUID().toString(); + private final String id; private final JdbcTemplate template; @@ -79,10 +81,27 @@ public class DefaultLockRepository implements LockRepository, InitializingBean { private String countQuery = "SELECT COUNT(REGION) FROM %SLOCK WHERE REGION=? AND LOCK_KEY=? AND CLIENT_ID=? AND CREATED_DATE>=?"; - + /** + * Constructor that initializes the client id that will be associated for + * all the locks persisted by the store instance to a random {@link UUID}. + * @param dataSource the {@link DataSource} used to maintain the lock repository. + */ @Autowired public DefaultLockRepository(DataSource dataSource) { + this(dataSource, UUID.randomUUID().toString()); + } + + /** + * Constructor that allows the user to specify a client id that will + * be associated for all the locks persisted by the store instance. + * @param dataSource the {@link DataSource} used to maintain the lock repository. + * @param id the client id to be associated with locks handled by the repository. + * @since 4.3.13 + */ + public DefaultLockRepository(DataSource dataSource, String id) { + Assert.hasText(id, "id must not be null nor empty"); this.template = new JdbcTemplate(dataSource); + this.id = id; } /** diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java index 890d0b444b..27e30637e2 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,11 +53,13 @@ import org.springframework.util.StopWatch; /** * @author Dave Syer * @author Artem Bilan + * @author Glenn Renfro + * * @since 4.3 */ @ContextConfiguration("JdbcLockRegistryTests-context.xml") @RunWith(SpringJUnit4ClassRunner.class) -@DirtiesContext // close at the end after class +@DirtiesContext public class JdbcLockRegistryDifferentClientTests { private static Log logger = LogFactory.getLog(JdbcLockRegistryDifferentClientTests.class); @@ -194,7 +196,11 @@ public class JdbcLockRegistryDifferentClientTests { @Test public void testOnlyOneLock() throws Exception { + testOnlyOneLock(null); + testOnlyOneLock("AABBCCDD"); + } + private void testOnlyOneLock(String id) throws Exception { for (int i = 0; i < 100; i++) { final List locked = new ArrayList(); @@ -202,7 +208,9 @@ public class JdbcLockRegistryDifferentClientTests { ExecutorService pool = Executors.newFixedThreadPool(6); ArrayList> tasks = new ArrayList>(); for (int j = 0; j < 20; j++) { - final DefaultLockRepository client = new DefaultLockRepository(this.dataSource); + final DefaultLockRepository client = (id == null) ? + new DefaultLockRepository(this.dataSource) : + new DefaultLockRepository(this.dataSource, id); client.afterPropertiesSet(); this.context.getAutowireCapableBeanFactory().autowireBean(client); Callable task = () -> { diff --git a/src/reference/asciidoc/jdbc.adoc b/src/reference/asciidoc/jdbc.adoc index e984ab568f..0d43dfd525 100644 --- a/src/reference/asciidoc/jdbc.adoc +++ b/src/reference/asciidoc/jdbc.adoc @@ -995,6 +995,8 @@ Therefore `prefix` property must be used on the `DefaultLockRepository` bean def Sometimes it happens that one application has moved to the state when it can't release distributed lock - remove the particular record in the data base. For this purpose such dead locks can be expired by the other application on the next locking invocation. The `timeToLive` (TTL) option on the `DefaultLockRepository` is provided for this purpose. +The user may also want to specify `CLIENT_ID` for the locks stored for a given `DefaultLockRepository` instance. +In this case you can specify the `id` to be associated with the `DefaultLockRepository` as a constructor parameter. [[jdbc-metadata-store]] === JDBC Metadata Store