Skip to content

Commit b348de8

Browse files
- Add support for java11.
- Add support for java11 testing pipeline. - Fix the dev pipeline.
1 parent fbf0e4b commit b348de8

18 files changed

+494
-76
lines changed

azure-pipelines.yml

+22-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ steps:
1111
checkLatest: true
1212
- pwsh: |
1313
Get-Command mvn
14-
displayName: 'Installing Maven'
14+
displayName: 'Check Maven is installed'
1515
- pwsh: |
1616
$buildNumber = 0
1717
if($env:APPVEYOR_REPO_TAG -eq "true") {
@@ -32,10 +32,10 @@ steps:
3232
CleanTargetFolder: true
3333
displayName: 'Copying files for artifacts'
3434
- pwsh: |
35-
.\setup-tests.ps1
35+
.\setup-tests-pipeline.ps1
3636
displayName: 'Setting tests'
3737
- pwsh: |
38-
.\run-tests.ps1
38+
.\build-run-tests-pipeline.ps1
3939
env:
4040
AzureWebJobsStorage: $(AzureWebJobsStorage)
4141
AzureWebJobsCosmosDBConnectionString: $(AzureWebJobsCosmosDBConnectionString)
@@ -47,8 +47,25 @@ steps:
4747
SBTopicSubName: $(SBTopicSubName)
4848
CosmosDBDatabaseName: $(CosmosDBDatabaseName)
4949
SBQueueName: $(SBQueueName)
50-
displayName: 'running tests'
51-
continueOnError: true
50+
displayName: 'Build & Run tests for java 8'
51+
continueOnError: false
52+
- pwsh: |
53+
.\build-run-tests-pipeline.ps1
54+
env:
55+
JAVA_HOME: 'C:\Program Files\Java\zulu-11-azure-jdk_11.33.15-11.0.4-win_x64'
56+
AzureWebJobsStorage: $(AzureWebJobsStorage)
57+
AzureWebJobsCosmosDBConnectionString: $(AzureWebJobsCosmosDBConnectionString)
58+
AzureWebJobsServiceBus: $(AzureWebJobsServiceBus)
59+
AzureWebJobsEventHubSender_2: $(AzureWebJobsEventHubSender_2)
60+
AzureWebJobsEventHubReceiver: $(AzureWebJobsEventHubReceiver)
61+
AzureWebJobsEventHubSender: $(AzureWebJobsEventHubSender)
62+
AzureWebJobsEventHubPath: $(AzureWebJobsEventHubPath)
63+
SBTopicName: $(SBTopicName)
64+
SBTopicSubName: $(SBTopicSubName)
65+
CosmosDBDatabaseName: $(CosmosDBDatabaseName)
66+
SBQueueName: $(SBQueueName)
67+
displayName: 'Build & Run tests for java 11'
68+
continueOnError: false
5269
- task: CopyFiles@2
5370
inputs:
5471
SourceFolder: '$(System.DefaultWorkingDirectory)/testResults'

build-run-tests-pipeline.ps1

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# A function that checks exit codes and fails script if an error is found
2+
function StopOnFailedExecution {
3+
if ($LastExitCode)
4+
{
5+
exit $LastExitCode
6+
}
7+
}
8+
9+
function RunTest([string] $project, [string] $description,[bool] $skipBuild = $false, $filter = $null) {
10+
Write-Host "Running test: $description" -ForegroundColor DarkCyan
11+
Write-Host "-----------------------------------------------------------------------------" -ForegroundColor DarkCyan
12+
Write-Host
13+
14+
$cmdargs = "test", "$project", "-v", "q", "-l", "trx", "-r",".\testResults"
15+
16+
if ($filter) {
17+
$cmdargs += "--filter", "$filter"
18+
}
19+
20+
& dotnet $cmdargs | Out-Host
21+
$r = $?
22+
23+
Write-Host
24+
Write-Host "-----------------------------------------------------------------------------" -ForegroundColor DarkCyan
25+
Write-Host
26+
27+
return $r
28+
}
29+
30+
$currDir = Get-Location
31+
32+
Write-Host "Building endtoendtests...."
33+
$Env:Path = $Env:Path+";$currDir\Azure.Functions.Cli"
34+
Push-Location -Path "./endtoendtests" -StackName javaWorkerDir
35+
Write-Host "Building azure-functions-maven-com.microsoft.azure.functions.endtoendtests"
36+
cmd.exe /c '.\..\mvnBuildSkipTests.bat'
37+
StopOnFailedExecution
38+
Pop-Location -StackName "javaWorkerDir"
39+
40+
$tests = @(
41+
@{project ="endtoendtests\Azure.Functions.Java.Tests.E2E\Azure.Functions.Java.Tests.E2E\Azure.Functions.Java.Tests.E2E.csproj"; description="E2E integration tests"}
42+
)
43+
44+
$success = $true
45+
$testRunSucceeded = $true
46+
47+
foreach ($test in $tests){
48+
$testRunSucceeded = RunTest $test.project $test.description $testRunSucceeded $test.filter
49+
$success = $testRunSucceeded -and $success
50+
}
51+
52+
if (-not $success) { exit 1 }
53+

endtoendtests/pom.xml

+28
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,34 @@
6767
<groupId>com.microsoft.azure.functions</groupId>
6868
<artifactId>azure-functions-java-library</artifactId>
6969
</dependency>
70+
<dependency>
71+
<groupId>org.apache.httpcomponents</groupId>
72+
<artifactId>httpclient</artifactId>
73+
<version>4.5.9</version>
74+
</dependency>
75+
<dependency>
76+
<groupId>com.google.guava</groupId>
77+
<artifactId>guava</artifactId>
78+
<version>28.1-jre</version>
79+
</dependency>
80+
<dependency>
81+
<groupId>com.h2database</groupId>
82+
<artifactId>h2</artifactId>
83+
<version>1.4.199</version>
84+
<scope>runtime</scope>
85+
</dependency>
86+
<dependency>
87+
<groupId>com.google.code.gson</groupId>
88+
<artifactId>gson</artifactId>
89+
<version>2.8.6</version>
90+
</dependency>
91+
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
92+
<dependency>
93+
<groupId>org.apache.commons</groupId>
94+
<artifactId>commons-lang3</artifactId>
95+
<version>3.10</version>
96+
</dependency>
97+
7098
</dependencies>
7199

72100
<build>

endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/HttpTriggerTests.java

+44-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@
44
import com.microsoft.azure.functions.*;
55
import java.util.*;
66

7+
import com.google.gson.Gson;
8+
import org.apache.http.HttpResponse;
9+
import org.apache.http.client.methods.HttpGet;
10+
import org.apache.http.impl.client.CloseableHttpClient;
11+
import org.apache.http.impl.client.HttpClients;
12+
13+
import java.sql.Connection;
14+
import java.sql.DriverManager;
15+
import java.sql.Statement;
16+
17+
import java.io.InputStream;
18+
import com.google.common.io.CharStreams;
19+
import java.io.IOException;
20+
import java.io.InputStreamReader;
21+
22+
import org.apache.commons.lang3.SystemUtils;
23+
724
/**
825
* Azure Functions with HTTP trigger.
926
*/
@@ -15,14 +32,28 @@ public class HttpTriggerTests {
1532
public HttpResponseMessage HttpTriggerJava(
1633
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
1734
final ExecutionContext context
18-
) {
35+
) throws Exception {
1936
context.getLogger().info("Java HTTP trigger processed a request.");
2037

2138
// Parse query parameters
2239
String query = request.getQueryParameters().get("name");
2340
String name = request.getBody().orElse(query);
2441
String readEnv = System.getenv("AzureWebJobsStorage");
2542

43+
try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test")) {
44+
try (Statement statement = connection.createStatement()) {
45+
statement.execute("select 1");
46+
}
47+
}
48+
49+
Gson a = new Gson();
50+
51+
// if(!SystemUtils.IS_JAVA_15) {
52+
// context.getLogger().info("Java version not 15");
53+
// }
54+
55+
get("https://httpstat.us/200");
56+
2657
if (name == null ) {
2758
return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
2859
}
@@ -32,6 +63,18 @@ public HttpResponseMessage HttpTriggerJava(
3263
return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
3364
}
3465

66+
private static String get(String url) throws IOException {
67+
CloseableHttpClient httpClient = HttpClients.createDefault();
68+
HttpGet httpGet = new HttpGet(url);
69+
httpGet.setHeader("Accept", "application/json");
70+
HttpResponse response = httpClient.execute(httpGet);
71+
InputStream content = response.getEntity().getContent();
72+
String body = CharStreams.toString(new InputStreamReader(content));
73+
content.close();
74+
httpClient.close();
75+
return "Response from " + url + " was: " + body;
76+
}
77+
3578
@FunctionName("HttpTriggerJavaThrows")
3679
public HttpResponseMessage HttpTriggerThrows(
3780
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
<properties>
2424
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
25-
<azure.functions.java.library.version>1.3.1-SNAPSHOT</azure.functions.java.library.version>
25+
<azure.functions.java.library.version>1.3.1</azure.functions.java.library.version>
2626
</properties>
2727

2828
<licenses>

setup-tests-pipeline.ps1

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Write-Host "$args[0]"
2+
Write-Host $args[0]
3+
4+
$skipCliDownload = $false
5+
if($args[0])
6+
{
7+
$skipCliDownload = $args[0]
8+
}
9+
Write-Host $skipCliDownload
10+
11+
$currDir = Get-Location
12+
if(!$skipCliDownload)
13+
{
14+
Write-Host "Deleting Functions Core Tools if exists...."
15+
Remove-Item -Force ./Azure.Functions.Cli.zip -ErrorAction Ignore
16+
Remove-Item -Recurse -Force ./Azure.Functions.Cli -ErrorAction Ignore
17+
18+
Write-Host "Downloading Functions Core Tools...."
19+
Invoke-RestMethod -Uri 'https://functionsclibuilds.blob.core.windows.net/builds/3/latest/version.txt' -OutFile version.txt
20+
Write-Host "Using Functions Core Tools version: $(Get-Content -Raw version.txt)"
21+
$version = "$(Get-Content -Raw version.txt)"
22+
Remove-Item version.txt
23+
24+
if ($version -and $version.trim())
25+
{
26+
$env:CORE_TOOLS_URL = "https://functionsclibuilds.blob.core.windows.net/builds/3/latest/Azure.Functions.Cli.win-x86.zip"
27+
}
28+
Write-Host "CORE_TOOLS_URL: $env:CORE_TOOLS_URL"
29+
$output = "$currDir\Azure.Functions.Cli.zip"
30+
$wc = New-Object System.Net.WebClient
31+
$wc.DownloadFile($env:CORE_TOOLS_URL, $output)
32+
33+
Write-Host "Extracting Functions Core Tools...."
34+
Expand-Archive ".\Azure.Functions.Cli.zip" -DestinationPath ".\Azure.Functions.Cli"
35+
}
36+
Write-Host "Copying azure-functions-java-worker to Functions Host workers directory...."
37+
Get-ChildItem -Path .\target\* -Include 'azure*' -Exclude '*shaded.jar','*tests.jar' | %{ Copy-Item $_.FullName ".\Azure.Functions.Cli\workers\java\azure-functions-java-worker.jar" }
38+
Copy-Item ".\worker.config.json" ".\Azure.Functions.Cli\workers\java"
39+

setup-tests.ps1

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# A function that checks exit codes and fails script if an error is found
33
function StopOnFailedExecution {
4-
if ($LastExitCode)
5-
{
6-
exit $LastExitCode
4+
if ($LastExitCode)
5+
{
6+
exit $LastExitCode
77
}
88
}
99
Write-Host "$args[0]"
@@ -24,13 +24,14 @@ if(!$skipCliDownload)
2424
Remove-Item -Recurse -Force ./Azure.Functions.Cli -ErrorAction Ignore
2525

2626
Write-Host "Downloading Functions Core Tools...."
27-
Invoke-RestMethod -Uri 'https://functionsclibuilds.blob.core.windows.net/builds/2/latest/version.txt' -OutFile version.txt
27+
Invoke-RestMethod -Uri 'https://functionsclibuilds.blob.core.windows.net/builds/3/latest/version.txt' -OutFile version.txt
2828
Write-Host "Using Functions Core Tools version: $(Get-Content -Raw version.txt)"
29+
$version = "$(Get-Content -Raw version.txt)"
2930
Remove-Item version.txt
3031

31-
if (-not (Test-Path env:CORE_TOOLS_URL))
32-
{
33-
$env:CORE_TOOLS_URL = "https://functionsclibuilds.blob.core.windows.net/builds/2/latest/Azure.Functions.Cli.win-x86.zip"
32+
if ($version -and $version.trim())
33+
{
34+
$env:CORE_TOOLS_URL = "https://functionsclibuilds.blob.core.windows.net/builds/3/latest/Azure.Functions.Cli.win-x86.zip"
3435
}
3536
Write-Host "CORE_TOOLS_URL: $env:CORE_TOOLS_URL"
3637
$output = "$currDir\Azure.Functions.Cli.zip"
@@ -41,13 +42,13 @@ if(!$skipCliDownload)
4142
Expand-Archive ".\Azure.Functions.Cli.zip" -DestinationPath ".\Azure.Functions.Cli"
4243
}
4344
Write-Host "Copying azure-functions-java-worker to Functions Host workers directory...."
44-
Get-ChildItem -Path .\target\* -Include 'azure*' -Exclude '*shaded.jar' | %{ Copy-Item $_.FullName ".\Azure.Functions.Cli\workers\java\azure-functions-java-worker.jar" }
45+
Get-ChildItem -Path .\target\* -Include 'azure*' -Exclude '*shaded.jar','*tests.jar' | %{ Copy-Item $_.FullName ".\Azure.Functions.Cli\workers\java\azure-functions-java-worker.jar" }
4546
Copy-Item ".\worker.config.json" ".\Azure.Functions.Cli\workers\java"
4647

4748
Write-Host "Building endtoendtests...."
4849
$Env:Path = $Env:Path+";$currDir\Azure.Functions.Cli"
4950
Push-Location -Path "./endtoendtests" -StackName javaWorkerDir
50-
Write-Host "Building azure-functions-maven-com.microsoft.azure.functions.endtoendtests"
51+
Write-Host "Building azure-functions-maven-com.microsoft.azure.functions.endtoendtests"
5152
cmd.exe /c '.\..\mvnBuildSkipTests.bat'
5253
StopOnFailedExecution
5354
Pop-Location -StackName "javaWorkerDir"

src/main/java/com/microsoft/azure/functions/worker/JavaWorkerClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public JavaWorkerClient(IApplication app) {
2828
this.channel = chanBuilder.build();
2929
this.peer = new AtomicReference<>(null);
3030
this.handlerSuppliers = new HashMap<>();
31-
this.classPathProvider = new DefaultClassLoaderProvider();
31+
this.classPathProvider = new FactoryClassLoader().createClassLoaderProvider();
3232

3333
this.addHandlers();
3434
}
@@ -117,5 +117,5 @@ private synchronized void send(String requestId, MessageHandler<?, ?> marshaller
117117
private final ManagedChannel channel;
118118
private final AtomicReference<StreamingMessagePeer> peer;
119119
private final Map<StreamingMessage.ContentCase, Supplier<MessageHandler<?, ?>>> handlerSuppliers;
120-
private final DefaultClassLoaderProvider classPathProvider;
120+
private final ClassLoaderProvider classPathProvider;
121121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.microsoft.azure.functions.worker.broker;
2+
3+
import java.lang.reflect.*;
4+
import java.util.*;
5+
6+
import com.microsoft.azure.functions.worker.binding.*;
7+
import com.microsoft.azure.functions.worker.description.*;
8+
import com.microsoft.azure.functions.worker.reflect.*;
9+
import com.microsoft.azure.functions.rpc.messages.*;
10+
11+
/**
12+
* Used to executor of arbitrary Java method in any JAR using reflection.
13+
* Thread-Safety: Multiple thread.
14+
*/
15+
public class EnhancedJavaMethodExecutorImpl implements JavaMethodExecutor {
16+
public EnhancedJavaMethodExecutorImpl(FunctionMethodDescriptor descriptor, Map<String, BindingInfo> bindingInfos, ClassLoaderProvider classLoaderProvider)
17+
throws ClassNotFoundException, NoSuchMethodException
18+
{
19+
descriptor.validateMethodInfo();
20+
21+
this.classLoader = classLoaderProvider.createClassLoader();
22+
this.containingClass = getContainingClass(descriptor.getFullClassName());
23+
this.overloadResolver = new ParameterResolver();
24+
25+
for (Method method : this.containingClass.getMethods()) {
26+
if (method.getName().equals(descriptor.getMethodName())) {
27+
this.overloadResolver.addCandidate(method);
28+
}
29+
}
30+
31+
if (!this.overloadResolver.hasCandidates()) {
32+
throw new NoSuchMethodException("There are no methods named \"" + descriptor.getName() + "\" in class \"" + descriptor.getFullClassName() + "\"");
33+
}
34+
35+
if (this.overloadResolver.hasMultipleCandidates()) {
36+
throw new UnsupportedOperationException("Found more than one function with method name \"" + descriptor.getName() + "\" in class \"" + descriptor.getFullClassName() + "\"");
37+
}
38+
39+
this.bindingDefinitions = new HashMap<>();
40+
41+
for (Map.Entry<String, BindingInfo> entry : bindingInfos.entrySet()) {
42+
this.bindingDefinitions.put(entry.getKey(), new BindingDefinition(entry.getKey(), entry.getValue()));
43+
}
44+
}
45+
46+
public Map<String, BindingDefinition> getBindingDefinitions() { return this.bindingDefinitions; }
47+
48+
public ParameterResolver getOverloadResolver() { return this.overloadResolver; }
49+
50+
public void execute(BindingDataStore dataStore) throws Exception {
51+
try {
52+
Thread.currentThread().setContextClassLoader(this.classLoader);
53+
Object retValue = this.overloadResolver.resolve(dataStore)
54+
.orElseThrow(() -> new NoSuchMethodException("Cannot locate the method signature with the given input"))
55+
.invoke(() -> this.containingClass.newInstance());
56+
dataStore.setDataTargetValue(BindingDataStore.RETURN_NAME, retValue);
57+
} finally {
58+
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
59+
}
60+
}
61+
62+
private Class<?> getContainingClass(String className) throws ClassNotFoundException {
63+
return Class.forName(className, true, this.classLoader);
64+
}
65+
66+
private final Class<?> containingClass;
67+
private final ClassLoader classLoader;
68+
private final ParameterResolver overloadResolver;
69+
private final Map<String, BindingDefinition> bindingDefinitions;
70+
}

0 commit comments

Comments
 (0)