From 7298bdd48596cbbbe73a3c829ed75f3a7b16a8bc Mon Sep 17 00:00:00 2001 From: Gunnar Hillert Date: Sun, 30 Oct 2016 21:04:16 -1000 Subject: [PATCH] gh-235 Fix Sort Properties are ignored in JdbcTaskExecutionDao - Add support for sorting similar to SCDF Core's `AbstractRdbmsKeyValueRepository` Added tests on merge --- .../repository/dao/JdbcTaskExecutionDao.java | 33 ++++++--- .../dao/JdbcTaskExecutionDaoTests.java | 71 +++++++++++++++++++ 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java index 5e0c0a27..ae8bbad1 100644 --- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java +++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 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. @@ -22,10 +22,9 @@ import java.sql.Types; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.TreeSet; import javax.sql.DataSource; @@ -39,6 +38,7 @@ import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; @@ -46,12 +46,14 @@ import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** * Stores Task Execution Information to a JDBC DataSource. * * @author Glenn Renfro + * @author Gunnar Hillert */ public class JdbcTaskExecutionDao implements TaskExecutionDao { @@ -114,7 +116,7 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao { private DataSource dataSource; - private Map orderMap; + private LinkedHashMap orderMap; private DataFieldMaxValueIncrementer taskIncrementer; @@ -122,7 +124,7 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao { Assert.notNull(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource); this.dataSource = dataSource; - orderMap = new TreeMap<>(); + orderMap = new LinkedHashMap<>(); orderMap.put("START_TIME", Order.DESCENDING); orderMap.put("TASK_EXECUTION_ID", Order.DESCENDING); } @@ -323,8 +325,23 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao { if(StringUtils.hasText(whereClause)){ factoryBean.setWhereClause(whereClause); } - factoryBean.setSortKeys(orderMap); - factoryBean.setDataSource(dataSource); + final Sort sort = pageable.getSort(); + final LinkedHashMap sortOrderMap = new LinkedHashMap<>(); + + if (sort != null) { + for (Sort.Order sortOrder : sort) { + sortOrderMap.put(sortOrder.getProperty(), sortOrder.isAscending() ? Order.ASCENDING : Order.DESCENDING); + } + } + + if (!CollectionUtils.isEmpty(sortOrderMap)) { + factoryBean.setSortKeys(sortOrderMap); + } + else { + factoryBean.setSortKeys(this.orderMap); + } + + factoryBean.setDataSource(this.dataSource); PagingQueryProvider pagingQueryProvider; try { pagingQueryProvider = factoryBean.getObject(); @@ -403,7 +420,7 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao { rs.getString("ERROR_MESSAGE"), rs.getString("EXTERNAL_EXECUTION_ID")); } - + private Integer getNullableExitCode(ResultSet rs) throws SQLException { int exitCode = rs.getInt("EXIT_CODE"); return !rs.wasNull() ? exitCode : null; diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java index 6576e80a..76044ed1 100644 --- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java +++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java @@ -19,6 +19,7 @@ package org.springframework.cloud.task.repository.dao; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.UUID; import javax.sql.DataSource; @@ -31,12 +32,19 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.cloud.task.configuration.TestConfiguration; import org.springframework.cloud.task.repository.TaskExecution; +import org.springframework.cloud.task.repository.TaskRepository; import org.springframework.cloud.task.util.TestDBUtils; import org.springframework.cloud.task.util.TestVerifierUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.junit.Assert.assertEquals; + /** * Executes unit tests on JdbcTaskExecutionDao. * @@ -53,6 +61,9 @@ public class JdbcTaskExecutionDaoTests { private JdbcTaskExecutionDao dao; + @Autowired + TaskRepository repository; + @Before public void setup(){ dao = new JdbcTaskExecutionDao(dataSource); @@ -122,4 +133,64 @@ public class JdbcTaskExecutionDaoTests { expectedTaskExecution.getExitCode(), expectedTaskExecution.getEndTime(), expectedTaskExecution.getExitMessage()); } + + @Test + @DirtiesContext + public void testFindAllPageableSort() { + initializeRepositoryNotInOrder(); + Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC, + "EXTERNAL_EXECUTION_ID")); + Iterator iter = getPageIterator(0, 2, sort); + TaskExecution taskExecution = iter.next(); + assertEquals("FOO2", taskExecution.getTaskName()); + taskExecution = iter.next(); + assertEquals("FOO3", taskExecution.getTaskName()); + + iter = getPageIterator(1, 2, sort); + taskExecution = iter.next(); + assertEquals("FOO1", taskExecution.getTaskName()); + } + + @Test + @DirtiesContext + public void testFindAllDefaultSort() { + initializeRepository(); + Iterator iter = getPageIterator(0, 2, null); + TaskExecution taskExecution = iter.next(); + assertEquals("FOO1", taskExecution.getTaskName()); + taskExecution = iter.next(); + assertEquals("FOO2", taskExecution.getTaskName()); + + iter = getPageIterator(1, 2, null); + taskExecution = iter.next(); + assertEquals("FOO3", taskExecution.getTaskName()); + } + + private Iterator getPageIterator(int pageNum, int pageSize, Sort sort) { + Pageable pageable = (sort == null) ? + new PageRequest(pageNum, pageSize) : + new PageRequest(pageNum, pageSize, sort); + Page page = dao.findAll(pageable); + assertEquals(3, page.getTotalElements()); + assertEquals(2, page.getTotalPages()); + return page.iterator(); + } + + private void initializeRepository() { + repository.createTaskExecution("FOO3", + new Date(),new ArrayList(0), "externalA"); + repository.createTaskExecution("FOO2", + new Date(),new ArrayList(0), "externalB"); + repository.createTaskExecution("FOO1", + new Date(),new ArrayList(0), "externalC"); + } + + private void initializeRepositoryNotInOrder() { + repository.createTaskExecution("FOO1", + new Date(), new ArrayList(0), "externalC"); + repository.createTaskExecution("FOO2", + new Date(), new ArrayList(0), "externalA"); + repository.createTaskExecution("FOO3", + new Date(), new ArrayList(0), "externalB"); + } }