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.
This commit is contained in:
Dave Syer
2016-10-06 07:20:01 +02:00
parent 2ba29cea25
commit 2e0dda930d
7 changed files with 105 additions and 5 deletions

View File

@@ -17,7 +17,7 @@
</parent>
<properties>
<spring-cloud-dataflow.version>1.0.1.BUILD-SNAPSHOT</spring-cloud-dataflow.version>
<spring-cloud-dataflow.version>1.0.2.BUILD-SNAPSHOT</spring-cloud-dataflow.version>
</properties>
<dependencyManagement>

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -142,6 +142,11 @@ public class DeployerProperties {
* E.g. when eureka is disabled you might want "eureka.client.enabled=false".
*/
private Map<String, String> 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<String, String> 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<String, String> getEnabled() {
return enabled;
}
public void setEnabled(Map<String, String> 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('}');

View File

@@ -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<String, String> map = extractProperties("/" + deployable.getName() + ".yml");
for (String key : map.keySet()) {
appDefProps.put(key, map.get(key));

View File

@@ -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

View File

@@ -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
*/