From 3c12d1c22988bcd580b39ef17736282055ab197e Mon Sep 17 00:00:00 2001 From: Alican Akkus Date: Wed, 22 May 2019 09:56:24 +0300 Subject: [PATCH 1/2] some refactorings and prevent possible nullpointer exception --- src/main/java/locksdemo/JdbcLockService.java | 190 +++++++++--------- src/main/java/locksdemo/LocksController.java | 94 +++++---- src/main/java/locksdemo/RedisLockService.java | 184 ++++++++--------- .../java/locksdemo/SimpleLockService.java | 179 ++++++++--------- 4 files changed, 312 insertions(+), 335 deletions(-) diff --git a/src/main/java/locksdemo/JdbcLockService.java b/src/main/java/locksdemo/JdbcLockService.java index fd35fc4..45ed431 100644 --- a/src/main/java/locksdemo/JdbcLockService.java +++ b/src/main/java/locksdemo/JdbcLockService.java @@ -32,104 +32,102 @@ /** * @author Dave Syer - * */ public class JdbcLockService implements LockService { - private final JdbcTemplate jdbcTemplate; - - @Setter - private long expiry = 30000; // 30 seconds - - private RowMapper rowMapper = new LockRowMapper(); - private String findAllQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS"; - private String createQuery = "INSERT INTO LOCKS (NAME,VALUE,EXPIRES) VALUES (?,?,?)"; - private String deleteQuery = "DELETE FROM LOCKS WHERE NAME=? AND VALUE=?"; - private String refreshQuery = "UPDATE LOCKS SET EXPIRES=? WHERE NAME=? AND VALUE=?"; - private String findOneByNameQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS WHERE NAME=?"; - - public JdbcLockService(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Override - public Iterable findAll() { - return jdbcTemplate.query(findAllQuery, rowMapper); - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public Lock create(String name) throws LockExistsException { - Lock lock = getLock(name); - if (lock != null) { - if (lock.isExpired()) { - jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); - } - else { - throw new LockExistsException(); - } - } - lock = new Lock(name, UUID.randomUUID().toString(), new Date( - System.currentTimeMillis() + expiry)); - jdbcTemplate.update(createQuery, lock.getName(), lock.getValue(), - lock.getExpires()); - return lock; - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public boolean release(String name, String value) throws LockNotHeldException { - Lock lock = getLock(name); - if (lock!=null) { - if (!lock.getValue().equals(value)) { - throw new LockNotHeldException(); - } - if (lock.isExpired()) { - throw new LockNotHeldException(); - } - } - int changes = jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); - return changes > 0; - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public Lock refresh(String name, String value) throws LockNotHeldException { - Lock lock = getLock(name); - if (lock!=null) { - if (!lock.getValue().equals(value)) { - throw new LockNotHeldException(); - } - if (lock.isExpired()) { - throw new LockNotHeldException(); - } - } - int changes = jdbcTemplate.update(refreshQuery, lock.getExpires(), - lock.getName(), lock.getValue()); - if (changes > 0) { - return lock; - } - throw new LockNotHeldException(); - } - - private Lock getLock(String name) { - Lock lock = null; - try { - lock = jdbcTemplate.queryForObject(findOneByNameQuery, rowMapper, name); - } - catch (IncorrectResultSizeDataAccessException e) { - // ignore - } - return lock; - } - - private static class LockRowMapper implements RowMapper { - - @Override - public Lock mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Lock(rs.getString(1), rs.getString(2), rs.getTimestamp(3)); - } - - } + private final JdbcTemplate jdbcTemplate; + + @Setter + private long expiry = 30000; // 30 seconds + + private RowMapper rowMapper = new LockRowMapper(); + private String findAllQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS"; + private String createQuery = "INSERT INTO LOCKS (NAME,VALUE,EXPIRES) VALUES (?,?,?)"; + private String deleteQuery = "DELETE FROM LOCKS WHERE NAME=? AND VALUE=?"; + private String refreshQuery = "UPDATE LOCKS SET EXPIRES=? WHERE NAME=? AND VALUE=?"; + private String findOneByNameQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS WHERE NAME=?"; + + public JdbcLockService(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public Iterable findAll() { + return jdbcTemplate.query(findAllQuery, rowMapper); + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public Lock create(String name) throws LockExistsException { + Lock lock = getLock(name); + if (lock != null) { + if (lock.isExpired()) { + jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); + } else { + throw new LockExistsException(); + } + } + lock = new Lock(name, UUID.randomUUID().toString(), new Date( + System.currentTimeMillis() + expiry)); + jdbcTemplate.update(createQuery, lock.getName(), lock.getValue(), + lock.getExpires()); + return lock; + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public boolean release(String name, String value) throws LockNotHeldException { + Lock lock = getLock(name); + if (lock != null) { + if (!lock.getValue().equals(value)) { + throw new LockNotHeldException(); + } + if (lock.isExpired()) { + throw new LockNotHeldException(); + } + int changes = jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); + return changes > 0; + } + return false; + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public Lock refresh(String name, String value) throws LockNotHeldException { + Lock lock = getLock(name); + if (lock != null) { + if (!lock.getValue().equals(value)) { + throw new LockNotHeldException(); + } + if (lock.isExpired()) { + throw new LockNotHeldException(); + } + + int changes = jdbcTemplate.update(refreshQuery, lock.getExpires(), lock.getName(), lock.getValue()); + if (changes > 0) { + return lock; + } + } + throw new LockNotHeldException(); + } + + private Lock getLock(String name) { + Lock lock = null; + try { + lock = jdbcTemplate.queryForObject(findOneByNameQuery, rowMapper, name); + } catch (IncorrectResultSizeDataAccessException e) { + // ignore + } + return lock; + } + + private static class LockRowMapper implements RowMapper { + + @Override + public Lock mapRow(ResultSet rs, int rowNum) throws SQLException { + return new Lock(rs.getString(1), rs.getString(2), rs.getTimestamp(3)); + } + + } } diff --git a/src/main/java/locksdemo/LocksController.java b/src/main/java/locksdemo/LocksController.java index 269cdb7..68ab4a8 100644 --- a/src/main/java/locksdemo/LocksController.java +++ b/src/main/java/locksdemo/LocksController.java @@ -33,63 +33,61 @@ /** * @author Dave Syer - * */ @RestController @RequestMapping("/") -@RequiredArgsConstructor(onConstructor=@_(@Autowired)) +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) public class LocksController { - - private final LockService service; - @RequestMapping(method=RequestMethod.GET) - public Iterable locks() { - return service.findAll(); - } + private final LockService service; + + @RequestMapping(method = RequestMethod.GET) + public Iterable locks() { + return service.findAll(); + } - @RequestMapping(value="{name}", method=RequestMethod.POST) - public Lock create(@PathVariable String name) { - return service.create(name); - } + @RequestMapping(value = "{name}", method = RequestMethod.POST) + public Lock create(@PathVariable String name) { + return service.create(name); + } - @RequestMapping(value="{name}/{value}", method=RequestMethod.DELETE) - public Map release(@PathVariable String name, @PathVariable String value) { - if (!service.release(name, value)) { - throw new NoSuchLockException(); - } - return Collections.singletonMap("status", (Object) "OK"); - } + @RequestMapping(value = "{name}/{value}", method = RequestMethod.DELETE) + public Map release(@PathVariable String name, @PathVariable String value) { + if (!service.release(name, value)) { + throw new NoSuchLockException(); + } + return Collections.singletonMap("status", (Object) "OK"); + } - @RequestMapping(value="{name}/{value}", method=RequestMethod.PUT) - public Lock refresh(@PathVariable String name, @PathVariable String value) { - return service.refresh(name, value); - } - - @ExceptionHandler(LockExistsException.class) - @ResponseBody - public ResponseEntity> lockExists() { - Map body = new HashMap(); - body.put("status", "INVALID"); - body.put("description", "Lock already exists"); - return new ResponseEntity>(body, HttpStatus.BAD_REQUEST); - } + @RequestMapping(value = "{name}/{value}", method = RequestMethod.PUT) + public Lock refresh(@PathVariable String name, @PathVariable String value) { + return service.refresh(name, value); + } - @ExceptionHandler(NoSuchLockException.class) - @ResponseBody - public ResponseEntity> noSuchLock() { - Map body = new HashMap(); - body.put("status", "INVALID"); - body.put("description", "Lock not found"); - return new ResponseEntity>(body, HttpStatus.NOT_FOUND); - } + @ExceptionHandler(LockExistsException.class) + @ResponseBody + public ResponseEntity> lockExists() { + Map body = new HashMap(); + body.put("status", "INVALID"); + body.put("description", "Lock already exists"); + return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); + } - @ExceptionHandler(LockNotHeldException.class) - @ResponseBody - public ResponseEntity> lockNotHeld() { - Map body = new HashMap(); - body.put("status", "INVALID"); - body.put("description", "Lock not held (values do not match)"); - return new ResponseEntity>(body, HttpStatus.NOT_FOUND); - } + @ExceptionHandler(NoSuchLockException.class) + @ResponseBody + public ResponseEntity> noSuchLock() { + Map body = new HashMap<>(); + body.put("status", "INVALID"); + body.put("description", "Lock not found"); + return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); + } + @ExceptionHandler(LockNotHeldException.class) + @ResponseBody + public ResponseEntity> lockNotHeld() { + Map body = new HashMap<>(); + body.put("status", "INVALID"); + body.put("description", "Lock not held (values do not match)"); + return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); + } } diff --git a/src/main/java/locksdemo/RedisLockService.java b/src/main/java/locksdemo/RedisLockService.java index df913ea..116b4dd 100644 --- a/src/main/java/locksdemo/RedisLockService.java +++ b/src/main/java/locksdemo/RedisLockService.java @@ -15,117 +15,99 @@ */ package locksdemo; +import lombok.Setter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisOperations; +import org.springframework.util.Assert; + import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; -import lombok.Setter; - -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.util.Assert; - /** * @author Dave Syer - * */ public class RedisLockService implements LockService { - private static final String DEFAULT_LOCK_PREFIX = "spring.lock."; - - private String prefix = DEFAULT_LOCK_PREFIX; - - @Setter - private long expiry = 30000; // 30 seconds - - private final RedisOperations redisOperations; - - /** - * The prefix for all lock keys. - * @param prefix the prefix to set for all lock keys - */ - public void setPrefix(String prefix) { - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - this.prefix = prefix; - } - - public RedisLockService(RedisConnectionFactory redisConnectionFactory) { - Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); - this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); - } - - @Override - public Iterable findAll() { - Set keys = redisOperations.keys(prefix + "*"); - Set locks = new LinkedHashSet(); - for (String key : keys) { - Date expires = new Date(System.currentTimeMillis() + redisOperations.getExpire(key, TimeUnit.MILLISECONDS)); - locks.add(new Lock(nameForKey(key), redisOperations.opsForValue().get(key), expires)); - } - return locks; - } - - @Override - public Lock create(String name) { - String stored = getValue(name); - if (stored != null) { - throw new LockExistsException(); - } - String value = UUID.randomUUID().toString(); - String key = keyForName(name); - if (!redisOperations.opsForValue().setIfAbsent(key, value)) { - throw new LockExistsException(); - } - redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); - Date expires = new Date(System.currentTimeMillis() + expiry); - return new Lock(name, value, expires); - } - - @Override - public boolean release(String name, String value) { - String stored = getValue(name); - if (stored != null && value.equals(stored)) { - String key = keyForName(name); - redisOperations.delete(key); - return true; - } - if (stored != null) { - throw new LockNotHeldException(); - } - return false; - } - - @Override - public Lock refresh(String name, String value) { - String key = keyForName(name); - String stored = getValue(name); - if (stored != null && value.equals(stored)) { - Date expires = new Date(System.currentTimeMillis() + expiry); - redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); - return new Lock(name, value, expires); - } - throw new LockNotHeldException(); - } - - private String getValue(String name) { - String key = keyForName(name); - String stored = redisOperations.opsForValue().get(key); - return stored; - } - - private String nameForKey(String key) { - if (!key.startsWith(prefix)) { - throw new IllegalStateException("Key (" + key + ") does not start with prefix (" + prefix + ")"); - } - return key.substring(prefix.length()); - } - - private String keyForName(String name) { - return prefix + name; - } + private static final String DEFAULT_LOCK_PREFIX = "spring.lock."; + + private String prefix = DEFAULT_LOCK_PREFIX; + + @Setter + private long expiry = 30000; // 30 seconds + + private final RedisOperations redisOperations; + + public RedisLockService(RedisConnectionFactory redisConnectionFactory) { + Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); + this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); + } + + @Override + public Iterable findAll() { + Set keys = redisOperations.keys(prefix + "*"); + Set locks = new LinkedHashSet<>(); + for (String key : keys) { + Date expires = new Date(System.currentTimeMillis() + redisOperations.getExpire(key, TimeUnit.MILLISECONDS)); + locks.add(new Lock(nameForKey(key), redisOperations.opsForValue().get(key), expires)); + } + return locks; + } + + @Override + public Lock create(String name) { + String value = UUID.randomUUID().toString(); + String key = keyForName(name); + if (!redisOperations.opsForValue().setIfAbsent(key, value)) { + throw new LockExistsException(); + } + redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); + Date expires = new Date(System.currentTimeMillis() + expiry); + return new Lock(name, value, expires); + } + + @Override + public boolean release(String name, String value) { + String stored = getValue(name); + if (value.equals(stored)) { + String key = keyForName(name); + redisOperations.delete(key); + return true; + } + if (stored != null) { + throw new LockNotHeldException(); + } + return false; + } + + @Override + public Lock refresh(String name, String value) { + String key = keyForName(name); + String stored = getValue(name); + if (value.equals(stored)) { + Date expires = new Date(System.currentTimeMillis() + expiry); + redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); + return new Lock(name, value, expires); + } + throw new LockNotHeldException(); + } + + private String getValue(String name) { + String key = keyForName(name); + return redisOperations.opsForValue().get(key); + } + + private String nameForKey(String key) { + if (!key.startsWith(prefix)) { + throw new IllegalStateException("Key (" + key + ") does not start with prefix (" + prefix + ")"); + } + return key.substring(prefix.length()); + } + + private String keyForName(String name) { + return prefix + name; + } } diff --git a/src/main/java/locksdemo/SimpleLockService.java b/src/main/java/locksdemo/SimpleLockService.java index 77c7bbb..fcf81f1 100644 --- a/src/main/java/locksdemo/SimpleLockService.java +++ b/src/main/java/locksdemo/SimpleLockService.java @@ -28,100 +28,99 @@ /** * @author Dave Syer - * */ @Service @ConfigurationProperties("spring.platform.lock") public class SimpleLockService implements LockService { - private final SimpleInMemoryRepository locks = new SimpleInMemoryRepository(); - - private final PriorityQueue ordered = new PriorityQueue(); - - @Setter - private long expiry = 30000; // 30 seconds - - @Override - public Iterable findAll() { - reap(); - return locks.findAll(); - } - - @Override - public Lock create(final String name) { - reap(name); - return locks.update(name, new Callback() { - @Override - public Lock modify(Lock current) { - if (locks.findOne(name) != null) { - throw new LockExistsException(); - } - return add(name, UUID.randomUUID().toString()); - } - }); - } - - @Override - public boolean release(final String name, final String value) { - reap(name); - final Lock lock = locks.findOne(name); - if (lock == null) { - return false; - } - locks.remove(name); - ordered.remove(lock); - return true; - - } - - @Override - public Lock refresh(final String name, final String value) { - return locks.update(name, new Callback() { - @Override - public Lock modify(Lock current) { - Lock lock = reap(name); - if (lock != null) { - throw new LockNotHeldException(); - } - if (!current.getValue().equals(value)) { - throw new LockNotHeldException(); - } - lock = add(name, value); - return lock; - } - }); - } - - private Lock add(String name, String value) { - Lock lock; - lock = new Lock(name, value, new Date(System.currentTimeMillis() + expiry)); - locks.set(name, lock); - ordered.add(lock); - return lock; - } - - private synchronized void reap() { - Lock lock = ordered.poll(); - while (lock != null && reap(lock.getName()) != null) { - lock = ordered.poll(); - } - if (lock != null) { - ordered.add(lock); - } - } - - private Lock reap(String name) { - Lock lock = locks.findOne(name); - if (lock == null) { - return null; - } - Date now = new Date(); - if (lock.getExpires().before(now)) { - locks.remove(lock.getName()); - ordered.remove(lock); - return lock; - } - return null; - } + private final SimpleInMemoryRepository locks = new SimpleInMemoryRepository<>(); + + private final PriorityQueue ordered = new PriorityQueue<>(); + + @Setter + private long expiry = 30000; // 30 seconds + + @Override + public Iterable findAll() { + reap(); + return locks.findAll(); + } + + @Override + public Lock create(final String name) { + reap(name); + return locks.update(name, new Callback() { + @Override + public Lock modify(Lock current) { + if (locks.findOne(name) != null) { + throw new LockExistsException(); + } + return add(name, UUID.randomUUID().toString()); + } + }); + } + + @Override + public boolean release(final String name, final String value) { + reap(name); + final Lock lock = locks.findOne(name); + if (lock == null) { + return false; + } + locks.remove(name); + ordered.remove(lock); + return true; + + } + + @Override + public Lock refresh(final String name, final String value) { + return locks.update(name, new Callback() { + @Override + public Lock modify(Lock current) { + Lock lock = reap(name); + if (lock != null) { + throw new LockNotHeldException(); + } + if (!current.getValue().equals(value)) { + throw new LockNotHeldException(); + } + lock = add(name, value); + return lock; + } + }); + } + + private Lock add(String name, String value) { + Lock lock; + lock = new Lock(name, value, new Date(System.currentTimeMillis() + expiry)); + locks.set(name, lock); + ordered.add(lock); + return lock; + } + + private synchronized void reap() { + Lock lock = ordered.poll(); + while (lock != null && reap(lock.getName()) != null) { + lock = ordered.poll(); + } + if (lock != null) { + ordered.add(lock); + } + } + + private Lock reap(String name) { + Lock lock = locks.findOne(name); + if (lock == null) { + return null; + } + Date now = new Date(); + if (lock.getExpires().before(now)) { + locks.remove(lock.getName()); + ordered.remove(lock); + return lock; + } + return null; + } } From b41bd6b46265533def2d4a70a40d1596cbeda80e Mon Sep 17 00:00:00 2001 From: Alican Akkus Date: Sun, 2 Jun 2019 00:09:47 +0300 Subject: [PATCH 2/2] adds spring format dependency and re-format classes --- pom.xml | 6 + src/main/java/locksdemo/JdbcLockService.java | 197 +++++++++--------- src/main/java/locksdemo/Lock.java | 5 +- src/main/java/locksdemo/LockService.java | 6 +- src/main/java/locksdemo/LocksApplication.java | 13 +- src/main/java/locksdemo/LocksController.java | 90 ++++---- src/main/java/locksdemo/RedisLockService.java | 159 +++++++------- src/main/java/locksdemo/RedisUtils.java | 1 + .../java/locksdemo/SimpleLockService.java | 178 ++++++++-------- .../locksdemo/AbstractLockServiceTests.java | 6 +- src/test/java/locksdemo/ApplicationTests.java | 8 +- .../java/locksdemo/JdbcLockServiceTests.java | 20 +- .../java/locksdemo/RedisLockServiceTests.java | 16 +- src/test/java/locksdemo/RedisServer.java | 8 +- .../locksdemo/SimpleLockServiceTests.java | 7 +- 15 files changed, 375 insertions(+), 345 deletions(-) diff --git a/pom.xml b/pom.xml index 9d58c1c..f5177d3 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,7 @@ UTF-8 1.7 + 0.0.9 @@ -89,6 +90,11 @@ false + + io.spring.javaformat + spring-javaformat-maven-plugin + ${spring-javaformat-maven-plugin.version} + diff --git a/src/main/java/locksdemo/JdbcLockService.java b/src/main/java/locksdemo/JdbcLockService.java index 45ed431..6ca7cf8 100644 --- a/src/main/java/locksdemo/JdbcLockService.java +++ b/src/main/java/locksdemo/JdbcLockService.java @@ -35,99 +35,108 @@ */ public class JdbcLockService implements LockService { - private final JdbcTemplate jdbcTemplate; - - @Setter - private long expiry = 30000; // 30 seconds - - private RowMapper rowMapper = new LockRowMapper(); - private String findAllQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS"; - private String createQuery = "INSERT INTO LOCKS (NAME,VALUE,EXPIRES) VALUES (?,?,?)"; - private String deleteQuery = "DELETE FROM LOCKS WHERE NAME=? AND VALUE=?"; - private String refreshQuery = "UPDATE LOCKS SET EXPIRES=? WHERE NAME=? AND VALUE=?"; - private String findOneByNameQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS WHERE NAME=?"; - - public JdbcLockService(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Override - public Iterable findAll() { - return jdbcTemplate.query(findAllQuery, rowMapper); - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public Lock create(String name) throws LockExistsException { - Lock lock = getLock(name); - if (lock != null) { - if (lock.isExpired()) { - jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); - } else { - throw new LockExistsException(); - } - } - lock = new Lock(name, UUID.randomUUID().toString(), new Date( - System.currentTimeMillis() + expiry)); - jdbcTemplate.update(createQuery, lock.getName(), lock.getValue(), - lock.getExpires()); - return lock; - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public boolean release(String name, String value) throws LockNotHeldException { - Lock lock = getLock(name); - if (lock != null) { - if (!lock.getValue().equals(value)) { - throw new LockNotHeldException(); - } - if (lock.isExpired()) { - throw new LockNotHeldException(); - } - int changes = jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); - return changes > 0; - } - return false; - } - - @Override - @Transactional(isolation = Isolation.REPEATABLE_READ) - public Lock refresh(String name, String value) throws LockNotHeldException { - Lock lock = getLock(name); - if (lock != null) { - if (!lock.getValue().equals(value)) { - throw new LockNotHeldException(); - } - if (lock.isExpired()) { - throw new LockNotHeldException(); - } - - int changes = jdbcTemplate.update(refreshQuery, lock.getExpires(), lock.getName(), lock.getValue()); - if (changes > 0) { - return lock; - } - } - throw new LockNotHeldException(); - } - - private Lock getLock(String name) { - Lock lock = null; - try { - lock = jdbcTemplate.queryForObject(findOneByNameQuery, rowMapper, name); - } catch (IncorrectResultSizeDataAccessException e) { - // ignore - } - return lock; - } - - private static class LockRowMapper implements RowMapper { - - @Override - public Lock mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Lock(rs.getString(1), rs.getString(2), rs.getTimestamp(3)); - } - - } + private final JdbcTemplate jdbcTemplate; + + @Setter + private long expiry = 30000; // 30 seconds + + private RowMapper rowMapper = new LockRowMapper(); + + private String findAllQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS"; + + private String createQuery = "INSERT INTO LOCKS (NAME,VALUE,EXPIRES) VALUES (?,?,?)"; + + private String deleteQuery = "DELETE FROM LOCKS WHERE NAME=? AND VALUE=?"; + + private String refreshQuery = "UPDATE LOCKS SET EXPIRES=? WHERE NAME=? AND VALUE=?"; + + private String findOneByNameQuery = "SELECT NAME,VALUE,EXPIRES FROM LOCKS WHERE NAME=?"; + + public JdbcLockService(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public Iterable findAll() { + return jdbcTemplate.query(findAllQuery, rowMapper); + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public Lock create(String name) throws LockExistsException { + Lock lock = getLock(name); + if (lock != null) { + if (lock.isExpired()) { + jdbcTemplate.update(deleteQuery, lock.getName(), lock.getValue()); + } + else { + throw new LockExistsException(); + } + } + lock = new Lock(name, UUID.randomUUID().toString(), + new Date(System.currentTimeMillis() + expiry)); + jdbcTemplate.update(createQuery, lock.getName(), lock.getValue(), + lock.getExpires()); + return lock; + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public boolean release(String name, String value) throws LockNotHeldException { + Lock lock = getLock(name); + if (lock != null) { + if (!lock.getValue().equals(value)) { + throw new LockNotHeldException(); + } + if (lock.isExpired()) { + throw new LockNotHeldException(); + } + int changes = jdbcTemplate.update(deleteQuery, lock.getName(), + lock.getValue()); + return changes > 0; + } + return false; + } + + @Override + @Transactional(isolation = Isolation.REPEATABLE_READ) + public Lock refresh(String name, String value) throws LockNotHeldException { + Lock lock = getLock(name); + if (lock != null) { + if (!lock.getValue().equals(value)) { + throw new LockNotHeldException(); + } + if (lock.isExpired()) { + throw new LockNotHeldException(); + } + + int changes = jdbcTemplate.update(refreshQuery, lock.getExpires(), + lock.getName(), lock.getValue()); + if (changes > 0) { + return lock; + } + } + throw new LockNotHeldException(); + } + + private Lock getLock(String name) { + Lock lock = null; + try { + lock = jdbcTemplate.queryForObject(findOneByNameQuery, rowMapper, name); + } + catch (IncorrectResultSizeDataAccessException e) { + // ignore + } + return lock; + } + + private static class LockRowMapper implements RowMapper { + + @Override + public Lock mapRow(ResultSet rs, int rowNum) throws SQLException { + return new Lock(rs.getString(1), rs.getString(2), rs.getTimestamp(3)); + } + + } } diff --git a/src/main/java/locksdemo/Lock.java b/src/main/java/locksdemo/Lock.java index d4d6127..6e7cc3b 100644 --- a/src/main/java/locksdemo/Lock.java +++ b/src/main/java/locksdemo/Lock.java @@ -22,6 +22,7 @@ /** * A value object representing a named lock, with a globally unique value and an expiry. + * * @author Dave Syer * */ @@ -33,16 +34,18 @@ public class Lock implements Comparable { * The name of the lock. */ private final String name; + /** * The value of the lock (globally unique, or at least different for locks with the * same name and different expiry). */ private final String value; + /** * The expiry of the lock expressed as a point in time. */ private final Date expires; - + public boolean isExpired() { return expires.before(new Date()); } diff --git a/src/main/java/locksdemo/LockService.java b/src/main/java/locksdemo/LockService.java index ff330ab..aef5d28 100644 --- a/src/main/java/locksdemo/LockService.java +++ b/src/main/java/locksdemo/LockService.java @@ -24,7 +24,7 @@ * holder to prove that he holds the lock. The value is thus unique per lock and per * expiry period (i.e. 2 locks held at different times with the same name will have * different values).. - * + * * @author Dave Syer * */ @@ -32,7 +32,6 @@ public interface LockService { /** * Iterate the existing locks. - * * @return an iterable of all locks */ Iterable findAll(); @@ -42,7 +41,6 @@ public interface LockService { * hold the lock with this name at any given time. Locks expire and can also be * released by the owner, so after either of those events the lock can be acquired by * the same or a different process. - * * @param name the name identifying the lock * @return a Lock containing a value that can be used to release or refresh the lock * @throws LockExistsException @@ -52,7 +50,6 @@ public interface LockService { /** * Release a lock before it expires. Only the holder of a lock can release it, and the * holder must have the correct unique value to prove that he holds it. - * * @param name the name of the lock * @param value the value of the lock (which has to match the value when it was * acquired) @@ -66,7 +63,6 @@ public interface LockService { * hold the lock there will be an exception, but the implementation may not be able to * tell if it was because he formerly held the lock and it expired, or if it simply * was never held. - * * @param name the name of the lock * @param value the value of the lock (which has to match the value when it was * acquired) diff --git a/src/main/java/locksdemo/LocksApplication.java b/src/main/java/locksdemo/LocksApplication.java index fe8a340..6893f5d 100644 --- a/src/main/java/locksdemo/LocksApplication.java +++ b/src/main/java/locksdemo/LocksApplication.java @@ -20,42 +20,49 @@ public class LocksApplication extends WebMvcConfigurerAdapter { public static void main(String[] args) { SpringApplication.run(LocksApplication.class, args); } - + @Bean public LocksController locksController(LockService lockService) { return new LocksController(lockService); } - + @ConditionalOnClass(RedisConnectionFactory.class) @ConditionalOnBean(RedisConnectionFactory.class) @Configuration protected static class RedisLockServiceConfiguration { + @Bean @ConditionalOnMissingBean(LockService.class) public RedisLockService lockService(RedisConnectionFactory connectionFactory) { return new RedisLockService(connectionFactory); } + } @ConditionalOnClass(RedisConnectionFactory.class) @ConditionalOnMissingBean(RedisConnectionFactory.class) @Configuration protected static class FallbackSimpleLockServiceConfiguration { + @Bean @ConditionalOnMissingBean(LockService.class) public SimpleLockService lockService() { return new SimpleLockService(); } + } - @ConditionalOnMissingClass(name="org.springframework.data.redis.connection.RedisConnectionFactory") + @ConditionalOnMissingClass( + name = "org.springframework.data.redis.connection.RedisConnectionFactory") @Configuration protected static class SimpleLockServiceConfiguration { + @Bean @ConditionalOnMissingBean(LockService.class) public SimpleLockService lockService() { return new SimpleLockService(); } + } } diff --git a/src/main/java/locksdemo/LocksController.java b/src/main/java/locksdemo/LocksController.java index 68ab4a8..64eaec1 100644 --- a/src/main/java/locksdemo/LocksController.java +++ b/src/main/java/locksdemo/LocksController.java @@ -39,55 +39,57 @@ @RequiredArgsConstructor(onConstructor = @_(@Autowired)) public class LocksController { - private final LockService service; + private final LockService service; - @RequestMapping(method = RequestMethod.GET) - public Iterable locks() { - return service.findAll(); - } + @RequestMapping(method = RequestMethod.GET) + public Iterable locks() { + return service.findAll(); + } - @RequestMapping(value = "{name}", method = RequestMethod.POST) - public Lock create(@PathVariable String name) { - return service.create(name); - } + @RequestMapping(value = "{name}", method = RequestMethod.POST) + public Lock create(@PathVariable String name) { + return service.create(name); + } - @RequestMapping(value = "{name}/{value}", method = RequestMethod.DELETE) - public Map release(@PathVariable String name, @PathVariable String value) { - if (!service.release(name, value)) { - throw new NoSuchLockException(); - } - return Collections.singletonMap("status", (Object) "OK"); - } + @RequestMapping(value = "{name}/{value}", method = RequestMethod.DELETE) + public Map release(@PathVariable String name, + @PathVariable String value) { + if (!service.release(name, value)) { + throw new NoSuchLockException(); + } + return Collections.singletonMap("status", (Object) "OK"); + } - @RequestMapping(value = "{name}/{value}", method = RequestMethod.PUT) - public Lock refresh(@PathVariable String name, @PathVariable String value) { - return service.refresh(name, value); - } + @RequestMapping(value = "{name}/{value}", method = RequestMethod.PUT) + public Lock refresh(@PathVariable String name, @PathVariable String value) { + return service.refresh(name, value); + } - @ExceptionHandler(LockExistsException.class) - @ResponseBody - public ResponseEntity> lockExists() { - Map body = new HashMap(); - body.put("status", "INVALID"); - body.put("description", "Lock already exists"); - return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); - } + @ExceptionHandler(LockExistsException.class) + @ResponseBody + public ResponseEntity> lockExists() { + Map body = new HashMap(); + body.put("status", "INVALID"); + body.put("description", "Lock already exists"); + return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); + } - @ExceptionHandler(NoSuchLockException.class) - @ResponseBody - public ResponseEntity> noSuchLock() { - Map body = new HashMap<>(); - body.put("status", "INVALID"); - body.put("description", "Lock not found"); - return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); - } + @ExceptionHandler(NoSuchLockException.class) + @ResponseBody + public ResponseEntity> noSuchLock() { + Map body = new HashMap<>(); + body.put("status", "INVALID"); + body.put("description", "Lock not found"); + return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(LockNotHeldException.class) + @ResponseBody + public ResponseEntity> lockNotHeld() { + Map body = new HashMap<>(); + body.put("status", "INVALID"); + body.put("description", "Lock not held (values do not match)"); + return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); + } - @ExceptionHandler(LockNotHeldException.class) - @ResponseBody - public ResponseEntity> lockNotHeld() { - Map body = new HashMap<>(); - body.put("status", "INVALID"); - body.put("description", "Lock not held (values do not match)"); - return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); - } } diff --git a/src/main/java/locksdemo/RedisLockService.java b/src/main/java/locksdemo/RedisLockService.java index 116b4dd..77230b7 100644 --- a/src/main/java/locksdemo/RedisLockService.java +++ b/src/main/java/locksdemo/RedisLockService.java @@ -31,83 +31,86 @@ */ public class RedisLockService implements LockService { - private static final String DEFAULT_LOCK_PREFIX = "spring.lock."; - - private String prefix = DEFAULT_LOCK_PREFIX; - - @Setter - private long expiry = 30000; // 30 seconds - - private final RedisOperations redisOperations; - - public RedisLockService(RedisConnectionFactory redisConnectionFactory) { - Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); - this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); - } - - @Override - public Iterable findAll() { - Set keys = redisOperations.keys(prefix + "*"); - Set locks = new LinkedHashSet<>(); - for (String key : keys) { - Date expires = new Date(System.currentTimeMillis() + redisOperations.getExpire(key, TimeUnit.MILLISECONDS)); - locks.add(new Lock(nameForKey(key), redisOperations.opsForValue().get(key), expires)); - } - return locks; - } - - @Override - public Lock create(String name) { - String value = UUID.randomUUID().toString(); - String key = keyForName(name); - if (!redisOperations.opsForValue().setIfAbsent(key, value)) { - throw new LockExistsException(); - } - redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); - Date expires = new Date(System.currentTimeMillis() + expiry); - return new Lock(name, value, expires); - } - - @Override - public boolean release(String name, String value) { - String stored = getValue(name); - if (value.equals(stored)) { - String key = keyForName(name); - redisOperations.delete(key); - return true; - } - if (stored != null) { - throw new LockNotHeldException(); - } - return false; - } - - @Override - public Lock refresh(String name, String value) { - String key = keyForName(name); - String stored = getValue(name); - if (value.equals(stored)) { - Date expires = new Date(System.currentTimeMillis() + expiry); - redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); - return new Lock(name, value, expires); - } - throw new LockNotHeldException(); - } - - private String getValue(String name) { - String key = keyForName(name); - return redisOperations.opsForValue().get(key); - } - - private String nameForKey(String key) { - if (!key.startsWith(prefix)) { - throw new IllegalStateException("Key (" + key + ") does not start with prefix (" + prefix + ")"); - } - return key.substring(prefix.length()); - } - - private String keyForName(String name) { - return prefix + name; - } + private static final String DEFAULT_LOCK_PREFIX = "spring.lock."; + + private String prefix = DEFAULT_LOCK_PREFIX; + + @Setter + private long expiry = 30000; // 30 seconds + + private final RedisOperations redisOperations; + + public RedisLockService(RedisConnectionFactory redisConnectionFactory) { + Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); + this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); + } + + @Override + public Iterable findAll() { + Set keys = redisOperations.keys(prefix + "*"); + Set locks = new LinkedHashSet<>(); + for (String key : keys) { + Date expires = new Date(System.currentTimeMillis() + + redisOperations.getExpire(key, TimeUnit.MILLISECONDS)); + locks.add(new Lock(nameForKey(key), redisOperations.opsForValue().get(key), + expires)); + } + return locks; + } + + @Override + public Lock create(String name) { + String value = UUID.randomUUID().toString(); + String key = keyForName(name); + if (!redisOperations.opsForValue().setIfAbsent(key, value)) { + throw new LockExistsException(); + } + redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); + Date expires = new Date(System.currentTimeMillis() + expiry); + return new Lock(name, value, expires); + } + + @Override + public boolean release(String name, String value) { + String stored = getValue(name); + if (value.equals(stored)) { + String key = keyForName(name); + redisOperations.delete(key); + return true; + } + if (stored != null) { + throw new LockNotHeldException(); + } + return false; + } + + @Override + public Lock refresh(String name, String value) { + String key = keyForName(name); + String stored = getValue(name); + if (value.equals(stored)) { + Date expires = new Date(System.currentTimeMillis() + expiry); + redisOperations.expire(key, expiry, TimeUnit.MILLISECONDS); + return new Lock(name, value, expires); + } + throw new LockNotHeldException(); + } + + private String getValue(String name) { + String key = keyForName(name); + return redisOperations.opsForValue().get(key); + } + + private String nameForKey(String key) { + if (!key.startsWith(prefix)) { + throw new IllegalStateException( + "Key (" + key + ") does not start with prefix (" + prefix + ")"); + } + return key.substring(prefix.length()); + } + + private String keyForName(String name) { + return prefix + name; + } } diff --git a/src/main/java/locksdemo/RedisUtils.java b/src/main/java/locksdemo/RedisUtils.java index 9ca6fcb..c25e8b9 100644 --- a/src/main/java/locksdemo/RedisUtils.java +++ b/src/main/java/locksdemo/RedisUtils.java @@ -46,4 +46,5 @@ static RedisOperations stringTemplate( RedisConnectionFactory redisConnectionFactory) { return new StringRedisTemplate(redisConnectionFactory); } + } diff --git a/src/main/java/locksdemo/SimpleLockService.java b/src/main/java/locksdemo/SimpleLockService.java index fcf81f1..4e6bff1 100644 --- a/src/main/java/locksdemo/SimpleLockService.java +++ b/src/main/java/locksdemo/SimpleLockService.java @@ -33,94 +33,94 @@ @ConfigurationProperties("spring.platform.lock") public class SimpleLockService implements LockService { - private final SimpleInMemoryRepository locks = new SimpleInMemoryRepository<>(); - - private final PriorityQueue ordered = new PriorityQueue<>(); - - @Setter - private long expiry = 30000; // 30 seconds - - @Override - public Iterable findAll() { - reap(); - return locks.findAll(); - } - - @Override - public Lock create(final String name) { - reap(name); - return locks.update(name, new Callback() { - @Override - public Lock modify(Lock current) { - if (locks.findOne(name) != null) { - throw new LockExistsException(); - } - return add(name, UUID.randomUUID().toString()); - } - }); - } - - @Override - public boolean release(final String name, final String value) { - reap(name); - final Lock lock = locks.findOne(name); - if (lock == null) { - return false; - } - locks.remove(name); - ordered.remove(lock); - return true; - - } - - @Override - public Lock refresh(final String name, final String value) { - return locks.update(name, new Callback() { - @Override - public Lock modify(Lock current) { - Lock lock = reap(name); - if (lock != null) { - throw new LockNotHeldException(); - } - if (!current.getValue().equals(value)) { - throw new LockNotHeldException(); - } - lock = add(name, value); - return lock; - } - }); - } - - private Lock add(String name, String value) { - Lock lock; - lock = new Lock(name, value, new Date(System.currentTimeMillis() + expiry)); - locks.set(name, lock); - ordered.add(lock); - return lock; - } - - private synchronized void reap() { - Lock lock = ordered.poll(); - while (lock != null && reap(lock.getName()) != null) { - lock = ordered.poll(); - } - if (lock != null) { - ordered.add(lock); - } - } - - private Lock reap(String name) { - Lock lock = locks.findOne(name); - if (lock == null) { - return null; - } - Date now = new Date(); - if (lock.getExpires().before(now)) { - locks.remove(lock.getName()); - ordered.remove(lock); - return lock; - } - return null; - } + private final SimpleInMemoryRepository locks = new SimpleInMemoryRepository<>(); + + private final PriorityQueue ordered = new PriorityQueue<>(); + + @Setter + private long expiry = 30000; // 30 seconds + + @Override + public Iterable findAll() { + reap(); + return locks.findAll(); + } + + @Override + public Lock create(final String name) { + reap(name); + return locks.update(name, new Callback() { + @Override + public Lock modify(Lock current) { + if (locks.findOne(name) != null) { + throw new LockExistsException(); + } + return add(name, UUID.randomUUID().toString()); + } + }); + } + + @Override + public boolean release(final String name, final String value) { + reap(name); + final Lock lock = locks.findOne(name); + if (lock == null) { + return false; + } + locks.remove(name); + ordered.remove(lock); + return true; + + } + + @Override + public Lock refresh(final String name, final String value) { + return locks.update(name, new Callback() { + @Override + public Lock modify(Lock current) { + Lock lock = reap(name); + if (lock != null) { + throw new LockNotHeldException(); + } + if (!current.getValue().equals(value)) { + throw new LockNotHeldException(); + } + lock = add(name, value); + return lock; + } + }); + } + + private Lock add(String name, String value) { + Lock lock; + lock = new Lock(name, value, new Date(System.currentTimeMillis() + expiry)); + locks.set(name, lock); + ordered.add(lock); + return lock; + } + + private synchronized void reap() { + Lock lock = ordered.poll(); + while (lock != null && reap(lock.getName()) != null) { + lock = ordered.poll(); + } + if (lock != null) { + ordered.add(lock); + } + } + + private Lock reap(String name) { + Lock lock = locks.findOne(name); + if (lock == null) { + return null; + } + Date now = new Date(); + if (lock.getExpires().before(now)) { + locks.remove(lock.getName()); + ordered.remove(lock); + return lock; + } + return null; + } } diff --git a/src/test/java/locksdemo/AbstractLockServiceTests.java b/src/test/java/locksdemo/AbstractLockServiceTests.java index f07f7a3..4778506 100644 --- a/src/test/java/locksdemo/AbstractLockServiceTests.java +++ b/src/test/java/locksdemo/AbstractLockServiceTests.java @@ -33,14 +33,14 @@ public abstract class AbstractLockServiceTests { private LockService service; protected abstract LockService getLockService(); - + protected abstract void setExpiry(long expires); - + @Before public void init() { service = getLockService(); } - + @Test public void createLock() { assertNotNull(service.create("foo")); diff --git a/src/test/java/locksdemo/ApplicationTests.java b/src/test/java/locksdemo/ApplicationTests.java index a8d8ecf..2fa6107 100644 --- a/src/test/java/locksdemo/ApplicationTests.java +++ b/src/test/java/locksdemo/ApplicationTests.java @@ -21,21 +21,23 @@ @WebAppConfiguration @IntegrationTest("server.port=0") public class ApplicationTests { - + @Value("${local.server.port}") private int port = 0; @Test public void locksLoad() { @SuppressWarnings("rawtypes") - ResponseEntity entity = new TestRestTemplate().getForEntity("http://localhost:" + port, List.class); + ResponseEntity entity = new TestRestTemplate() + .getForEntity("http://localhost:" + port, List.class); assertEquals(HttpStatus.OK, entity.getStatusCode()); } @Test public void createLock() { @SuppressWarnings("rawtypes") - ResponseEntity entity = new TestRestTemplate().postForEntity("http://localhost:" + port + "/foo", "bar", Map.class); + ResponseEntity entity = new TestRestTemplate() + .postForEntity("http://localhost:" + port + "/foo", "bar", Map.class); assertEquals(HttpStatus.OK, entity.getStatusCode()); } diff --git a/src/test/java/locksdemo/JdbcLockServiceTests.java b/src/test/java/locksdemo/JdbcLockServiceTests.java index 0eaec78..a8782cb 100644 --- a/src/test/java/locksdemo/JdbcLockServiceTests.java +++ b/src/test/java/locksdemo/JdbcLockServiceTests.java @@ -32,47 +32,49 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes=TestConfiguration.class) +@SpringApplicationConfiguration(classes = TestConfiguration.class) @IntegrationTest("spring.datasource.schema=classpath:/locks-schema.sql") public class JdbcLockServiceTests extends AbstractLockServiceTests { @Autowired private JdbcLockService service; - + @Autowired private DataSource dataSource; - + @Before public void init() { super.init(); service.setExpiry(30000); new JdbcTemplate(dataSource).update("DELETE FROM LOCKS"); } - + @Override protected LockService getLockService() { return service; } - + @Override protected void setExpiry(long expiry) { getLockService(); service.setExpiry(expiry); - } + } @Configuration - @Import({DataSourceAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class}) + @Import({ DataSourceAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class }) protected static class TestConfiguration { + @Bean public JdbcLockService lockService(DataSource dataSource) { return new JdbcLockService(dataSource); } + } - + } diff --git a/src/test/java/locksdemo/RedisLockServiceTests.java b/src/test/java/locksdemo/RedisLockServiceTests.java index e79960e..7965556 100644 --- a/src/test/java/locksdemo/RedisLockServiceTests.java +++ b/src/test/java/locksdemo/RedisLockServiceTests.java @@ -19,7 +19,6 @@ import org.junit.ClassRule; import org.springframework.data.redis.core.RedisOperations; - /** * @author Dave Syer * @@ -27,30 +26,31 @@ public class RedisLockServiceTests extends AbstractLockServiceTests { private RedisLockService service; - + @ClassRule public static RedisServer server = RedisServer.running(); - + @Before public void init() { super.init(); - RedisOperations template = RedisUtils.stringTemplate(server.getResource()); + RedisOperations template = RedisUtils + .stringTemplate(server.getResource()); template.delete("spring.lock.foo"); template.delete("spring.lock.bar"); } - + @Override protected LockService getLockService() { - if (service==null) { + if (service == null) { service = new RedisLockService(server.getResource()); } return service; } - + @Override protected void setExpiry(long expiry) { getLockService(); service.setExpiry(expiry); - } + } } diff --git a/src/test/java/locksdemo/RedisServer.java b/src/test/java/locksdemo/RedisServer.java index e5281a2..1d70d3a 100644 --- a/src/test/java/locksdemo/RedisServer.java +++ b/src/test/java/locksdemo/RedisServer.java @@ -97,9 +97,10 @@ private Statement failOrSkip(Exception exception) { @Override public void evaluate() throws Throwable { - Assume.assumeTrue("Skipping test due to " - + RedisServer.this.resourceDescription - + " not being available", false); + Assume.assumeTrue( + "Skipping test due to " + RedisServer.this.resourceDescription + + " not being available", + false); } }; } @@ -122,7 +123,6 @@ public RedisConnectionFactory getResource() { /** * Perform cleanup of the {@link #resource} field, which is guaranteed to be non null. - * * @throws Exception any exception thrown by this method will be logged and swallowed */ protected void cleanupResource() throws Exception { diff --git a/src/test/java/locksdemo/SimpleLockServiceTests.java b/src/test/java/locksdemo/SimpleLockServiceTests.java index b04c76b..467f5d8 100644 --- a/src/test/java/locksdemo/SimpleLockServiceTests.java +++ b/src/test/java/locksdemo/SimpleLockServiceTests.java @@ -15,7 +15,6 @@ */ package locksdemo; - /** * @author Dave Syer * @@ -23,15 +22,15 @@ public class SimpleLockServiceTests extends AbstractLockServiceTests { private SimpleLockService service = new SimpleLockService(); - + @Override protected LockService getLockService() { return service; } - + @Override protected void setExpiry(long expiry) { service.setExpiry(expiry); - } + } }