Streamline and refactor the azure and the azure-web adapters.
- Add SCF/Azure Gradle sample and docs. - Move the function-azure-di-samples into standalone projects. - Apply the name convetion and project structure for the SCF adaptes. E.g. function-sample-azure-XXX projects under the spring-cloud-function-samples root. - Remove the redudant samples. - Improve the samples docs and the Adapter generic docs. - Streamline docs. - Add azure web adapter sample and README. - Add Spring Azure Functions banner for azure and azure web adapters. - azure-web adapter fixes: - Fix issues in serverles-web ProxyHttpServletResponse implementation. - Remove the custom FunctionClassUtils utils in favor of scf-context/util/FunctionClassUtils. - Remove redundant files. - Add FunctionInvoker deprecation annotations. - Extend the time trigger sample with Retry policies example.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
=== Introduction
|
||||
|
||||
Light weight Azure Function forwarding proxy which can deploy any existing Spring Boot web application as Azure Functions.
|
||||
Infernally uses the Azure Http Trigger mapping.
|
||||
|
||||
This module is identified as the only additional dependency to the existing web-app.
|
||||
|
||||
A sample is provided in https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-web[azure-web sample]
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#### Introduction
|
||||
|
||||
This module represents a concept of a light weight AWS forwarding proxy which deploys and interacts with existing
|
||||
Spring Boot web application deployed as AWS Lambda.
|
||||
|
||||
A sample is provided in [sample](https://github.com/spring-cloud/spring-cloud-function/tree/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store) directory. It contain README and SAM template file to simplify the deployment. This module is identified as the only additional dependnecy to the existing web-app.
|
||||
|
||||
_NOTE: Although this module is AWS specific, this dependency is protocol only (not binary), therefore there is no AWS dependnecies._
|
||||
|
||||
The aformentioned proxy is identified as AWS Lambda [handler](https://github.com/spring-cloud/spring-cloud-function/blob/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store/template.yml#L14)
|
||||
|
||||
The main Spring Boot configuration file is identified as [MAIN_CLASS](https://github.com/spring-cloud/spring-cloud-function/blob/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store/template.yml#L22)
|
||||
@@ -24,10 +24,18 @@
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-function-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-function-serverless-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure.functions</groupId>
|
||||
<artifactId>azure-functions-java-library</artifactId>
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.function.serverless.web.ProxyHttpServletRequest;
|
||||
import org.springframework.cloud.function.serverless.web.ProxyHttpServletResponse;
|
||||
import org.springframework.cloud.function.serverless.web.ProxyMvc;
|
||||
import org.springframework.cloud.function.utils.FunctionClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -61,7 +62,6 @@ public class AzureWebProxyInvoker implements FunctionInstanceInjector {
|
||||
|
||||
@Override
|
||||
public <T> T getInstance(Class<T> functionClass) throws Exception {
|
||||
// System.setProperty("MAIN_CLASS", "oz.spring.petstore.PetStoreSpringAppConfig");
|
||||
this.initialize();
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-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.function.adapter.azure.web;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
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.core.KotlinDetector;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* General utility class which aggregates various class-level utility functions
|
||||
* used by the framework.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 3.0.1
|
||||
*/
|
||||
public final class FunctionClassUtils {
|
||||
|
||||
private static Log logger = LogFactory.getLog(FunctionClassUtils.class);
|
||||
|
||||
private FunctionClassUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers the start class in the currently running application.
|
||||
* The discover search order is 'MAIN_CLASS' environment property,
|
||||
* 'MAIN_CLASS' system property, META-INF/MANIFEST.MF:'Start-Class' attribute,
|
||||
* meta-inf/manifest.mf:'Start-Class' attribute.
|
||||
*
|
||||
* @return instance of Class which represent the start class of the application.
|
||||
*/
|
||||
public static Class<?> getStartClass() {
|
||||
ClassLoader classLoader = FunctionClassUtils.class.getClassLoader();
|
||||
return getStartClass(classLoader);
|
||||
}
|
||||
|
||||
static Class<?> getStartClass(ClassLoader classLoader) {
|
||||
Class<?> mainClass = null;
|
||||
if (System.getenv("MAIN_CLASS") != null) {
|
||||
mainClass = ClassUtils.resolveClassName(System.getenv("MAIN_CLASS"), classLoader);
|
||||
}
|
||||
else if (System.getProperty("MAIN_CLASS") != null) {
|
||||
mainClass = ClassUtils.resolveClassName(System.getProperty("MAIN_CLASS"), classLoader);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Class<?> result = getStartClass(
|
||||
Collections.list(classLoader.getResources(JarFile.MANIFEST_NAME)), classLoader);
|
||||
if (result == null) {
|
||||
result = getStartClass(Collections
|
||||
.list(classLoader.getResources("meta-inf/manifest.mf")), classLoader);
|
||||
}
|
||||
Assert.notNull(result, "Failed to locate main class");
|
||||
mainClass = result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to discover main class. An attempt was made to discover "
|
||||
+ "main class as 'MAIN_CLASS' environment variable, system property as well as "
|
||||
+ "entry in META-INF/MANIFEST.MF (in that order).", ex);
|
||||
}
|
||||
}
|
||||
logger.info("Main class: " + mainClass);
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
private static Class<?> getStartClass(List<URL> list, ClassLoader classLoader) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Searching manifests: " + list);
|
||||
}
|
||||
for (URL url : list) {
|
||||
try {
|
||||
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 {
|
||||
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, classLoader);
|
||||
|
||||
if (KotlinDetector.isKotlinType(startClass)) {
|
||||
PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver(classLoader);
|
||||
String packageName = startClass.getPackage().getName();
|
||||
Resource[] resources = r.getResources("classpath:" + packageName.replace(".", "/") + "/*.class");
|
||||
for (int i = 0; i < resources.length; i++) {
|
||||
Resource resource = resources[i];
|
||||
String className = packageName + "." + (resource.getFilename().replace("/", ".")).replace(".class", "");
|
||||
startClass = ClassUtils.forName(className, classLoader);
|
||||
// if (isSpringBootApplication(startClass)) {
|
||||
// logger.info("Loaded Main Kotlin Class: " + startClass);
|
||||
// return startClass;
|
||||
// }
|
||||
}
|
||||
}
|
||||
// else if (isSpringBootApplication(startClass)) {
|
||||
// logger.info("Loaded Start Class: " + startClass);
|
||||
// return startClass;
|
||||
// }
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.debug("Failed to determine Start-Class in manifest file of " + url, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// private static boolean isSpringBootApplication(Class<?> startClass) {
|
||||
// return startClass.getDeclaredAnnotation(SpringBootApplication.class) != null
|
||||
// || startClass.getDeclaredAnnotation(SpringBootConfiguration.class) != null;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
spring.banner.location=classpath:/spring-azure-function-banner.txt
|
||||
@@ -0,0 +1,8 @@
|
||||
____ _ _ _____ _ _
|
||||
/ ___| _ __ _ __(_)_ __ __ _ / \ _____ _ _ __ ___ | ___| _ _ __ ___| |_(_) ___ _ __ ___
|
||||
\___ \| '_ \| '__| | '_ \ / _` | / _ \ |_ / | | | '__/ _ \ | |_ | | | | '_ \ / __| __| |/ _ \| '_ \/ __|
|
||||
___) | |_) | | | | | | | (_| | / ___ \ / /| |_| | | | __/ | _|| |_| | | | | (__| |_| | (_) | | | \__ \
|
||||
|____/| .__/|_| |_|_| |_|\__, | /_/ \_\/___|\__,_|_| \___| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
|
||||
|_| |___/
|
||||
${application.title} ${application.version}
|
||||
Powered by Spring Boot ${spring-boot.version} and Azure Functions
|
||||
Reference in New Issue
Block a user