diff --git a/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/BootVersionsCompletionProviderTests.java b/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/BootVersionsCompletionProviderTests.java index 9a7a8bdfea..ba81e4889e 100644 --- a/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/BootVersionsCompletionProviderTests.java +++ b/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/BootVersionsCompletionProviderTests.java @@ -37,6 +37,7 @@ import org.springframework.cloud.dataflow.core.ApplicationType; import org.springframework.cloud.dataflow.core.DefaultStreamDefinitionService; import org.springframework.cloud.dataflow.core.StreamDefinitionService; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; @@ -128,7 +129,7 @@ public AppRegistryService appRegistry() { return new DefaultAppRegistryService(mock(AppRegistrationRepository.class), new AppResourceCommon(new MavenProperties(), new FileSystemResourceLoader()), - mock(DefaultAuditRecordService.class)) { + mock(DefaultAuditRecordService.class), mock(AppRegistrationDao.class)) { @Override public boolean appExist(String name, ApplicationType type) { diff --git a/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/CompletionTestsMocks.java b/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/CompletionTestsMocks.java index 5228350c25..d47d85428c 100644 --- a/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/CompletionTestsMocks.java +++ b/spring-cloud-dataflow-completion/src/test/java/org/springframework/cloud/dataflow/completion/CompletionTestsMocks.java @@ -35,6 +35,7 @@ import org.springframework.cloud.dataflow.core.ApplicationType; import org.springframework.cloud.dataflow.core.DefaultStreamDefinitionService; import org.springframework.cloud.dataflow.core.StreamDefinitionService; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; @@ -74,7 +75,7 @@ public AppRegistryService appRegistry() { return new DefaultAppRegistryService(mock(AppRegistrationRepository.class), new AppResourceCommon(new MavenProperties(), new FileSystemResourceLoader()), - mock(DefaultAuditRecordService.class)) { + mock(DefaultAuditRecordService.class), mock(AppRegistrationDao.class)) { @Override public boolean appExist(String name, ApplicationType type) { diff --git a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationDao.java b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationDao.java new file mode 100644 index 0000000000..ab48678243 --- /dev/null +++ b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationDao.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021 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. + * You may obtain a copy of the License at + * + * https://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.springframework.cloud.dataflow.registry.repository; + +import org.springframework.cloud.dataflow.core.AppRegistration; +import org.springframework.cloud.dataflow.core.ApplicationType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.lang.Nullable; + +/** + * DAO to access {@link org.springframework.cloud.dataflow.core.AppRegistration}. Contains + * predicate specific operations to make filtering based on optional parameters more + * efficient. + * + * @author Siddhant Sorann + */ +public interface AppRegistrationDao { + + /** + * Function to find all app registrations based on various optional parameters using + * predicates. + * @param type application type. + * @param name application name. + * @param version application version. + * @param defaultVersion default version. + * @param pageable enumerates the data to be returned. + * @return paginated list of filtered app registrations. + */ + Page findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion( + @Nullable ApplicationType type, @Nullable String name, @Nullable String version, boolean defaultVersion, + Pageable pageable); + +} diff --git a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationRepository.java b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationRepository.java index 8e09070d04..08c8a06e4c 100644 --- a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationRepository.java +++ b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/AppRegistrationRepository.java @@ -52,6 +52,8 @@ public interface AppRegistrationRepository extends KeyValueRepository findAllByNameContainingIgnoreCaseAndDefaultVersionIsTrue(String name, Pageable pageable); + List findAllByName(String name); + @Override S save(S s); diff --git a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/JdbcAppRegistrationDao.java b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/JdbcAppRegistrationDao.java new file mode 100644 index 0000000000..72a5d6aea2 --- /dev/null +++ b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/repository/JdbcAppRegistrationDao.java @@ -0,0 +1,106 @@ +/* + * Copyright 2021 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. + * You may obtain a copy of the License at + * + * https://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.springframework.cloud.dataflow.registry.repository; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.springframework.cloud.dataflow.core.AppRegistration; +import org.springframework.cloud.dataflow.core.ApplicationType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.query.QueryUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * DAO to access {@link org.springframework.cloud.dataflow.core.AppRegistration}. Contains + * predicate specific operations to make filtering based on optional parameters more + * efficient. Implements + * {@link org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao} + * + * @author Siddhant Sorann + */ +public class JdbcAppRegistrationDao implements AppRegistrationDao { + + private final EntityManager entityManager; + + private final AppRegistrationRepository appRegistrationRepository; + + public JdbcAppRegistrationDao(EntityManager entityManager, AppRegistrationRepository appRegistrationRepository) { + Assert.notNull(entityManager, "Entity manager cannot be null"); + Assert.notNull(appRegistrationRepository, "AppRegistrationRepository cannot be null"); + this.entityManager = entityManager; + this.appRegistrationRepository = appRegistrationRepository; + } + + @Override + public Page findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion(ApplicationType type, + String name, String version, boolean defaultVersion, Pageable pageable) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(AppRegistration.class); + Root appRegistrationRoot = cq.from(AppRegistration.class); + final List predicates = new ArrayList<>(); + if (type != null) { + predicates.add(cb.equal(appRegistrationRoot.get("type"), type)); + } + if (StringUtils.hasText(name)) { + predicates.add(cb.like(cb.lower(appRegistrationRoot.get("name")), "%" + name.toLowerCase() + "%")); + } + if (StringUtils.hasText(version)) { + predicates.add(cb.equal(cb.lower(appRegistrationRoot.get("version")), version.toLowerCase())); + } + if (defaultVersion) { + predicates.add(cb.isTrue(appRegistrationRoot.get("defaultVersion"))); + } + cq.where(predicates.toArray(new Predicate[0])); + cq.orderBy(QueryUtils.toOrders(pageable.getSort(), appRegistrationRoot, cb)); + TypedQuery query = entityManager.createQuery(cq); + query.setFirstResult((int) pageable.getOffset()); + query.setMaxResults(pageable.getPageSize()); + final List resultList = query.getResultList(); + if (defaultVersion) { + resultList.forEach(appRegistration -> { + HashSet versions = appRegistrationRepository.findAllByName(appRegistration.getName()).stream() + .map(AppRegistration::getVersion).collect(Collectors.toCollection(HashSet::new)); + appRegistration.setVersions(versions); + }); + } + return new PageImpl<>(resultList, pageable, getTotalCount(cb, predicates.toArray(new Predicate[0]))); + } + + private Long getTotalCount(CriteriaBuilder criteriaBuilder, Predicate[] predicateArray) { + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); + Root root = criteriaQuery.from(AppRegistration.class); + + criteriaQuery.select(criteriaBuilder.count(root)); + criteriaQuery.where(predicateArray); + + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + +} diff --git a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/AppRegistryService.java b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/AppRegistryService.java index 19ea19a494..39d458bde0 100644 --- a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/AppRegistryService.java +++ b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/AppRegistryService.java @@ -24,6 +24,7 @@ import org.springframework.core.io.Resource; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.lang.Nullable; /** * @author Christian Tzolov @@ -206,4 +207,17 @@ default AppRegistration find(String name, ApplicationType type, String version) * @return the resource version */ String getResourceVersion(String uriString); + + /** + * Returns all app registrations based on various optional parameters. + * @param type application type + * @param name application name + * @param version application version + * @param defaultVersion application default version + * @param pageable Pagination information + * @return returns all {@link AppRegistration} versions for given name and type. Uses the + * pagination. + */ + Page findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion(@Nullable ApplicationType type, + @Nullable String name, @Nullable String version, boolean defaultVersion, Pageable pageable); } diff --git a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryService.java b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryService.java index 4ff381dee8..5717e232e2 100644 --- a/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryService.java +++ b/spring-cloud-dataflow-registry/src/main/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryService.java @@ -39,6 +39,7 @@ import org.springframework.cloud.dataflow.core.ApplicationType; import org.springframework.cloud.dataflow.core.AuditActionType; import org.springframework.cloud.dataflow.core.AuditOperationType; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.support.AppResourceCommon; import org.springframework.cloud.dataflow.registry.support.NoSuchAppRegistrationException; @@ -81,6 +82,8 @@ public class DefaultAppRegistryService implements AppRegistryService { private final AppRegistrationRepository appRegistrationRepository; + private final AppRegistrationDao appRegistrationDao; + private AppResourceCommon appResourceCommon; protected final AuditRecordService auditRecordService; @@ -88,7 +91,8 @@ public class DefaultAppRegistryService implements AppRegistryService { protected final AuditServiceUtils auditServiceUtils; public DefaultAppRegistryService(AppRegistrationRepository appRegistrationRepository, - AppResourceCommon appResourceCommon, AuditRecordService auditRecordService) { + AppResourceCommon appResourceCommon, AuditRecordService auditRecordService, + AppRegistrationDao appRegistrationDao) { Assert.notNull(appResourceCommon, "'appResourceCommon' must not be null"); Assert.notNull(appRegistrationRepository, "'appRegistrationRepository' must not be null"); Assert.notNull(auditRecordService, "'auditRecordService' must not be null"); @@ -96,6 +100,7 @@ public DefaultAppRegistryService(AppRegistrationRepository appRegistrationReposi this.appRegistrationRepository = appRegistrationRepository; this.auditRecordService = auditRecordService; this.auditServiceUtils = new AuditServiceUtils(); + this.appRegistrationDao = appRegistrationDao; } @Override @@ -183,22 +188,25 @@ else if (StringUtils.hasText(name)) { } @Override - public Page findAllByTypeAndNameIsLikeAndDefaultVersionIsTrue(ApplicationType type, String name, Pageable pageable) { + public Page findAllByTypeAndNameIsLikeAndDefaultVersionIsTrue(ApplicationType type, String name, + Pageable pageable) { Page result = null; if (!StringUtils.hasText(name) && type == null) { result = this.appRegistrationRepository.findAllByDefaultVersionIsTrue(pageable); } else if (StringUtils.hasText(name) && type == null) { - result = this.appRegistrationRepository.findAllByNameContainingIgnoreCaseAndDefaultVersionIsTrue(name, pageable); + result = this.appRegistrationRepository.findAllByNameContainingIgnoreCaseAndDefaultVersionIsTrue(name, + pageable); } else if (StringUtils.hasText(name)) { - result = this.appRegistrationRepository.findAllByTypeAndNameContainingIgnoreCaseAndDefaultVersionIsTrue(type, name, pageable); + result = this.appRegistrationRepository + .findAllByTypeAndNameContainingIgnoreCaseAndDefaultVersionIsTrue(type, name, pageable); } else { result = this.appRegistrationRepository.findAllByTypeAndDefaultVersionIsTrue(type, pageable); } - for (AppRegistration pagedAppRegistration: result.getContent()) { - for (AppRegistration appRegistration: this.findAll()) { + for (AppRegistration pagedAppRegistration : result.getContent()) { + for (AppRegistration appRegistration : this.findAll()) { if (pagedAppRegistration.getName().equals(appRegistration.getName()) && pagedAppRegistration.getType().equals(appRegistration.getType())) { if (pagedAppRegistration.getVersions() == null) { @@ -272,7 +280,8 @@ private void populateAuditData(AuditActionType auditActionType, AppRegistration public void delete(String name, ApplicationType type, String version) { this.appRegistrationRepository.deleteAppRegistrationByNameAndTypeAndVersion(name, type, version); - populateAuditData(AuditActionType.DELETE, new AppRegistration(name, type, version, URI.create(""), URI.create(""))); + populateAuditData(AuditActionType.DELETE, + new AppRegistration(name, type, version, URI.create(""), URI.create(""))); } @Override @@ -326,6 +335,13 @@ public String getResourceVersion(String uriString) { return this.getResourceVersion(this.appResourceCommon.getResource(uriString)); } + @Override + public Page findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion(ApplicationType type, + String name, String version, boolean defaultVersion, Pageable pageable) { + return appRegistrationDao.findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion(type, name, version, + defaultVersion, pageable); + } + protected Properties loadProperties(Resource resource) { try { return PropertiesLoaderUtils.loadProperties(resource); @@ -383,9 +399,7 @@ public List importAll(boolean overwrite, Resource... resources) return registrations; } - private BiFunction, - ? super String[], - HashMap> reduceToAppRegistrations() { + private BiFunction, ? super String[], HashMap> reduceToAppRegistrations() { return (map, lineSplit) -> { String[] typeName = lineSplit[0].split("\\."); if (typeName.length < 2 || typeName.length > 3) { diff --git a/spring-cloud-dataflow-registry/src/test/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryServiceTests.java b/spring-cloud-dataflow-registry/src/test/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryServiceTests.java index f2bd076d42..9787589872 100644 --- a/spring-cloud-dataflow-registry/src/test/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryServiceTests.java +++ b/spring-cloud-dataflow-registry/src/test/java/org/springframework/cloud/dataflow/registry/service/DefaultAppRegistryServiceTests.java @@ -29,6 +29,7 @@ import org.springframework.cloud.dataflow.audit.service.DefaultAuditRecordService; import org.springframework.cloud.dataflow.core.AppRegistration; import org.springframework.cloud.dataflow.core.ApplicationType; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.support.AppResourceCommon; import org.springframework.cloud.deployer.resource.maven.MavenProperties; @@ -72,7 +73,8 @@ public class DefaultAppRegistryServiceTests { private ResourceLoader resourceLoader = new DefaultResourceLoader(); private AppRegistryService appRegistryService = new DefaultAppRegistryService(appRegistrationRepository, - new AppResourceCommon(new MavenProperties(), resourceLoader), mock(DefaultAuditRecordService.class)); + new AppResourceCommon(new MavenProperties(), resourceLoader), mock(DefaultAuditRecordService.class), mock( + AppRegistrationDao.class)); @Test public void testNotFound() { diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java index 69493297ad..6e87393c12 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java @@ -45,6 +45,7 @@ import org.springframework.cloud.dataflow.completion.TaskCompletionProvider; import org.springframework.cloud.dataflow.configuration.metadata.ApplicationConfigurationMetadataResolver; import org.springframework.cloud.dataflow.core.StreamDefinitionService; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; @@ -227,8 +228,10 @@ public AppResourceCommon appResourceCommon(@Nullable MavenProperties mavenProper @Bean public AppRegistryService appRegistryService(AppRegistrationRepository appRegistrationRepository, - AppResourceCommon appResourceCommon, AuditRecordService auditRecordService) { - return new DefaultAppRegistryService(appRegistrationRepository, appResourceCommon, auditRecordService); + AppResourceCommon appResourceCommon, AuditRecordService auditRecordService, + AppRegistrationDao appRegistrationDao) { + return new DefaultAppRegistryService(appRegistrationRepository, appResourceCommon, auditRecordService, + appRegistrationDao); } @Bean diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfiguration.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfiguration.java index bfb9782381..a8555a61a8 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfiguration.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.dataflow.server.config; +import javax.persistence.EntityManager; import javax.servlet.Filter; import javax.sql.DataSource; @@ -26,6 +27,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.dataflow.audit.service.AuditRecordService; import org.springframework.cloud.dataflow.completion.CompletionConfiguration; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; +import org.springframework.cloud.dataflow.registry.repository.JdbcAppRegistrationDao; import org.springframework.cloud.dataflow.server.config.apps.CommonApplicationProperties; import org.springframework.cloud.dataflow.server.config.features.FeaturesConfiguration; import org.springframework.cloud.dataflow.server.config.web.WebConfiguration; @@ -113,4 +117,10 @@ public AuthenticationSuccessEventListener authenticationSuccessEventListener( AuditRecordService auditRecordService) { return new AuthenticationSuccessEventListener(auditRecordService); } + + @Bean + AppRegistrationDao appRegistrationDao( + EntityManager entityManager, AppRegistrationRepository appRegistrationRepository) { + return new JdbcAppRegistrationDao(entityManager, appRegistrationRepository); + } } diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AppRegistryController.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AppRegistryController.java index 5749e3662d..c97e25d769 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AppRegistryController.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AppRegistryController.java @@ -63,6 +63,7 @@ import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -128,22 +129,22 @@ public AppRegistryController(Optional streamDefiniti * @param pageable Pagination information * @param pagedResourcesAssembler the resource assembler for app registrations * @param type the application type: source, sink, processor, task + * @param version optional application version * @param search optional findByTaskNameContains parameter * @return the list of registered applications */ - @RequestMapping(method = RequestMethod.GET) + @GetMapping @ResponseStatus(HttpStatus.OK) public PagedModel list( Pageable pageable, PagedResourcesAssembler pagedResourcesAssembler, @RequestParam(value = "type", required = false) ApplicationType type, @RequestParam(required = false) String search, + @RequestParam(required = false) String version, @RequestParam(required = false) boolean defaultVersion) { - Page pagedRegistrations = (defaultVersion) ? - this.appRegistryService.findAllByTypeAndNameIsLikeAndDefaultVersionIsTrue(type, search, pageable) - : this.appRegistryService.findAllByTypeAndNameIsLike(type, search, - pageable); + Page pagedRegistrations = this.appRegistryService + .findAllByTypeAndNameIsLikeAndVersionAndDefaultVersion(type, search, version, defaultVersion, pageable); return pagedResourcesAssembler.toModel(pagedRegistrations, this.appRegistryAssembler); } diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/completion/TabOnTapCompletionProviderTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/completion/TabOnTapCompletionProviderTests.java index 1e36195858..99c0b425de 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/completion/TabOnTapCompletionProviderTests.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/completion/TabOnTapCompletionProviderTests.java @@ -40,6 +40,7 @@ import org.springframework.cloud.dataflow.core.ApplicationType; import org.springframework.cloud.dataflow.core.StreamDefinition; import org.springframework.cloud.dataflow.core.StreamDefinitionService; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; @@ -134,7 +135,7 @@ public AppRegistryService appRegistry() { return new DefaultAppRegistryService(mock(AppRegistrationRepository.class), new AppResourceCommon(new MavenProperties(), new FileSystemResourceLoader()), - mock(DefaultAuditRecordService.class)) { + mock(DefaultAuditRecordService.class), mock(AppRegistrationDao.class)) { @Override public boolean appExist(String name, ApplicationType type) { diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java index ba1eee8fa7..32f740dd41 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; +import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @@ -48,7 +49,9 @@ import org.springframework.cloud.dataflow.configuration.metadata.container.ContainerImageMetadataResolver; import org.springframework.cloud.dataflow.core.Launcher; import org.springframework.cloud.dataflow.core.TaskPlatform; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; +import org.springframework.cloud.dataflow.registry.repository.JdbcAppRegistrationDao; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; import org.springframework.cloud.dataflow.registry.support.AppResourceCommon; @@ -380,9 +383,10 @@ public RestControllerAdvice restControllerAdvice() { @Bean @ConditionalOnMissingBean public AppRegistryService appRegistryService(AppRegistrationRepository appRegistrationRepository, - AuditRecordService auditRecordService) { + AuditRecordService auditRecordService, AppRegistrationDao appRegistrationDao) { return new DefaultAppRegistryService(appRegistrationRepository, - new AppResourceCommon(new MavenProperties(), new DefaultResourceLoader()), auditRecordService); + new AppResourceCommon(new MavenProperties(), new DefaultResourceLoader()), auditRecordService, + appRegistrationDao); } @Bean @@ -491,4 +495,10 @@ public ScheduleInfo getSchedule(String scheduleName) { public OAuth2TokenUtilsService oauth2TokenUtilsService() { return mock(OAuth2TokenUtilsService.class); } + + @Bean + public AppRegistrationDao appRegistrationDao(EntityManager entityManager, + AppRegistrationRepository appRegistrationRepository) { + return new JdbcAppRegistrationDao(entityManager, appRegistrationRepository); + } } diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java index a1f8eba332..d66d8af2ec 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java @@ -24,6 +24,7 @@ import java.util.Optional; import java.util.concurrent.ForkJoinPool; +import javax.persistence.EntityManager; import javax.sql.DataSource; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -58,7 +59,9 @@ import org.springframework.cloud.dataflow.core.Launcher; import org.springframework.cloud.dataflow.core.StreamDefinitionService; import org.springframework.cloud.dataflow.core.TaskPlatform; +import org.springframework.cloud.dataflow.registry.repository.AppRegistrationDao; import org.springframework.cloud.dataflow.registry.repository.AppRegistrationRepository; +import org.springframework.cloud.dataflow.registry.repository.JdbcAppRegistrationDao; import org.springframework.cloud.dataflow.registry.service.AppRegistryService; import org.springframework.cloud.dataflow.registry.service.DefaultAppRegistryService; import org.springframework.cloud.dataflow.registry.support.AppResourceCommon; @@ -410,8 +413,10 @@ public ToolsController toolsController() { @Bean public AppRegistryService appRegistryService(AppRegistrationRepository appRegistrationRepository, - AppResourceCommon appResourceService, AuditRecordService auditRecordService) { - return new DefaultAppRegistryService(appRegistrationRepository, appResourceService, auditRecordService); + AppResourceCommon appResourceService, AuditRecordService auditRecordService, + AppRegistrationDao appRegistrationDao) { + return new DefaultAppRegistryService(appRegistrationRepository, appResourceService, auditRecordService, + appRegistrationDao); } @Bean @@ -714,4 +719,11 @@ public JobInstanceController jobInstanceController() { public OAuth2TokenUtilsService oauth2TokenUtilsService() { return mock(OAuth2TokenUtilsService.class); } + + @Bean + public AppRegistrationDao appRegistrationDao(EntityManager entityManager, + AppRegistrationRepository appRegistrationRepository) { + return new JdbcAppRegistrationDao(entityManager, appRegistrationRepository); + } + } diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/AppRegistryControllerTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/AppRegistryControllerTests.java index 5fdca8b33b..1b5ba193c4 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/AppRegistryControllerTests.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/AppRegistryControllerTests.java @@ -661,4 +661,21 @@ public void testPagination() throws Exception { .andExpect(jsonPath("page.number", is(5))); } + @Test + public void testListApplicationsByVersion() throws Exception { + mockMvc.perform(get("/apps?version=1.0.0.BUILD-SNAPSHOT").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("content", hasSize(4))); + } + + @Test + public void testListApplicationsByVersionAndSearch() throws Exception { + mockMvc.perform(get("/apps?version=1.0.0.BUILD-SNAPSHOT&search=time").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("content", hasSize(2))); + mockMvc.perform(get("/apps?version=1.0.0.BUILD-SNAPSHOT&search=timestamp").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("content", hasSize(1))); + } + }