GGH-431 Fixed discovery of a start class
- Ensured that FunctionClassUtils performs additional check to ensure that located star class is SpringBootApplication - Added additional lookup to look for Main-Class if nothing was found in Start-Class primarily to support Azure - Updated Azure samples - Updated documentation Resolves #431
This commit is contained in:
@@ -15,12 +15,10 @@ Example:
|
|||||||
```java
|
```java
|
||||||
public class FooHandler extends AzureSpringBootRequestHandler<Foo, Bar> {
|
public class FooHandler extends AzureSpringBootRequestHandler<Foo, Bar> {
|
||||||
@FunctionName("uppercase")
|
@FunctionName("uppercase")
|
||||||
public Bar execute(
|
public Bar execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
||||||
@HttpTrigger(name = "req", methods = { HttpMethod.GET,
|
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<Foo>> request,
|
||||||
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS)
|
ExecutionContext context) {
|
||||||
Foo foo,
|
return handleRequest(request.getBody().get(), context);
|
||||||
ExecutionContext context) {
|
|
||||||
return handleRequest(foo, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -125,7 +123,7 @@ You can run the sample locally, just like the other Spring Cloud Function sample
|
|||||||
./mvnw spring-boot:run
|
./mvnw spring-boot:run
|
||||||
---
|
---
|
||||||
|
|
||||||
and `curl -H "Content-Type: text/plain" localhost:8080/function -d '{"value": "hello foobar"}'`.
|
and `curl -H "Content-Type: text/plain" localhost:8080/api/uppercase -d '{"value": "hello foobar"}'`.
|
||||||
|
|
||||||
You will need the `az` CLI app (see https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven for more detail). To deploy the function on Azure runtime:
|
You will need the `az` CLI app (see https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven for more detail). To deploy the function on Azure runtime:
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.springframework.cloud.function.utils;
|
package org.springframework.cloud.function.utils;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.JarURLConnection;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -27,8 +26,10 @@ import java.util.jar.Manifest;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General utility class which aggregates various class-level utility functions
|
* General utility class which aggregates various class-level utility functions
|
||||||
@@ -93,15 +94,20 @@ public final class FunctionClassUtils {
|
|||||||
try {
|
try {
|
||||||
logger.info("Searching manifest: " + url);
|
logger.info("Searching manifest: " + url);
|
||||||
|
|
||||||
Manifest manifest;
|
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
try {
|
try {
|
||||||
if ("jar".equals(url.getProtocol())) {
|
Manifest manifest = new Manifest(url.openStream());
|
||||||
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
|
String startClassName = manifest.getMainAttributes().getValue("Start-Class");
|
||||||
manifest = jarConnection.getManifest();
|
if (!StringUtils.hasText(startClassName)) {
|
||||||
|
startClassName = manifest.getMainAttributes().getValue("Main-Class");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
manifest = new Manifest(url.openStream());
|
if (StringUtils.hasText(startClassName)) {
|
||||||
|
Class<?> startClass = ClassUtils.forName(startClassName, FunctionClassUtils.class.getClassLoader());
|
||||||
|
if (startClass.getDeclaredAnnotation(SpringBootApplication.class) != null) {
|
||||||
|
logger.info("Loaded Start Class: " + startClass);
|
||||||
|
return startClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -109,12 +115,6 @@ public final class FunctionClassUtils {
|
|||||||
inputStream.close();
|
inputStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String startClass = manifest.getMainAttributes().getValue("Start-Class");
|
|
||||||
if (startClass != null) {
|
|
||||||
return ClassUtils.forName(startClass, FunctionClassUtils.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.debug("Failed to determine Start-Class in manifest file of " + url, ex);
|
logger.debug("Failed to determine Start-Class in manifest file of " + url, ex);
|
||||||
|
|||||||
@@ -25,10 +25,9 @@
|
|||||||
<functionAppName>function-sample-azure</functionAppName>
|
<functionAppName>function-sample-azure</functionAppName>
|
||||||
<functionAppRegion>westus</functionAppRegion>
|
<functionAppRegion>westus</functionAppRegion>
|
||||||
<functionResourceGroup>java-function-group</functionResourceGroup>
|
<functionResourceGroup>java-function-group</functionResourceGroup>
|
||||||
<stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}
|
<stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
|
||||||
</stagingDirectory>
|
|
||||||
<start-class>example.Config</start-class>
|
<start-class>example.Config</start-class>
|
||||||
<wrapper.version>1.0.15.RELEASE</wrapper.version>
|
<wrapper.version>1.0.23.RELEASE</wrapper.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -55,7 +54,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-function-dependencies</artifactId>
|
<artifactId>spring-cloud-function-dependencies</artifactId>
|
||||||
<version>2.2.0.BUILD-SNAPSHOT</version>
|
<version>3.0.1.BUILD-SNAPSHOT</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -92,7 +91,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.microsoft.azure</groupId>
|
<groupId>com.microsoft.azure</groupId>
|
||||||
<artifactId>azure-functions-maven-plugin</artifactId>
|
<artifactId>azure-functions-maven-plugin</artifactId>
|
||||||
<version>1.0.0-beta-7</version>
|
<version>1.3.4</version>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"functionTimeout": "00:10:00"
|
"functionTimeout": "00:05:00",
|
||||||
|
"version": "2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
// @checkstyle:off
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
@@ -36,7 +35,6 @@ public class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// @checkstyle:on
|
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ package example;
|
|||||||
|
|
||||||
import com.microsoft.azure.functions.ExecutionContext;
|
import com.microsoft.azure.functions.ExecutionContext;
|
||||||
import com.microsoft.azure.functions.HttpMethod;
|
import com.microsoft.azure.functions.HttpMethod;
|
||||||
|
import com.microsoft.azure.functions.HttpRequestMessage;
|
||||||
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
|
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
|
||||||
import com.microsoft.azure.functions.annotation.FunctionName;
|
import com.microsoft.azure.functions.annotation.FunctionName;
|
||||||
import com.microsoft.azure.functions.annotation.HttpTrigger;
|
import com.microsoft.azure.functions.annotation.HttpTrigger;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHandler;
|
import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,11 +33,10 @@ import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHa
|
|||||||
public class FooHandler extends AzureSpringBootRequestHandler<Foo, Bar> {
|
public class FooHandler extends AzureSpringBootRequestHandler<Foo, Bar> {
|
||||||
|
|
||||||
@FunctionName("uppercase")
|
@FunctionName("uppercase")
|
||||||
public Bar execute(
|
public Bar execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
||||||
@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<Foo>> request,
|
||||||
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) Foo foo,
|
|
||||||
ExecutionContext context) {
|
ExecutionContext context) {
|
||||||
return handleRequest(foo, context);
|
return handleRequest(request.getBody().get(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user