diff --git a/spring-cloud-function-deployer/pom.xml b/spring-cloud-function-deployer/pom.xml index 42c7a13d4..9eac9923c 100644 --- a/spring-cloud-function-deployer/pom.xml +++ b/spring-cloud-function-deployer/pom.xml @@ -15,7 +15,7 @@ - 1.0.0.RELEASE + 1.0.2.RELEASE diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java index 65cdd29d5..4e2c27d42 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java +++ b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java @@ -21,7 +21,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -30,24 +29,19 @@ import javax.annotation.PreDestroy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.graph.Dependency; + import org.springframework.boot.Banner.Mode; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.loader.archive.Archive; -import org.springframework.boot.loader.thin.ArchiveUtils; import org.springframework.boot.loader.thin.DependencyResolver; import org.springframework.cloud.deployer.thin.ContextRunner; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.core.SpringVersion; -import org.springframework.messaging.Message; +import org.springframework.context.support.LiveBeansView; +import org.springframework.core.io.ClassPathResource; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import reactor.core.publisher.Flux; /** * @author Dave Syer @@ -56,10 +50,6 @@ import reactor.core.publisher.Flux; // NOT a @Component (to prevent it from being scanned by the "main" application). public class ApplicationRunner implements CommandLineRunner { - private static final String DEFAULT_REACTOR_VERSION = "3.0.4.RELEASE"; - - private static final String DEFAULT_SPRING_VERSION = SpringVersion.getVersion(); - private static Log logger = LogFactory.getLog(ApplicationRunner.class); public static void main(String[] args) { @@ -84,8 +74,9 @@ public class ApplicationRunner implements CommandLineRunner { ClassUtils.overrideThreadContextClassLoader(classLoader); Class cls = classLoader.loadClass(ContextRunner.class.getName()); this.app = cls.newInstance(); - runContext(DeployedFunctionApplication.class.getName(), - Collections.emptyMap(), args); + runContext(DeployedFunctionApplication.class.getName(), Collections + .singletonMap(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME, "deployer"), + args); } catch (Exception e) { logger.error("Cannot deploy", e); @@ -93,6 +84,10 @@ public class ApplicationRunner implements CommandLineRunner { finally { ClassUtils.overrideThreadContextClassLoader(contextLoader); } + RuntimeException e = getError(); + if (e != null) { + throw e; + } } @PreDestroy @@ -100,6 +95,22 @@ public class ApplicationRunner implements CommandLineRunner { closeContext(); } + private RuntimeException getError() { + if (this.app == null) { + return null; + } + Method method = ReflectionUtils.findMethod(this.app.getClass(), "getError"); + Throwable e; + e = (Throwable) ReflectionUtils.invokeMethod(method, this.app); + if (e==null) { + return null; + } + if (e instanceof RuntimeException) { + return (RuntimeException) e; + } + return new IllegalStateException("Cannot launch", e); + } + private void runContext(String mainClass, Map properties, String... args) { Method method = ReflectionUtils.findMethod(this.app.getClass(), "run", @@ -125,14 +136,7 @@ public class ApplicationRunner implements CommandLineRunner { for (URL url : urls) { child.add(url); } - DependencyResolver resolver = DependencyResolver.instance(); - String reactor = getReactorCoordinates(); - // spring-core is OK, spring-context is not, spring-messaging depends on - // spring-context (so it is not OK) - String spring = getSpringCoordinates(); - List resolved = Arrays.asList( - resolver.resolve(new Dependency(new DefaultArtifact(reactor), "runtime")), - resolver.resolve(new Dependency(new DefaultArtifact(spring), "runtime"))); + List resolved = resolveParent(); for (File archive : resolved) { try { URL url = archive.toURI().toURL(); @@ -151,42 +155,15 @@ public class ApplicationRunner implements CommandLineRunner { return new URLClassLoader(child.toArray(new URL[0]), base); } - private String getSpringCoordinates() { - Package pkg = Message.class.getPackage(); - String version = null; - version = (pkg != null ? pkg.getImplementationVersion() : DEFAULT_SPRING_VERSION); - return "org.springframework:spring-core:" + version; - } - - private String getReactorCoordinates() { - Package pkg = Flux.class.getPackage(); - String version = null; - version = (pkg != null ? pkg.getImplementationVersion() - : DEFAULT_REACTOR_VERSION); - if (version == null) { - Archive archive = ArchiveUtils.getArchive(Flux.class); - try { - String path = archive.getUrl().toString(); - if (path.endsWith("!/")) { - path = path.substring(0, path.length() - 2); - } - path = StringUtils.getFilename(path); - if (path.startsWith("reactor-core-")) { - path = path.substring("reactor-core-".length()); - } - if (path.endsWith(".jar")) { - path = path.substring(0, path.length() - ".jar".length()); - } - version = path; - } - catch (MalformedURLException e) { - // ignore - } + private List resolveParent() { + DependencyResolver resolver = DependencyResolver.instance(); + List dependencies = resolver + .dependencies(new ClassPathResource("core-pom.xml")); + List resolved = new ArrayList<>(); + for (Dependency dependency : dependencies) { + resolved.add(resolver.resolve(dependency)); } - if (version == null) { - version = DEFAULT_REACTOR_VERSION; - } - return "io.projectreactor:reactor-core:" + version; + return resolved; } } diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionAdminController.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionAdminController.java index b7c9c3510..0d8dbee49 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionAdminController.java +++ b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionAdminController.java @@ -23,8 +23,10 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.loader.thin.ArchiveUtils; +import org.springframework.cloud.deployer.spi.app.AppDeployer; import org.springframework.cloud.deployer.spi.core.AppDefinition; import org.springframework.cloud.deployer.spi.core.AppDeploymentRequest; +import org.springframework.context.support.LiveBeansView; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.web.bind.annotation.DeleteMapping; @@ -62,10 +64,10 @@ public class FunctionAdminController implements CommandLineRunner { } @DeleteMapping(path = "/{name}") - public Map undeploy(@PathVariable String name, - @RequestParam String path) throws Exception { + public Map undeploy(@PathVariable String name) throws Exception { String id = names.get(name); if (id == null) { + // TODO: Convert to 404 throw new IllegalStateException("No such app"); } deployer.undeploy(id); @@ -78,8 +80,8 @@ public class FunctionAdminController implements CommandLineRunner { public Map deployed() { Map result = new LinkedHashMap<>(); for (String name : names.keySet()) { - result.put(name, new DeployedArtifact(name, names.get(name), - deployed.get(names.get(name)))); + String id = names.get(name); + result.put(name, new DeployedArtifact(name, id, deployed.get(id))); } return result; } @@ -93,12 +95,14 @@ public class FunctionAdminController implements CommandLineRunner { Resource resource = new FileSystemResource( ArchiveUtils.getArchiveRoot(ArchiveUtils.getArchive(path))); AppDefinition definition = new AppDefinition(resource.getFilename(), - Collections.emptyMap()); + Collections.singletonMap(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME, + "functions." + name)); AppDeploymentRequest request = new AppDeploymentRequest(definition, resource, - Collections.emptyMap(), Arrays.asList(args)); + Collections.singletonMap(AppDeployer.GROUP_PROPERTY_KEY, "functions"), + Arrays.asList(args)); String deployed = deployer.deploy(request); this.deployed.put(deployed, path); - this.names.put(deployed, name); + this.names.put(name, deployed); return deployed; } } diff --git a/spring-cloud-function-deployer/src/main/resources/core-pom.xml b/spring-cloud-function-deployer/src/main/resources/core-pom.xml new file mode 100644 index 000000000..12465fb6b --- /dev/null +++ b/spring-cloud-function-deployer/src/main/resources/core-pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + spring-cloud-function-deployer + jar + spring-cloud-function-deployer + Spring Cloud Function Web Support + + + org.springframework.boot + spring-boot-starter-parent + 1.5.3.RELEASE + + + + 3.0.7.RELEASE + + + + + org.springframework + spring-core + + + commons-logging + commons-logging + 1.2 + + + io.projectreactor + reactor-core + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Dalston.BUILD-SNAPSHOT + pom + import + + + + +