From 2e0dda930dc68b8053be1ff6cde8be7fc9ddf2a8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 6 Oct 2016 07:20:01 +0200 Subject: [PATCH] Make sure dataflow server uses h2 launched by spring cloud If user runs `spring cloud dataflow h2` you'd expect the database to be used by dataflow. It's tricky to achieve, and impossible with an in-memory data store (because of the way dataflow is set up currently). This was achieved by adding a feature: each deployable can specify "enabled" (in addition to existing "disabled" feature) properties: i.e. environemnt properties that are applied to all other apps as long as this one is running. Another change here is to pass the "PATH" env var from the deployer down to deployed apps. This affects dataflow in particular because it likes to launch other apps, and it will pick the wrong Java version (for instance) if the path is not preserved. --- .../spring-cloud-launcher-dataflow/pom.xml | 2 +- .../dataflow/DataFlowApplication.java | 68 +++++++++++++++++++ .../src/main/resources/application.yml | 3 +- .../launcher/deployer/DeployerProperties.java | 14 ++++ .../launcher/deployer/DeployerThread.java | 5 ++ .../src/main/resources/cloud.yml | 12 ++++ .../cloud/launcher/h2/H2Application.java | 6 +- 7 files changed, 105 insertions(+), 5 deletions(-) diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml index 29a6fc5..bbcdfb9 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml @@ -17,7 +17,7 @@ - 1.0.1.BUILD-SNAPSHOT + 1.0.2.BUILD-SNAPSHOT diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java index eb3616c..2176996 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java +++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java @@ -16,10 +16,24 @@ package org.springframework.cloud.launcher.dataflow; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.batch.BatchDatabaseInitializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.dataflow.server.EnableDataFlowServer; +import org.springframework.cloud.dataflow.server.config.features.FeaturesProperties; +import org.springframework.cloud.dataflow.server.repository.RdbmsTaskDefinitionRepository; +import org.springframework.cloud.dataflow.server.repository.TaskDefinitionRepository; +import org.springframework.cloud.dataflow.server.repository.support.DataflowRdbmsInitializer; +import org.springframework.cloud.task.repository.support.TaskRepositoryInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; /** * @author Spencer Gibb @@ -33,4 +47,58 @@ public class DataFlowApplication { SpringApplication.run(DataFlowApplication.class, args); } + /* + * Special case for local H2 with tcp, but not in memory. Create a load of beans that + * dataflow doesn't in this case, but probably should (see + * https://github.com/spring-cloud/spring-cloud-dataflow/issues/926). + */ + @Configuration + @ConditionalOnExpression("#{'${spring.datasource.url:}'.startsWith('jdbc:h2:tcp://localhost:') && !'${spring.datasource.url:}'.contains('/mem:')}") + public static class H2ServerConfiguration { + + @Bean + public JobRepositoryFactoryBean jobRepositoryFactoryBean(DataSource dataSource, + DataSourceTransactionManager dataSourceTransactionManager) { + JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); + repositoryFactoryBean.setDataSource(dataSource); + repositoryFactoryBean.setTransactionManager(dataSourceTransactionManager); + return repositoryFactoryBean; + } + + @Bean + public BatchDatabaseInitializer batchRepositoryInitializer( + DataSource dataSource) { + return new BatchDatabaseInitializer(); + } + + @Bean + public TaskRepositoryInitializer taskRepositoryInitializer( + DataSource dataSource) { + TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer(); + taskRepositoryInitializer.setDataSource(dataSource); + return taskRepositoryInitializer; + } + + @Bean + @ConditionalOnMissingBean + public TaskDefinitionRepository taskDefinitionRepository(DataSource dataSource) + throws Exception { + return new RdbmsTaskDefinitionRepository(dataSource); + } + + @Bean + public DataSourceTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean + public DataflowRdbmsInitializer dataflowRdbmsInitializer(DataSource dataSource, + FeaturesProperties featuresProperties) { + DataflowRdbmsInitializer dataflowRdbmsInitializer = new DataflowRdbmsInitializer( + featuresProperties); + dataflowRdbmsInitializer.setDataSource(dataSource); + return dataflowRdbmsInitializer; + } + } + } diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml index 0d78565..e64aaff 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml +++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml @@ -1,6 +1,8 @@ server: port: 9393 +debug: true + eureka: instance: status-page-url-path: /dashboard #allows you to click on the link in eureka dashboard @@ -15,7 +17,6 @@ security: enabled: false management: - context-path: /admin security: enabled: false diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java index 9125074..3dfb4ca 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java +++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java @@ -142,6 +142,11 @@ public class DeployerProperties { * E.g. when eureka is disabled you might want "eureka.client.enabled=false". */ private Map disabled = new LinkedHashMap<>(); + /** + * A map of "positive" properties that apply to all apps when this one is enabled. + * E.g. when h2 is disabled you might want the JDBC URL to be used everywhere. + */ + private Map enabled = new LinkedHashMap<>(); /** * A list of java options to pass to the jvm command (e.g. java). * E.g. -Dmy.prop=myval @@ -213,6 +218,14 @@ public class DeployerProperties { this.javaOptions = javaOptions; } + public Map getEnabled() { + return enabled; + } + + public void setEnabled(Map enabled) { + this.enabled = enabled; + } + @Override public String toString() { final StringBuffer sb = new StringBuffer("Deployable{"); @@ -222,6 +235,7 @@ public class DeployerProperties { sb.append(", waitUntilStarted=").append(this.waitUntilStarted); sb.append(", order=").append(this.order); sb.append(", disabled=").append(this.disabled); + sb.append(", enabled=").append(this.disabled); sb.append(", javaOptions=").append(this.javaOptions); sb.append(", message=").append(this.message); sb.append('}'); diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java index a3ab1fe..323c8cc 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java +++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java @@ -304,6 +304,11 @@ public class DeployerThread extends Thread { appDefProps.putAll(other.getDisabled()); } } + for (Deployable other : properties.getDeployables().values()) { + if (shouldDeploy(other.getName(), properties)) { + appDefProps.putAll(other.getEnabled()); + } + } Map map = extractProperties("/" + deployable.getName() + ".yml"); for (String key : map.keySet()) { appDefProps.put(key, map.get(key)); diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml index 063fa1e..a7ed3cb 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml +++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml @@ -1,6 +1,16 @@ dt: pre: maven://org.springframework.cloud.launcher:spring-cloud-launcher- ver: ${launcher.version} + +deployer: + local: + envVarsToInherit: + - TMP + - LANG + - LANGUAGE + - LC_.* + - PATH + spring: cloud: maven: @@ -33,6 +43,8 @@ spring: message: Connect on jdbc:h2:tcp://localhost:9096/./target/test, web console at http://localhost:9095 waitUntilStarted: true order: -50 + enabled: + spring.datasource.url: jdbc:h2:tcp://localhost:9096/./target/test hystrixdashboard: coordinates: ${dt.pre}hystrixdashboard:${dt.ver} port: 7979 diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java index 2b7c731..a8b9476 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java +++ b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java @@ -16,8 +16,6 @@ package org.springframework.cloud.launcher.h2; -import java.util.concurrent.atomic.AtomicBoolean; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.h2.server.web.WebServlet; @@ -25,7 +23,7 @@ import org.h2.tools.Console; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.embedded.ServletRegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; @@ -35,6 +33,8 @@ import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; +import java.util.concurrent.atomic.AtomicBoolean; + /** * @author Spencer Gibb */