From 313f10946d6b44c77fc553bdc16af57f341ba791 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 29 Jan 2020 18:38:09 +0100 Subject: [PATCH] GH-439 Fixed main class discovery The regression was caused by filtering main classes that are @SpringVootApplication only, essentially excluding @SpringBootConfiguration Resolves #439 --- .../function/utils/FunctionClassUtils.java | 28 +++++++++----- .../utils/FunctionClassUtilsTests.java | 37 +++++++++++++++++++ .../{util => utils}/JsonMapperTests.java | 2 +- 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/FunctionClassUtilsTests.java rename spring-cloud-function-context/src/test/java/org/springframework/cloud/function/{util => utils}/JsonMapperTests.java (98%) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java index ef7533dd2..d7ba8d1d5 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2019 the original author or authors. + * Copyright 2019-2020 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. @@ -26,6 +26,7 @@ import java.util.jar.Manifest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -59,7 +60,7 @@ public final class FunctionClassUtils { return getStartClass(classLoader); } - private static Class getStartClass(ClassLoader classLoader) { + static Class getStartClass(ClassLoader classLoader) { Class mainClass = null; if (System.getenv("MAIN_CLASS") != null) { mainClass = ClassUtils.resolveClassName(System.getenv("MAIN_CLASS"), classLoader); @@ -70,10 +71,10 @@ public final class FunctionClassUtils { else { try { Class result = getStartClass( - Collections.list(classLoader.getResources(JarFile.MANIFEST_NAME))); + Collections.list(classLoader.getResources(JarFile.MANIFEST_NAME)), classLoader); if (result == null) { result = getStartClass(Collections - .list(classLoader.getResources("meta-inf/manifest.mf"))); + .list(classLoader.getResources("meta-inf/manifest.mf")), classLoader); } Assert.notNull(result, "Failed to locate main class"); mainClass = result; @@ -88,23 +89,25 @@ public final class FunctionClassUtils { return mainClass; } - private static Class getStartClass(List list) { + private static Class getStartClass(List list, ClassLoader classLoader) { logger.info("Searching manifests: " + list); for (URL url : list) { try { - logger.info("Searching manifest: " + url); - InputStream inputStream = null; + Manifest manifest = new Manifest(url.openStream()); + logger.info("Searching for start class in manifest: " + url); + if (logger.isDebugEnabled()) { + manifest.write(System.out); + } try { - Manifest manifest = new Manifest(url.openStream()); String startClassName = manifest.getMainAttributes().getValue("Start-Class"); if (!StringUtils.hasText(startClassName)) { startClassName = manifest.getMainAttributes().getValue("Main-Class"); } if (StringUtils.hasText(startClassName)) { - Class startClass = ClassUtils.forName(startClassName, FunctionClassUtils.class.getClassLoader()); - if (startClass.getDeclaredAnnotation(SpringBootApplication.class) != null) { + Class startClass = ClassUtils.forName(startClassName, classLoader); + if (isSpringBootApplication(startClass)) { logger.info("Loaded Start Class: " + startClass); return startClass; } @@ -122,4 +125,9 @@ public final class FunctionClassUtils { } return null; } + + private static boolean isSpringBootApplication(Class startClass) { + return startClass.getDeclaredAnnotation(SpringBootApplication.class) != null + || startClass.getDeclaredAnnotation(SpringBootConfiguration.class) != null; + } } diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/FunctionClassUtilsTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/FunctionClassUtilsTests.java new file mode 100644 index 000000000..24481e82f --- /dev/null +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/FunctionClassUtilsTests.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020-2020 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.function.utils; + +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Ignore; +import org.junit.jupiter.api.Test; + +public class FunctionClassUtilsTests { + + @Test + @Ignore + public void test() throws Exception { +// String fileName = "/Users/olegz/dev/workspaces/spring/spring-cloud-function/spring-cloud-function-samples/function-sample-aws/target/function-sample-aws-2.0.0.RELEASE-aws.jar"; + String fileName = "/Users/olegz/Downloads/my.spring.functions/my.spring.functions.aws/target/tmp/my.spring.functions.aws-0.0.1-SNAPSHOT.jar"; + + URLClassLoader cl = new URLClassLoader(new URL[] {new URL("file:" + fileName)}); + FunctionClassUtils.getStartClass(cl); + } + +} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java similarity index 98% rename from spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java rename to spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java index a96ddf308..cbf997ab9 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/util/JsonMapperTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.function.util; +package org.springframework.cloud.function.utils; import java.util.Arrays; import java.util.List;