Giter VIP home page Giter VIP logo

azure-functions-java-worker's Introduction

Azure Functions Logo

Branch Status
Dev Build status
v3 Build status

Contributing

Please refer to CONTRIBUTING.md for more information.

Environment Setup

Maven

  • Run all maven commands under the root folder of this repository

IntelliJ

  • Import the root folder of this repository as an existing project in IntelliJ
  • Configure the Language level (under Project Structure -> Modules -> Sources) to 8

Eclipse

  • Set workspace to the parent folder of this repository
  • Import the root folder of this repository as an existing Maven project in Eclipse
  • Configure the project Java compiler compliance level to 1.8
  • Set the JRE libraries to JRE 1.8
  • "Ignore optional compiler problems" in "Java Build Path" for "target/generated-sources/**/*.java"

Development Cycle

Build

This is a maven based project, thus you can use any command line tools or IDEs which support maven to build it. Here we will use command line as the example (you could configure your own development environment accordingly).

To build the project, you just need to run one command from the root folder of this project:

mvn clean package

And the binary will be built to "./azure-functions-java-worker/target/azure-functions-java-worker-<version>.jar".

If you have updated the core interface (azure-functions-java-core), a mvn clean install is required for your test functions app to reference the latest core package.

Updating Dependencies and Plugins

  • Update dependencies
mvn versions:use-latest-versions
  • Update plugins
mvn versions:display-plugin-updates

For each of the plugin that displayed, update pom.xml

  • Update version
mvn release:update-versions

Debug

The Java worker alone is not enough to establish the functions app, we also need the support from Azure Functions Host. You may either use a published host CLI or use the in-development host. But both of the methods require you to attach to the java process if you want a step-by-step debugging experience.

Published Host

You can install the latest Azure functions CLI tool by:

npm install -g azure-functions-core-tools@core

By default, the binaries are located in "<Home Folder>/.azurefunctions/bin". Copy the "<Azure Functions Java Worker Root>/azure-functions-java-worker/target/azure-functions-java-worker-<version>.jar" to "<Home Folder>/.azurefunctions/bin/workers/java/azure-functions-java-worker.jar". And start it normally using:

func start

Latest Host

A developer may also use the latest host code by cloning the git repository Azure Functions Host. Now you need to navigate to the root folder of the host project and build it through:

dotnet restore WebJobs.Script.sln
dotnet build WebJobs.Script.sln

After the build succeeded, set the environment variable "AzureWebJobsScriptRoot" to the root folder path (the folder which contains the host.json) of your test functions app; and copy the "<Azure Functions Java Worker Root>/azure-functions-java-worker/target/azure-functions-java-worker-<version>.jar" to "<Azure Functions Host Root>/src/WebJobs.Script.WebHost/bin/Debug/netcoreapp2.0/workers/java/azure-functions-java-worker.jar". Now it's time to start the host:

dotnet ./src/WebJobs.Script.WebHost/bin/Debug/netcoreapp2.0/Microsoft.Azure.WebJobs.Script.WebHost.dll

Note: Remember to remove "AzureWebJobsScriptRoot" environment variable after you have finished debugging, because it will also influence the func CLI tool.

Generate JavaDoc

Simply using the following command to do so (if there are dependency errors, run mvn clean install beforehand):

mvn javadoc:javadoc

Development Notes

Java worker now shades all its jars, to introduce any new jars it is required by the developers to add a section in the pom file to relocate it.

Coding Convention

Version Management

Our version strategy just follows the maven package version convention: <major>.<minor>.<hotfix>-<prerelease>, where:

  • <major>: Increasing when incompatible breaking changes happened
  • <minor>: Increasing when new features added
  • <hotfix>: Increasing when a hotfix is pushed
  • <prerelease>: A string representing a pre-release version

Use SNAPSHOT pre-release tag for packages under development. Here is the sample workflow:

  1. Initially the package version is 1.0-SNAPSHOT. There is no hotfix for SNAPSHOT
  2. Modify the version to 1.0.0-ALPHA for internal testing purpose. Notice the hotfix exists here
  3. After several BUG fixes, update the version to 1.0.0.
  4. Create a new development version 1.1-SNAPSHOT.
  5. Make a new hotfix into 1.0-SNAPSHOT, and release to version 1.0.1.
  6. New features are added to 1.1-SNAPSHOT.

Every time you release a non-development version (like 1.0.0-ALPHA or 1.0.1), you also need to update the tag in your git repository.

Advanced Java Concepts

Reflection for Type

Primitives have two different type definitions, for example: int.class (which is identical to Integer.TYPE) is not Integer.class.

All Java types are represented by Type interface, which may be one of the following implementations:

  • Class<?>: normal class type like String
  • ParameterizedType: generic class type like List<Integer>
  • WildcardType: generic argument contains question mark like ? extends Number
  • TypeVariable<?>: generic argument like T
  • GenericArrayType: generic array like T[]

For the generic type behaviors (including compile-time validation and runtime type erasure) in Java, please refer to Generics in the Java Programming Language .

azure-functions-java-worker's People

Contributors

amamounelsayed avatar ankitkumarr avatar brunoborges avatar dependabot[bot] avatar eliaslopezgt avatar francisco-gamino avatar helayoty avatar januswu avatar jdneo avatar jonathangiles avatar kaibocai avatar kamperiadis avatar kevinhillinger avatar liliankasem avatar mhoeger avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar pragnagopa avatar safihamid avatar shreyas-gopalakrishna avatar tsuyoshiushio avatar vrdmr avatar xscript avatar yojagad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-functions-java-worker's Issues

Errors (not exceptions) cause worker timeouts

Almost certainly related to #61

Java has, sort of, three classes of "exceptional" flows, in two categories:

  1. Exceptions
    a. CheckedExceptions, which developers are supposed to know about and explicitly handle/ignore
    b. RuntimeExceptions, which developers may need to handle
  2. Errors, which usually encompass things like Out of Memory, and aren't generally supposed to be caught.

Unfortunately, any errors thrown from the function body are handled opaquely, and time out (assuming an explicit timeout has been set in the test host) . They print the following stack trace:

[2018-02-27 17:39:02] Executing 'Functions.hello' (Reason='This function was programmatically called via the host APIs.', Id=d4483b21-2eb0-4983-a660-eca104320859)
[2018-02-27 17:39:07] A ScriptHost error has occurred
[2018-02-27 17:39:07] Timeout value of 00:00:05 exceeded by function 'Functions.hello' (Id: 'd4483b21-2eb0-4983-a660-eca104320859'). Initiating cancellation.
[2018-02-27 17:39:07] Timeout value of 00:00:05 exceeded by function 'Functions.hello' (Id: 'd4483b21-2eb0-4983-a660-eca104320859'). Initiating cancellation.
[2018-02-27 17:39:07]
[2018-02-27 17:39:07] Function completed (Failure, Id=d4483b21-2eb0-4983-a660-eca104320859, Duration=5043ms)
[2018-02-27 17:39:07]
[2018-02-27 17:39:07] A ScriptHost error has occurred
[2018-02-27 17:39:07] Microsoft.Azure.WebJobs.Host: Timeout value of 00:00:05 was exceeded by function: Functions.hello.
[2018-02-27 17:39:07] Microsoft.Azure.WebJobs.Host: Timeout value of 00:00:05 was exceeded by function: Functions.hello.
[2018-02-27 17:39:07]
[2018-02-27 17:39:07] Executed 'Functions.hello' (Failed, Id=d4483b21-2eb0-4983-a660-eca104320859)
[2018-02-27 17:39:07] Microsoft.Azure.WebJobs.Host: Timeout value of 00:00:05 was exceeded by function: Functions.hello.
[2018-02-27 17:39:07] Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is 'd4483b21-2eb0-4983-a660-eca104320859'
[2018-02-27 17:39:07] Microsoft.Azure.WebJobs.Host: Timeout value of 00:00:05 was exceeded by function: Functions.hello.
[2018-02-27 17:39:09] A function timeout has occurred. Host is shutting down.
[2018-02-27 17:39:09] Microsoft.Azure.WebJobs.Host: Timeout value of 00:00:05 was exceeded by function: Functions.hello.
[2018-02-27 17:39:09] Job host stopped

Javadoc and sample consistent sample code is missing.

Javadoc is missing on a lot of code.
Please provide useful API documentation. Not "a, this is an a" kind of documentation.

I Now have to guess from .NET, NodeJS, Java Documentation and outdated blogposts on how stuff works.
This sometime breaks due to API changes.

Content Type text/html doesn't work for Java functions

Hi

When I'm trying to execute following sample I'm getting 406 error:

@FunctionName("test")
public HttpResponseMessage<String> hello(
        @HttpTrigger(name = "req", methods = {"get"},
                authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context) {

    String html = "<html><body>hello</body></html>";

    HttpResponseMessage<String> resp = request.createResponse(200, html);
    resp.addHeader("Content-Type","text/html");
    return resp;

}

Jackson serialization BUG with @JsonTypeInfo

We've updated our function to jackson 2.9.2.
After that we were still able to run it locally with Azure Functions beta.18.
After updated to Azure Functions beta.21 and run it locally or at Azure, we got the following exception:

If we delete @JsonTypeInfo it succeeds, but we will need this annotation for our application

[12/05/2017 10:08:23] ### parent JSON: {"_typeName":"com.xxx.iot.azure.xxx.discovery.Parent","parentInt":42}
[12/05/2017 10:08:23] A ScriptHost error has occurred
[12/05/2017 10:08:23] Exception while executing function: Functions.discover. System.Private.CoreLib: Result: Could not resolve type id 'com.xxx.iot.azure.xxx.discovery.Parent' as a subtype of [simple type, class com.xxx.iot.azure.xxx.discovery.Parent]: no such class found
[12/05/2017 10:08:23]  at [Source: (String)"{"_typeName":"com.xxx.iot.azure.xxx.discovery.Parent","parentInt":42}"; line: 1, column: 14]
[12/05/2017 10:08:23] Exception: Could not resolve type id 'com.xxx.iot.azure.xxx.discovery.Parent' as a subtype of [simple type, class com.xxx.iot.azure.xxx.discovery.Parent]: no such class found
[12/05/2017 10:08:23]  at [Source: (String)"{"_typeName":"com.xxx.iot.azure.xxx.discovery.Parent","parentInt":42}"; line: 1, column: 14]
[12/05/2017 10:08:23] Stack: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'com.xxx.iot.azure.xxx.discovery.Parent' as a subtype of [simple type, class com.xxx.iot.azure.xxx.discovery.Parent]: no such class found
[12/05/2017 10:08:23]  at [Source: (String)"{"_typeName":"com.xxx.iot.azure.xxx.discovery.Parent","parentInt":42}"; line: 1, column: 14]
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.DeserializationContext.invalidTypeIdException(DeserializationContext.java:1628)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownTypeId(DeserializationContext.java:1186)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver._typeFromId(ClassNameIdResolver.java:51)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:42)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:156)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:113)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1156)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
[12/05/2017 10:08:23]      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
[12/05/2017 10:08:23]      at com.xxx.iot.azure.xxx.discovery.FunctionDiscoveryDirectory.discover(FunctionDiscoveryDirectory.java:58)

Our code:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_typeName")
public class Parent {
       public int parentInt;
       public Parent() {}
       public Parent(int parentInt) {
              this.parentInt = parentInt;
       }
}

ObjectMapper mapper = new ObjectMapper();
Parent parent = new Parent(42);
String parentJson = mapper.writeValueAsString(parent); // OK
context.getLogger().info("### parent JSON: " + parentJson);
Parent parentDeserialized = mapper.readValue(parentJson, Parent.class); // com.fasterxml.jackson.databind.exc.InvalidTypeIdException
context.getLogger().info("### parent deserialized: " + parentDeserialized);

Loading Jar-files from /lib in the function app root

+ @JonathanGiles

Related to #46 This is a feature request to avoid forcing a deployment using a fat jar / uber jar for the azure-functions-java-worker.

This would be in addition to supporting the fat jar deployment, but resolves a host of support issues that will be coming in the future if this isn't implemented.

Proposed Feature

  1. support a lib folder under the function app root, just as the bin for C#
  2. add this path to the classpath when starting up the worker

This should make any jar-files available for the "function app jar".

I think this actually doesn't require any change on the part of the azure-functions-java-worker as the system classpath would end up including the lib folder, which in turn, is included in the URIClassLoader being used to resolve methods.

Implementation

Modify the JavaWorkerProvider in azure-functions-host to accept a classpath resolver.

Gist

// azure-functions-host\src\WebJobs.Script\Description\Java\JavaConstants.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Azure.WebJobs.Script.Description.Java
{
    public static class JavaConstants
    {
        public const string PrivateJarsFolderName = "lib";
    }
}

// azure-functions-host\src\WebJobs.Script\Description\Java\ClasspathResolver.cs

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.Extensions.Logging;

namespace Microsoft.Azure.WebJobs.Script.Description.Java
{
    public sealed class ClasspathResolver
    {
        private readonly string rootScriptPath;
        private readonly string libPath;
        private readonly ILogger logger;

        public ClasspathResolver(string rootScriptPath, ILogger logger)
        {
            this.libPath = GetLibDirectory(rootScriptPath);
            this.logger = logger;
        }

        public string Resolve()
        {
            return $".;{libPath}";
        }

        /// <summary>
        /// Gets the 'lib' path for a given script, so jars can be placed in the classpath
        /// </summary>
        /// <param name="baseDirectory">The path to the base directory.</param>
        /// <returns>The path to the function app's lib directory</returns>
        private static string GetLibDirectory(string baseDirectory)
        {
            var path = Path.Combine(Path.GetFullPath(baseDirectory), JavaConstants.PrivateJarsFolderName);
            return string.Concat(path, "*");
        }
    }
}

Modify the JavaWorkerProvider.TryConfigureArguments()

            if (classpathResolver != null)
            {
                var classpath = classpathResolver.Resolve();
                args.ExecutableArguments.Add("-classpath {classpath}");
            }

There's not much documentation on getting a development environment running to test this out, but I'm willing to work with a developer to get this proposed change in as a pull request to the azure-functions-host.

SLF4J hangs

If creating the sample from here: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven

When adding this to the pom.xml:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

Adding this to the Function.java file:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

And adding this to the HttpResponseMessage function:

Logger logger = LoggerFactory.getLogger(Function.class);

The function will hang on the getLogger call. Given the popularity of SLF4J, it would be great to either fix this or document that it doesn't work so time is not waited thinking something else is wrong.

Method overloading in Functions

I am triggering a function from EventHub but the message provided from event hub will vary. Is it possible to overload the methods. I am setting the point of entry to the overloaded methods in function.json.

For testing purposes I am using a HTTPTrigger and passing different message types and I get the below listed error.

Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[10/26/2017 21:56:38] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:33)
...

If I comment out one of the overloaded method then it works as expected.

Is this a right place to post such issues?

Issue can be reproducible with the code listed below.
https://github.com/brokencranium/functions-method-overloading

Ensure concurrent invocations are handled correctly

https://github.com/Azure/azure-function-java-host/blob/dev/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/HostLoggingListener.java#L53

if I'm reading this correctly, this will maintain a stack of invocations and only publish log messages from the top session

the logic to process worker logs is https://github.com/Azure/azure-webjobs-sdk-script/blob/core/src/WebJobs.Script/Description/Worker/WorkerLanguageInvoker.cs#L60 which relies on invocationId, but I'm not seeing any invocation ids in returned logs from java

JSON Validation error yields HTTP 500

minimal repro project

Start it up via the usual methods, then send:

{
	"keyValue":"asdasd"
}

(there's a missing other required property)
This should result in an HTTP 400 error. Instead, it punts back an HTTP 500:

[2018-02-23 00:16:02] A ScriptHost error has occurred
[2018-02-23 00:16:02] Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at java.base/java.util.Optional.orElseThrow(Optional.java:385)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1393)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
[2018-02-23 00:16:02] .
[2018-02-23 00:16:02] Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at java.base/java.util.Optional.orElseThrow(Optional.java:385)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1393)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
[2018-02-23 00:16:02] .
[2018-02-23 00:16:02]
[2018-02-23 00:16:02] Exception while executing function: Functions.hello
[2018-02-23 00:16:02] Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at java.base/java.util.Optional.orElseThrow(Optional.java:385)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1393)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
[2018-02-23 00:16:02] .
[2018-02-23 00:16:02] Function completed (Failure, Id=16ddb322-1f6c-45e9-9cdf-b8e73f8ff450, Duration=181ms)
[2018-02-23 00:16:02]
[2018-02-23 00:16:02] Executed 'Functions.hello' (Failed, Id=16ddb322-1f6c-45e9-9cdf-b8e73f8ff450)
[2018-02-23 00:16:02] System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at java.base/java.util.Optional.orElseThrow(Optional.java:385)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1393)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
[2018-02-23 00:16:02] .
[2018-02-23 00:16:02] Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '16ddb322-1f6c-45e9-9cdf-b8e73f8ff450'
[2018-02-23 00:16:02] System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at java.base/java.util.Optional.orElseThrow(Optional.java:385)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:58)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[2018-02-23 00:16:02] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1393)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
[2018-02-23 00:16:02] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
[2018-02-23 00:16:02] .

This also happens if you provide no fields (assuming none are required), which I'm taking more as a symptom of how things were written.

Error when passing a byte array larger than 4MB

When the Azure function contains a byte[] input parameter larger than 4MB the following error is thrown on the server side:
java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: RESOURCE_EXHAUSTED: io.grpc.netty.NettyClientTransport$3: Frame size XXX exceeds maximum: 4194304.

4MB is quite limiting when processing files for instance.
It should be possible to change the maximum message size in the gRPC by using a method parameter attribute or more globally.

Spring ApplicationContext XML not found in classpath in Azure Function even though it's there

I've a function using Spring Framework and when I try to get the ApplicationContext using ClasspathXmlApplicationContext and the following line:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

I get the following exception even tough I see the file in my function JAR's root.

[27/02/2018 20:32:03] Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '2c2dab1a-16ea-469b-98a1-32dbbde405be'
[27/02/2018 20:32:03] System.Private.CoreLib: Exception while executing function: Functions.ReadinessSyncFunction. System.Private.CoreLib: Result: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
Exception: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
Stack: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
[27/02/2018 20:32:03] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:343)
[27/02/2018 20:32:03] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:258)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:128)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:94)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:620)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:521)
[27/02/2018 20:32:03] at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144)
[27/02/2018 20:32:03] at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85)
[27/02/2018 20:32:03] at br.com.microsoft.ocp.partner.readiness.sync.Function.sync(Function.java:41)
[27/02/2018 20:32:03] Caused by: java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
[27/02/2018 20:32:03] at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:180)
[27/02/2018 20:32:03] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:329)
[27/02/2018 20:32:03] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
[27/02/2018 20:32:03] at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:258)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:128)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:94)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:620)
[27/02/2018 20:32:03] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:521)
[27/02/2018 20:32:03] at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144)
[27/02/2018 20:32:03] at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85)
[27/02/2018 20:32:03] at br.com.microsoft.ocp.partner.readiness.sync.Function.sync(Function.java:41)
[27/02/2018 20:32:03] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[27/02/2018 20:32:03] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[27/02/2018 20:32:03] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[27/02/2018 20:32:03] at java.lang.reflect.Method.invoke(Method.java:498)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.broker.JavaMethodInvokeInfo.invoke(JavaMethodInvokeInfo.java:22)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:59)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
[27/02/2018 20:32:03] at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[27/02/2018 20:32:03] at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
[27/02/2018 20:32:03] at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
[27/02/2018 20:32:03] at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
[27/02/2018 20:32:03] at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
[27/02/2018 20:32:03] at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
[27/02/2018 20:32:03] .

calling clojure from Java Azure Function ( ExceptionInInitializerError)

I had a previous issue on the same topic described in this thread. I found a solution using maven-assembly-plugin however I encountered the below issue.

Sample code.

1)the following classes

      i) import clojure.java.api.Clojure; ,
     ii) import clojure.lang.IFn;

2)compile your clojure into an uberjar then import it into the java
code.

I have opted for the 2nd option as it's more straight forward.

Here is the clojure code

(ns com.test.app.service
 (:gen-class
	   :name com.test.app.service
	   :main false
	   :methods [^{:static true} [returned [int] int]]))

	(defn returned
	  [number]
	  (* 2 number))

	(defn -returned
	  [number]
	  (returned number))

Here is the Java code.

package com.s.profile;

import java.util.*;
import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;
import com.test.app.service;


/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
	/**
	 * This function listens at endpoint "/api/hello". Two ways to invoke it using "curl" command in bash:
	 * 1. curl -d "HTTP Body" {your host}/api/hello
	 * 2. curl {your host}/api/hello?name=HTTP%20Query
	 */
	@FunctionName("hello")
	public HttpResponseMessage<String> hello(
			@HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
			final ExecutionContext context) {
		context.getLogger().info("Java HTTP trigger processed a request.");

		// Parse query parameter
		String query = request.getQueryParameters().get("name");
		String name = request.getBody().orElse(query);

		if (name == null) {
			return request.createResponse(400, "Please pass a name on the query string or in the request body");
		} else {
			service.returned(4);
			context.getLogger().info("process data" );
			return request.createResponse(200, "Hellos, " + name );
		}
	}
}

And here is the full stacktrace

    info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
		  java.lang.ExceptionInInitializerError
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.Namespace.<init>(Namespace.java:34)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.Var.internPrivate(Var.java:151)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.test.app.service.<clinit>(Unknown Source)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.s.profile.Function.hello(Function.java:42)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.lang.reflect.Method.invoke(Method.java:483)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.broker.JavaMethodInvokeInfo.invoke(JavaMethodInvokeInfo.java:22)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:59)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:43)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer$$Lambda$10/293453555.run(Unknown Source)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:902)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1689)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1644)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
		  Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath:
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.RT.load(RT.java:443)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.RT.load(RT.java:411)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.RT.doInit(RT.java:447)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]
			at clojure.lang.RT.<clinit>(RT.java:329)
	info: Worker.Java.917bfefd-b67a-49b2-b77b-6848c52c3a98[0]

The information I have on that issue is below as per the documentation.

Signals that an unexpected exception has occurred in a static initializer. An ExceptionInInitializerError is thrown to indicate that an exception occurred during evaluation of a static initializer or the initializer for a static variable.

Which static method had a problem the one in my clojure code? Seems unlikely because when I run the code from a more simple "hello world" Java example from the main function it returns fine, which leads me to believe my compiled clojure jar file is not the problem. So where is it stemming from? Are there rules behind how the azure functions work internally that limit what can get called?

Method not found returned for Java HttpTrigger with binary data

From @jeffhollan on December 2, 2017 4:19

Can't seem to find a way to successfully pass in binary data to Java function with HttpTrigger. Always says no method signature found regardless of combinations.

Repro Steps

  1. Create Function app using Maven tools for Java
  2. Add the datatype = "binary" attribute for the HttpTrigger and change the type to Byte[], byte[], or HttpRequestMessage<byte[]>
  3. Make sure method is valid and try to return any type
  4. AFter running and executing the script errors with method not found

Other notes
Verified that the function.json file being generated looks accurate. Samples below:

function.json

{
  "scriptFile" : "../helloworld2-1.0-SNAPSHOT.jar",
  "entryPoint" : "io.hollan.hello.Function.hello",
  "bindings" : [ {
    "type" : "httpTrigger",
    "name" : "req",
    "direction" : "in",
    "dataType" : "binary",
    "authLevel" : "anonymous",
    "methods" : [ "get", "post" ]
  }, {
    "type" : "http",
    "name" : "$return",
    "direction" : "out"
  } ],
  "disabled" : false
}
package io.hollan.hello;

import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    @FunctionName("hello")
    public String hello(@HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS, dataType = "binary") Byte[] req,
                                     final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        return "foo";
    }
}

Copied from original issue: Azure/azure-functions-host#2179

Rename groupId to com.microsoft.azure

Just a discussion.
Almost all packages for Azure services in Maven Central is under groupId com.microsoft.azure, except iot and servicefabric.
It might be easier for user to find and use our packages with the unified groupId com.microsoft.azure.

createResponse method on HttpResponseMessage inconvenient when no body required

The HttpRequestMessage class has a createResponse(status, body) method to return a response. This seems unfortunate when no body is required, but a header is, for example in the case of a redirect.

It would possibly be useful to have a createResponse(status) or createResponse() overloaded method, such that it is not necessary to write code such as the following (where url is duplicated or set to null - it is unclear what best practice is):

HttpResponseMessage response = request.createResponse(status, url);
response.addHeader("Location", url);
return response;

Error 406 or 500 when executing function returning HttpResponseMessage<byte[]> on Azure CLI

I am trying to implement a file download using Azure function in java. The function is:

@FunctionName("FileDownload")
@HttpOutput(name="$return", dataType = "binary")
public HttpResponseMessage<byte[]> download(@HttpTrigger(name = "req", methods = {"get"}, route = "download", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage req, ExecutionContext context) {
    try {
        byte[] bytes = "Simple text file to test download".getBytes("UTF-8");

        HttpResponseMessage<byte[]> response = req.createResponse(200, bytes);
        response.addHeader("Content-Type", "application/octet-stream");
//            response.addHeader("Content-Length", "" + bytes.length);
        response.addHeader("Content-Disposition", "attachment; filename=myfile.txt");
        return response;

    } catch (UnsupportedEncodingException e) {
        context.getLogger().warning("Invalid encoding");
    }

    return req.createResponse(200, "Invalid encoding!".getBytes());
}

Function is executed successfully as it is reported in the log:

[3/15/2018 6:45:49 AM] Function started (Id=d6b40f17-7217-4f6e-8c19-00e3025f3821)
[3/15/2018 6:45:49 AM] Executing 'Functions.FileDownload' (Reason='This function was programmatically called via the host APIs.', Id=d6b40f17-7217-4f6e-8c19-00e3025f3821)
[3/15/2018 6:45:49 AM] Function "FileDownload" (ID: 02ea5ace-c7ff-47b1-816a-03a845973936) invoked by Java Worker
[3/15/2018 6:45:49 AM] Function completed (Success, Id=d6b40f17-7217-4f6e-8c19-00e3025f3821, Duration=57ms)
[3/15/2018 6:45:49 AM] Executed 'Functions.FileDownload' (Succeeded, Id=d6b40f17-7217-4f6e-8c19-00e3025f3821)

The execution in curl produces the following:

$ curl -v http://localhost:7071/api/download
* timeout on name lookup is not supported
*   Trying ::1...
* Connected to localhost (::1) port 7071 (#0)
> GET /api/download HTTP/1.1
> Host: localhost:7071
> User-Agent: curl/7.48.0
> Accept: */*
>
< HTTP/1.1 406 Not Acceptable
< Date: Thu, 15 Mar 2018 07:56:57 GMT
< Content-Type: application/octet-stream
< Server: Kestrel
< Content-Length: 0
< Content-Disposition: attachment; filename=myfile.txt
<
* Connection #0 to host localhost left intact

When I uncomment the line where Content-Length header is set then it produces error 500.

Enable asynchronous function execution flow.

The recommendation for Azure functions is to be asynchronous (granted, in context they're clearly expecting C# given the method names), however this is not a language feature in Java. Currently, the entry and exit points for Azure Java functions must be synchronous (although I'm assuming they execute in an async context externally).

In Java, this is mostly done via libraries. In particular:

  • Returning, say, CompletableFuture<T> (for some supported types, like HttpResponseMessage) should "just work". Currently this returns:
{
    "completedExceptionally": false,
    "numberOfDependents": 0,
    "cancelled": false,
    "done": true
}
  • Starting from version 9 Java includes the Flow API. While this particular inclusion is new, this came in response to most of the major libraries that provide reactive/async capabilities in Java, meaning including it would enable consumers to use things like Akka or Reactor in their function. Functions using this capability would probably be expected to take a Publisher and return a Subscriber - that is, the functions would really be acting as a factory, not as an invocation per se.

The Flow API in particular is likely to be helpful in Azure managing resource limits and scale-out, via the inclusion of back-pressure in the system.

Files do not contain class - breaks JavaDoc

When I try to generate JavaDoc I get issues as shown below:

[ERROR] Exit code: 1 - javadoc: warning - bad source file: /Users/jonathan/Code/azure/projects/azure-javadocs/azure-functions-java-worker/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/binding/RpcComplexDataSources.java [ERROR] file does not contain class com.microsoft.azure.webjobs.script.binding.RpcComplexDataSources [ERROR] Please remove or make sure it appears in the correct subdirectory of the sourcepath. [ERROR] javadoc: warning - bad source file: /Users/jonathan/Code/azure/projects/azure-javadocs/azure-functions-java-worker/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/binding/RpcPrimitiveDataSources.java [ERROR] file does not contain class com.microsoft.azure.webjobs.script.binding.RpcPrimitiveDataSources [ERROR] Please remove or make sure it appears in the correct subdirectory of the sourcepath. [ERROR] javadoc: warning - bad source file: /Users/jonathan/Code/azure/projects/azure-javadocs/azure-functions-java-worker/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/binding/SourceAndTarget.java [ERROR] file does not contain class com.microsoft.azure.webjobs.script.binding.SourceAndTarget [ERROR] Please remove or make sure it appears in the correct subdirectory of the sourcepath. [ERROR] javadoc: warning - bad source file: /Users/jonathan/Code/azure/projects/azure-javadocs/azure-functions-java-worker/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/binding/RpcDataTargets.java

The basic issue appears to be that, for example, https://github.com/Azure/azure-functions-java-worker/blob/dev/azure-functions-java-worker/src/main/java/com/microsoft/azure/webjobs/script/binding/RpcComplexDataSources.java should contain a class called RpcComplexDataSources, but it does not.

I can create a PR that adds in non-public classes for these four files if you want.

Functions with the same package path and method name will not co-exist under the same Function App.

Symptoms

If two Functions are deployed into the same application the loader tries to find both Functions in the first Jar and the the language worker exits.

Logs

info: Host.General[0]
Starting Host (HostId=fincom-functions-201803071535451, Version=2.0.11587.0, ProcessId=5488, Debug=False, ConsecutiveErrors=0, StartupCount=1, FunctionsExtensionVersion=beta)
Found the following functions:
Host.Functions.goodbye
Host.Functions.hello
info: Host.Startup[0]
Found the following functions:
Host.Functions.goodbye
Host.Functions.hello

Job host started
info: Host.Startup[0]
Job host started
info: Host.General[0]
Host lock lease acquired by instance ID '7883d528e2f2fd79a0b584d02a135ee1'.
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
Microsoft Azure Functions Java Runtime [build 1.0.0-beta-3]
info: Host.Executor[0]
=> RequestId:0HLC53OESPDU9:00000002 RequestPath:/api/goodbye => System.Collections.Generic.Dictionary2[System.String,System.Object] => System.Collections.Generic.Dictionary2[System.String,System.Object]
Function started (Id=d0f52bf2-9be7-420f-b319-4982b5d3f8a6)
Executing 'Functions.goodbye' (Reason='This function was programmatically called via the host APIs.', Id=d0f52bf2-9be7-420f-b319-4982b5d3f8a6)
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
[INFO] {MessageHandler.handle}: Message generated by "StartStream.Builder"
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
Worker initialized
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
"goodbye" loaded (ID: ad30c8fd-e9ed-468c-a8c5-120cf943901b, Reflection: "D:\home\site\wwwroot\fincom-airport-1.0-SNAPSHOT.jar"::"com.fincom.functions.Function.goodbye")
warn: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
There are no methods named "hello" in class "com.fincom.functions.Function"
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]
[SEVERE] {Application.main}: Unexpected Exception causes system to exit
info: Worker.Java.076a6a45-e40a-4b03-a657-a9078a7baf4c[0]

Here are my POM.xml snippets.

Hello Function

<groupId>com.fincom.functions</groupId>
<artifactId>fincom-functions</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Azure Java Functions</name>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <functionAppName>fincom-functions-20180307153545156</functionAppName>
    <functionAppRegion>west europe</functionAppRegion>
</properties>

Goodbye Function

<groupId>com.fincom.functions</groupId>
<artifactId>fincom-airport</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Azure Java Functions</name>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <functionAppName>fincom-functions-20180307153545156</functionAppName>
    <functionAppRegion>west europe</functionAppRegion>
</properties>

Function,Json Snippets

For Hello

"scriptFile" : "..\fincom-functions-1.0-SNAPSHOT.jar",
"entryPoint" : "com.fincom.functions.Function.hello",

For Goodbye

"scriptFile": "..\fincom-airport-1.0-SNAPSHOT.jar",
"entryPoint": "com.fincom.functions.Function.goodbye",

Steps to repro

  1. Create a Java Function as normal.
  2. Build and Deploy.
  3. Create a second Function as step 1 and re-use the same App Name and GroupId.
  4. Deploy the second Function to the same App.
  5. Invoking either will cause the symptoms as above to happen.

Workaround

The only workaround is to not share the GroupId

Error: Host crashes on empty body when string is the input parameter

When making an HTTP request to a Java HTTP Triggered Function, it throws a 500 error. If you give it a body with a single piece of whitespace.

Repro:

Make a GET request to this following function ("http://localhost:7071")

package com.chris.functions;

import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.ExecutionContext;

/**
 * Hello function with HTTP Trigger.
 */
public class Function {
    @FunctionName("hello")
    public String hello(@HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS) String req,
                        ExecutionContext context) {
        return String.format("Hello, %s!", req);
    }
}

Error:

[10/19/2017 9:42:50 PM] Exception while executing function: Functions.hello
[10/19/2017 9:42:50 PM] Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:33)
[10/19/2017 9:42:50 PM]         at java.util.Optional.orElseThrow(Optional.java:290)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:33)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:41)
[10/19/2017 9:42:50 PM]         at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[10/19/2017 9:42:50 PM]         at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
[10/19/2017 9:42:50 PM]         at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
[10/19/2017 9:42:50 PM]         at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
[10/19/2017 9:42:50 PM]         at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
[10/19/2017 9:42:50 PM]         at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
[10/19/2017 9:42:50 PM] .
[10/19/2017 9:42:51 PM] Function completed (Failure, Id=3fd20974-19c1-4c7b-b475-d034277839be, Duration=75ms)
[10/19/2017 9:42:51 PM]
[10/19/2017 9:42:51 PM] Executed 'Functions.hello' (Failed, Id=3fd20974-19c1-4c7b-b475-d034277839be)
[10/19/2017 9:42:51 PM] System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:33)
[10/19/2017 9:42:51 PM]         at java.util.Optional.orElseThrow(Optional.java:290)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:33)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:41)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
[10/19/2017 9:42:51 PM] .
[10/19/2017 9:42:51 PM]   Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '3fd20974-19c1-4c7b-b475-d034277839be'
[10/19/2017 9:42:51 PM] System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Cannot locate the method signature with the given input
Exception: Cannot locate the method signature with the given input
Stack: java.lang.NoSuchMethodException: Cannot locate the method signature with the given input
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.lambda$execute$0(JavaMethodExecutor.java:33)
[10/19/2017 9:42:51 PM]         at java.util.Optional.orElseThrow(Optional.java:290)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:33)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:40)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.handler.MessageHandler.handle(MessageHandler.java:41)
[10/19/2017 9:42:51 PM]         at com.microsoft.azure.webjobs.script.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:84)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
[10/19/2017 9:42:51 PM]         at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

Expected:

I expect a more helpful error message or potentially supporting an null body.

I also suggest we change the sample to not support GET or use the full HTTP object.

Document "stronger" that state between functions is separated, even for static fields!

I Wrote a class DataBaseMock that mocked a database using static methods for CRUD.
It basically wraps a ConcurrentHashMap<id,MySpecialRecord>.
This class works fine according to my unit tests.

When I use the class from Azure Functions locally, a record inserted by one function is not observed by another function. I added logging that logs the number of entries in the map.
After inserting by one function the logging says there is one entry in the map.
The other function still logs that there are 0 entries in the map. So they cannot be the same map. Since the the methods and the map are static, I think some class loader trickery is used.

Suggestion add warning: "State is not shared between functions: not even if they are in the same class and not even if you play dirty with static fields and methods"

Logger access before function invocation

As a developer I want to have access to the logger when the application is started if possible.
We can customize the logging in function invocations but not on startup of the function app.
We want to add application name, version and buildhost to the log messages.
How can this be done for log messages not caused by a function invocation?

Adding version info to every log message caused by function invocation

For our functions we prefix every log message with application-version and buildhost info using the following template source:

public final class Version {

  /**
   * Name of the project.
   */
  public final static String APPLICATIONNAME = "${project.name}";

  /**
   * Version of the application.
   */
  public final static String APPLICATIONVERSION = "${project.version}";

  /**
   * The time stamp when this application was build.
   */
  public final static String BUILDTIME = "${timestamp}";

  /**
   * The host that build the application.
   */
  public final static String BUILDHOST = "${hostname}";

  /**
   * Returns a log prefix with version information.
   * 
   * @return the log prefix
   */
  public static String logPrefix() {
    return String.format("%s-%s - %s -%s", APPLICATIONNAME, APPLICATIONVERSION, BUILDTIME, BUILDHOST);
  }

  /**
   * Constructor.
   */
  private Version() {
    throw new UnsupportedOperationException();
  }
}

The buildhost is resolved using the Maven groovy plugin:

    <plugin>
      <groupId>org.codehaus.gmaven</groupId>
      <artifactId>gmaven-plugin</artifactId>
      <version>1.5</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <source>
                project.properties["hostname"] = InetAddress.getLocalHost().getHostName()
              </source>
            </configuration>
          </execution>
        </executions>
      </plugin

The version info etc in the Version class is added using the Maven templating plugin

 <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>templating-maven-plugin</artifactId>
        <version>1.0.0</version>
        <executions>
          <execution>
            <id>filter-src</id>
            <goals>
              <goal>filter-sources</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

the version info is added to every log message by adding a filter to the logger retrieved from the ExecutionContext in every Azure Function.

...
  final Logger logger = context.getLogger();
    addVersionPrefix(logger);
...

This filter is chained before any existing filter:

 public static void addVersionPrefix(final Logger logger) {
    if (isNull(logger)) {
      return;
    }
    final Filter originalFilter = logger.getFilter();
    final Filter filter = logRecord -> {
      if (logRecord == null) {
        return nonNull(originalFilter) ? originalFilter.isLoggable(logRecord) : true;
      }
      logRecord.setMessage(String.format("[%s]:%s", logPrefix(), java.util.Objects.toString(logRecord.getMessage())));
      return nonNull(originalFilter) ? originalFilter.isLoggable(logRecord) : true;
    };
    logger.setFilter(filter);
  }

Log messages show up twice in the functions runtime

Expected

As a user of the Azure Functions runtime for Java I expect log messages to show up only once.
I log a message with

   logger.log(Level.SEVERE,"This should not be produced twice: " + System.currentTimeMillis());

I expect this message to be logged once.

Actual

The message is logged twice.
Once without a '.' and once with a '.' concatenated to the message

Sample output:

1/2/2018 11:00:05 AM] Function started (Id=174ad102-d561-41ba-97cd-c35d8a3b67b9)
[1/2/2018 11:00:05 AM] Executing 'Functions.hello' (Reason='This function was programmatically called via the host APIs.', Id=174ad102-d561-41ba-97cd-c35d8a3b67b9)
[1/2/2018 11:00:05 AM] A ScriptHost error has occurred
[1/2/2018 11:00:05 AM] This should not be produced twice: 1514890805254.
[1/2/2018 11:00:05 AM] This should not be produced twice: 1514890805254
[1/2/2018 11:00:05 AM]
[1/2/2018 11:00:05 AM] Function "3a627573-bd53-48be-b23a-9921a53febbc" executed
[1/2/2018 11:00:05 AM] Function completed (Success, Id=174ad102-d561-41ba-97cd-c35d8a3b67b9, Duration=289ms)
[1/2/2018 11:00:05 AM] Executed 'Functions.hello' (Succeeded, Id=174ad102-d561-41ba-97cd-c35d8a3b67b9)

Sample code

package eu.hanskruse;

import java.util.*;
import java.util.logging.Logger;
import java.util.logging.Level;
import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;

public class Function {
    @FunctionName("hello")
    public HttpResponseMessage<String> hello(
            @HttpTrigger(name = "req", 
                                    methods = {"get", "post"},
                                    authLevel = AuthorizationLevel.ANONYMOUS) 
HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        final Logger logger = context.getLogger();
        logger.log(Level.SEVERE,"This should not be produced twice: " + System.currentTimeMillis());

        // Parse query parameter
        String name = request.getQueryParameters().get("name");
        return request.createResponse(200, "Hello, " + name);
        
    }
}

I created a Sample project to illustrate this issue. This is a simplified version of the standard generated HelloWorld Archetype.

After cloning you can build and run it with:

mvn clean package azure-functions:package azure-functions:run

The double log entries can be produced by going to the following url in a browser:
http://localhost:7071/api/hello?name=hans

Creating CosmosDB client freezes the function

We're building a Java HTTP trigger function following this doc and trying to insert into Cosmos DB Collection. Cosmos DB SDK have been correctly packaged as maven dependency.

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-documentdb</artifactId>
    <version>1.9.1</version>
</dependency>

However the call to create DocumentClient just freezes the function (both locally as well as in Azure). Same code works fine inside a regular Java Console app. Here is what we're doing

package com.fabrikam.functions;

import java.util.*;
import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;

import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.microsoft.azure.documentdb.ConsistencyLevel;
import com.microsoft.azure.documentdb.DocumentClient;

public class Function {

        private DocumentClient client;

        @FunctionName("hello")
        public HttpResponseMessage<String> hello (
                @HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
                final ExecutionContext context) {
                context.getLogger().info("Function started.");

                this.client = new DocumentClient("https://FILLME.documents.azure.com",
                        "FILLME",
                        new ConnectionPolicy(),
                        ConsistencyLevel.Session);

                context.getLogger().info("Function ended.");

                return request.createResponse(200, "Hello, Cosmos DB!");
        }
}

Log of above execution says "Function started."

Access Azure SQL

I am trying to access Azure SQL from Azure functions. To do the same I have added this dependency in in pom.xml

<dependency>
 <groupId>com.microsoft.sqlserver</groupId>
 <artifactId>mssql-jdbc</artifactId>
 <version>6.2.2.jre8</version>
 <type>jar</type>
</dependency>
 

To access the Azure SQL using JDBC, I am using

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection(connectionString);

The test case execution during mvn package works fine and I get the connection.
But during mvn azure-functions:run, I get ClassNotFoundException for com.microsoft.sqlserver.jdbc.SQLServerDriver.

Can you please let me know how to add the SQL Server jar file to Azure function package?

Regards,
Vishal Kothari

Java Console to stdout instead of stderr

Java Logger logs INFO to stderr instead of stdout.

I'd prefer to see this log to stdout via a handler - on the host side we will log process stdout to info and stderr to error as a general rule

Add Nuget Generation to build

@JunyiYi can we get nuget builds from the server? It will make it a lot easier to consume updates

Added this commit with a sample nuspec: c1b1a03

in build scripts:
nuget pack Worker.nuspec -Properties version=10000 (insert a $version$ into the nuspec version string)

We can set up the build to automatically publish to myget as well.

Currently consuming here: https://github.com/Azure/azure-webjobs-sdk-script/blob/core/src/WebJobs.Script/WebJobs.Script.csproj#L18

Nuget generation for java is currently a manual step.

A required class was missing while executing com.microsoft.azure:azure-functions-maven-plugin:0.1.10:package:

I'm facing the error A required class was missing while executing com.microsoft.azure:azure-functions-maven-plugin:0.1.10:package: org/springframework/context/ApplicationContext when using Spring framework in my functions.

Reproducer.zip
The error happens on mvn clean package and seems to be related to class scanning for annotations.

A reproducer is attached.

Full log bellow:
Reproducer.zip

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Azure Java Functions 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ ReadinessSyncFunction ---
[INFO] Deleting C:\Java\eclipse\workspace\Reproducer\target
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ ReadinessSyncFunction ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ ReadinessSyncFunction ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Java\eclipse\workspace\Reproducer\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ ReadinessSyncFunction ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Java\eclipse\workspace\Reproducer\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ ReadinessSyncFunction ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ ReadinessSyncFunction ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ ReadinessSyncFunction ---
[INFO] Building jar: C:\Java\eclipse\workspace\Reproducer\target\ReadinessSyncFunction-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- azure-functions-maven-plugin:0.1.10:package (package-functions) @ ReadinessSyncFunction ---
[INFO]
[INFO] Step 1 of 6: Searching for Azure Function entry points
[INFO] Reflections took 31 ms to scan 1 urls, producing 1 keys and 1 values
[INFO] Reflections took 0 ms to scan 1 urls, producing 1 keys and 1 values
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.753 s
[INFO] Finished at: 2018-02-27T17:47:50-03:00
[INFO] Final Memory: 52M/286M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal com.microsoft.azure:azure-functions-maven-plugin:0.1.10:package (package-functions) on project ReadinessSyncFunction: Execution package-functions of goal com.microsoft.azure:azure-functions-maven-plugin:0.1.10:package failed: A required class was missing while executing com.microsoft.azure:azure-functions-maven-plugin:0.1.10:package: org/springframework/context/ApplicationContext
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>com.microsoft.azure:azure-functions-maven-plugin:0.1.10
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-functions-maven-plugin/0.1.10/azure-functions-maven-plugin-0.1.10.jar
[ERROR] urls[1] = file:/C:/Users/user/.m2/repository/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar
[ERROR] urls[2] = file:/C:/Users/user/.m2/repository/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar
[ERROR] urls[3] = file:/C:/Users/user/.m2/repository/org/eclipse/sisu/org.eclipse.sisu.inject/0.3.0/org.eclipse.sisu.inject-0.3.0.jar
[ERROR] urls[4] = file:/C:/Users/user/.m2/repository/org/apache/maven/maven-builder-support/3.3.3/maven-builder-support-3.3.3.jar
[ERROR] urls[5] = file:/C:/Users/user/.m2/repository/org/apache/maven/maven-aether-provider/3.3.3/maven-aether-provider-3.3.3.jar
[ERROR] urls[6] = file:/C:/Users/user/.m2/repository/org/eclipse/aether/aether-util/1.0.2.v20150114/aether-util-1.0.2.v20150114.jar
[ERROR] urls[7] = file:/C:/Users/user/.m2/repository/org/sonatype/sisu/sisu-guice/3.2.5/sisu-guice-3.2.5-no_aop.jar
[ERROR] urls[8] = file:/C:/Users/user/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar
[ERROR] urls[9] = file:/C:/Users/user/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.21/plexus-interpolation-1.21.jar
[ERROR] urls[10] = file:/C:/Users/user/.m2/repository/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar
[ERROR] urls[11] = file:/C:/Users/user/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar
[ERROR] urls[12] = file:/C:/Users/user/.m2/repository/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar
[ERROR] urls[13] = file:/C:/Users/user/.m2/repository/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar
[ERROR] urls[14] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-maven-plugin-lib/0.1.7/azure-maven-plugin-lib-0.1.7.jar
[ERROR] urls[15] = file:/C:/Users/user/.m2/repository/org/apache/maven/shared/maven-filtering/3.0.0/maven-filtering-3.0.0.jar
[ERROR] urls[16] = file:/C:/Users/user/.m2/repository/org/apache/maven/shared/maven-shared-utils/3.0.0/maven-shared-utils-3.0.0.jar
[ERROR] urls[17] = file:/C:/Users/user/.m2/repository/com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.jar
[ERROR] urls[18] = file:/C:/Users/user/.m2/repository/org/sonatype/plexus/plexus-build-api/0.0.7/plexus-build-api-0.0.7.jar
[ERROR] urls[19] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure/1.2.1/azure-1.2.1.jar
[ERROR] urls[20] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-resources/1.2.1/azure-mgmt-resources-1.2.1.jar
[ERROR] urls[21] = file:/C:/Users/user/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar
[ERROR] urls[22] = file:/C:/Users/user/.m2/repository/io/reactivex/rxjava/1.2.4/rxjava-1.2.4.jar
[ERROR] urls[23] = file:/C:/Users/user/.m2/repository/org/apache/httpcomponents/httpcore/4.4.5/httpcore-4.4.5.jar
[ERROR] urls[24] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-storage/1.2.1/azure-mgmt-storage-1.2.1.jar
[ERROR] urls[25] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-network/1.2.1/azure-mgmt-network-1.2.1.jar
[ERROR] urls[26] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-compute/1.2.1/azure-mgmt-compute-1.2.1.jar
[ERROR] urls[27] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-graph-rbac/1.2.1/azure-mgmt-graph-rbac-1.2.1.jar
[ERROR] urls[28] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-keyvault/1.2.1/azure-mgmt-keyvault-1.2.1.jar
[ERROR] urls[29] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-batch/1.2.1/azure-mgmt-batch-1.2.1.jar
[ERROR] urls[30] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-trafficmanager/1.2.1/azure-mgmt-trafficmanager-1.2.1.jar
[ERROR] urls[31] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-dns/1.2.1/azure-mgmt-dns-1.2.1.jar
[ERROR] urls[32] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-redis/1.2.1/azure-mgmt-redis-1.2.1.jar
[ERROR] urls[33] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-appservice/1.2.1/azure-mgmt-appservice-1.2.1.jar
[ERROR] urls[34] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-cdn/1.2.1/azure-mgmt-cdn-1.2.1.jar
[ERROR] urls[35] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-sql/1.2.1/azure-mgmt-sql-1.2.1.jar
[ERROR] urls[36] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-containerregistry/1.2.1/azure-mgmt-containerregistry-1.2.1.jar
[ERROR] urls[37] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-cosmosdb/1.2.1/azure-mgmt-cosmosdb-1.2.1.jar
[ERROR] urls[38] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-search/1.2.1/azure-mgmt-search-1.2.1.jar
[ERROR] urls[39] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-mgmt-servicebus/1.2.1/azure-mgmt-servicebus-1.2.1.jar
[ERROR] urls[40] = file:/C:/Users/user/.m2/repository/joda-time/joda-time/2.1/joda-time-2.1.jar
[ERROR] urls[41] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-client-runtime/1.1.0/azure-client-runtime-1.1.0.jar
[ERROR] urls[42] = file:/C:/Users/user/.m2/repository/com/microsoft/rest/client-runtime/1.1.0/client-runtime-1.1.0.jar
[ERROR] urls[43] = file:/C:/Users/user/.m2/repository/com/squareup/retrofit2/retrofit/2.1.0/retrofit-2.1.0.jar
[ERROR] urls[44] = file:/C:/Users/user/.m2/repository/com/squareup/okhttp3/okhttp/3.3.1/okhttp-3.3.1.jar
[ERROR] urls[45] = file:/C:/Users/user/.m2/repository/com/squareup/okio/okio/1.8.0/okio-1.8.0.jar
[ERROR] urls[46] = file:/C:/Users/user/.m2/repository/com/squareup/okhttp3/logging-interceptor/3.3.1/logging-interceptor-3.3.1.jar
[ERROR] urls[47] = file:/C:/Users/user/.m2/repository/com/squareup/okhttp3/okhttp-urlconnection/3.3.1/okhttp-urlconnection-3.3.1.jar
[ERROR] urls[48] = file:/C:/Users/user/.m2/repository/com/squareup/retrofit2/converter-jackson/2.1.0/converter-jackson-2.1.0.jar
[ERROR] urls[49] = file:/C:/Users/user/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.7.2/jackson-databind-2.7.2.jar
[ERROR] urls[50] = file:/C:/Users/user/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-joda/2.7.2/jackson-datatype-joda-2.7.2.jar
[ERROR] urls[51] = file:/C:/Users/user/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.7.0/jackson-annotations-2.7.0.jar
[ERROR] urls[52] = file:/C:/Users/user/.m2/repository/com/squareup/retrofit2/adapter-rxjava/2.1.0/adapter-rxjava-2.1.0.jar
[ERROR] urls[53] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-client-authentication/1.1.0/azure-client-authentication-1.1.0.jar
[ERROR] urls[54] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/adal4j/1.1.2/adal4j-1.1.2.jar
[ERROR] urls[55] = file:/C:/Users/user/.m2/repository/com/nimbusds/oauth2-oidc-sdk/4.5/oauth2-oidc-sdk-4.5.jar
[ERROR] urls[56] = file:/C:/Users/user/.m2/repository/javax/mail/mail/1.4.7/mail-1.4.7.jar
[ERROR] urls[57] = file:/C:/Users/user/.m2/repository/javax/activation/activation/1.1/activation-1.1.jar
[ERROR] urls[58] = file:/C:/Users/user/.m2/repository/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0.jar
[ERROR] urls[59] = file:/C:/Users/user/.m2/repository/net/minidev/json-smart/1.1.1/json-smart-1.1.1.jar
[ERROR] urls[60] = file:/C:/Users/user/.m2/repository/com/nimbusds/lang-tag/1.4/lang-tag-1.4.jar
[ERROR] urls[61] = file:/C:/Users/user/.m2/repository/com/nimbusds/nimbus-jose-jwt/3.1.2/nimbus-jose-jwt-3.1.2.jar
[ERROR] urls[62] = file:/C:/Users/user/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.51/bcprov-jdk15on-1.51.jar
[ERROR] urls[63] = file:/C:/Users/user/.m2/repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar
[ERROR] urls[64] = file:/C:/Users/user/.m2/repository/commons-codec/commons-codec/1.10/commons-codec-1.10.jar
[ERROR] urls[65] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-annotations/1.2.0/azure-annotations-1.2.0.jar
[ERROR] urls[66] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/applicationinsights-core/1.0.9/applicationinsights-core-1.0.9.jar
[ERROR] urls[67] = file:/C:/Users/user/.m2/repository/eu/infomas/annotation-detector/3.0.4/annotation-detector-3.0.4.jar
[ERROR] urls[68] = file:/C:/Users/user/.m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar
[ERROR] urls[69] = file:/C:/Users/user/.m2/repository/org/apache/httpcomponents/httpclient/4.5.3/httpclient-4.5.3.jar
[ERROR] urls[70] = file:/C:/Users/user/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar
[ERROR] urls[71] = file:/C:/Users/user/.m2/repository/commons-net/commons-net/3.6/commons-net-3.6.jar
[ERROR] urls[72] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-functions-java-core/1.0.0-beta-2/azure-functions-java-core-1.0.0-beta-2.jar
[ERROR] urls[73] = file:/C:/Users/user/.m2/repository/org/reflections/reflections/0.9.11/reflections-0.9.11.jar
[ERROR] urls[74] = file:/C:/Users/user/.m2/repository/com/google/guava/guava/20.0/guava-20.0.jar
[ERROR] urls[75] = file:/C:/Users/user/.m2/repository/org/javassist/javassist/3.21.0-GA/javassist-3.21.0-GA.jar
[ERROR] urls[76] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-storage/5.4.0/azure-storage-5.4.0.jar
[ERROR] urls[77] = file:/C:/Users/user/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.6.0/jackson-core-2.6.0.jar
[ERROR] urls[78] = file:/C:/Users/user/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar
[ERROR] urls[79] = file:/C:/Users/user/.m2/repository/com/microsoft/azure/azure-keyvault-core/0.8.0/azure-keyvault-core-0.8.0.jar
[ERROR] urls[80] = file:/C:/Users/user/.m2/repository/org/zeroturnaround/zt-zip/1.12/zt-zip-1.12.jar
[ERROR] urls[81] = file:/C:/Users/user/.m2/repository/junit/junit/4.12/junit-4.12.jar
[ERROR] urls[82] = file:/C:/Users/user/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import from realm ClassRealm[maven.api, parent: null]]
[ERROR]
[ERROR] -----------------------------------------------------
[ERROR] : org.springframework.context.ApplicationContext
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException

Packaging of jars from private repo fails with Azure Functions Java SDK

As a developer in a project using Azure Functions I want to use the Java Azure SDK with components from private repositories.

In an Azure Functions project mvn package fails if you refer components in private repositories.

  • I want to use a self created library from my Azure Function
  • I want to use proprietary libraries within that function or another function. These libraries cannot be deployed to Maven Central or another public repository for legal reasons.

Reproduce

  1. Create an Azure Function with the Azure Functions Archetype:
    https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven
  2. create another java project that just produces a jar with an Hello World function.
  3. install the jar in your local .m2 cache
  4. Refer to it from the Function project pom file.
  5. Use the Hello World from within the function
  6. mvn compile and mvn test should already work
  7. observe that mvn package does not work.

Private repo

After Googleing I noticed that for package a repository should be available and that packaging does not work with only the local cache in ~/.m2

I "Fixed" this by publishing to a local repository from the library project and refering to that from the Azure Function project.
8. Publish to "remote" repository by adding the following to the pom.xml of the library project:

<plugin>
  <artifactId>maven-deploy-plugin</artifactId>
  <version>2.8.2</version>
  <configuration>
  
 <altDeploymentRepository>internal.repo::default::file:${project.basedir}/../mvn-repo</altDeploymentRepository>
  </configuration>
</plugin>
  1. Do mvn clean package install deploy in the library project folder.
  2. Verify that the library is deployed to the new local file repo.
  3. clear my .m2/repository
  4. Go to the functions project project
  5. Add the following to the pom.xml file
<repositories>
    <!--other repositories if any-->
    <repository>
        <id>project.local</id>
        <name>project</name>
        <url>file:${project.basedir}/../mvn-repo</url>
    </repository>
</repositories>
  1. do mvn clean compile test
  2. Observe that the tests are run (If you do not add the repository. The code will fail to compile/test if your .m2 cache is empty too.)
  3. Do mvn package --> fails with library classes that cannot be found
  4. Try mvn azure-functions:run It tries to package first and fails.

Error:

INFO] Reflections took 78 ms to scan 1 urls, producing 1 keys and 1 values
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 38.051 s
[INFO] Finished at: 2017-11-09T15:41:27+01:00
[INFO] Final Memory: 43M/286M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal com.microsoft.azure:azure-functions-maven-plugin:0.1.6:package (package-functions) on project helloworldFunction: Execution package-functions of goal com.microsoft.azure:azure-functions-mave
[ERROR] -----------------------------------------------------
[ERROR] realm =    plugin>com.microsoft.azure:azure-functions-maven-plugin:0.1.6
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/hkruse/.m2/repository/com/microsoft/azure/azure-functions-maven-plugin/0.1.6/azure-functions-maven-plugin-0.1.6.jar
[... <<<cut>>> ...]
[ERROR] urls[82] = file:/C:/Users/hkruse/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import  from realm ClassRealm[maven.api, parent: null]]

Side note: using Github as repo

We looked into using hosted Nexus as a repo but did not do that for cost reasons.

We finally want to use either Github site plugin or Wagon-git
I think wagon-git is finally the way to go because the site plugin is more for publishing sites.
I did not want to complicate matters more yet by using git based repo plugins now. So I used the local file system to try it out.

Feature Request: EventHubTrigger

The Event Hub Trigger does not yet work.

Error Message in the local environment:

info: Worker.Java.fe7e29b7-c013-4369-b4db-0071d7e171e6[0]
      Start Process: /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/bin/java  -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 "/Users/matthiasniehoff/.azurefunctions/bin/workers/Java/azure-functions-java-worker.jar" --host 127.0.0.1 --port 55575 --workerId fe7e29b7-c013-4369-b4db-0071d7e171e6 --requestId fb3e5e92-d9dc-4ecd-bb18-fadec311afb5
[02.11.17 10:54:06] Generating 0 job function(s)
[02.11.17 10:54:06] Starting Host (HostId=matthiasmacbookpro-1212839178, Version=2.0.11308.0, ProcessId=11064, Debug=False, Attempt=0)
[02.11.17 10:54:06] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).
info: Worker.Java.fe7e29b7-c013-4369-b4db-0071d7e171e6[0]
      Listening for transport dt_socket at address: 5005
[02.11.17 10:54:06] Job host started
[02.11.17 10:54:06] The following 1 functions are in error:
[02.11.17 10:54:06] hello: Object reference not set to an instance of an object.
[02.11.17 10:54:06] 
[02.11.17 10:54:06] 
info: Worker.Java.fe7e29b7-c013-4369-b4db-0071d7e171e6[0]
      Microsoft Azure Functions Java Runtime [build 1.1-SNAPSHOT]
info: Worker.Java.fe7e29b7-c013-4369-b4db-0071d7e171e6[0]
      [INFO] {com.microsoft.azure.webjobs.script.handler.MessageHandler.handle}: message generated by "class com.microsoft.azure.webjobs.script.rpc.messages.StartStream$Builder"
Listening on http://localhost:7071/
Hit CTRL-C to exit...
[02.11.17 10:54:06] Host lock lease acquired by instance ID '0000000000000000000000003BDBF0D9'.

Error Message when deployed:

Function ($hello) Error: Object reference not set to an instance of an object.

My Function:

    @FunctionName("hello")
    public String hello(@EventHubTrigger(name = "req", eventHubName = "event-hub", connection = "ReceiverConnectionString", consumerGroup = "es-function") String req,
                        ExecutionContext context) {
        return String.format("Hello, %s!", req);
    }

My local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=...",
    "AzureWebJobsDashboard": "DefaultEndpointsProtocol=https;AccountName=...",
    "ReceiverConnectionString": "Endpoint=....."
  },
  "bindings": [
    {
      "type": "eventHubTrigger",
      "name": "req",
      "direction": "in",
      "path": "event-hub",
      "connection": "ReceiverConnectionString",
      "consumerGroup": "es-function"
    }
  ]
}

Did I something wrong is it not yet supported by now?

Bind message ID from queue trigger

i'd like to bind the message ID from a queue trigger to a parameter:

public class Function {
	@FunctionName("execute")
	@QueueOutput(name = "output", queueName = "results")
	public String execute(@QueueTrigger(name = "input", queueName="inputs") String input, @BindingName("Id") String id) throws IOException {
		// ...
		return "result";
	}
}

however, an exception is thrown when a new mesage is received: Cannot locate the method signature with the given input. is there a way to bind the ID?

Should HTTP methods be an enum

Rather than have the user dealing with Strings for GET, POST, etc, should there be an enum of all possible types? This would improve code readability and type inferencing for developers.

Reduce noise: 'org.reflections.ReflectionsException: could not get type for name' error during compilation

In a certain code situation, I get the following exception at compile time:

[INFO] Step 1 of 6: Searching for Azure Function entry points
[INFO] Reflections took 27 ms to scan 1 urls, producing 2 keys and 2 values
[WARNING] could not get type for name net.jonathangiles.azure.functions.interfacebug.db.DataStore from any class loader
org.reflections.ReflectionsException: could not get type for name net.jonathangiles.azure.functions.interfacebug.db.DataStore
at org.reflections.ReflectionUtils.forName(ReflectionUtils.java:390)
at org.reflections.Reflections.expandSuperTypes(Reflections.java:381)
at org.reflections.Reflections.(Reflections.java:126)
at com.microsoft.azure.maven.function.handlers.AnnotationHandlerImpl.findFunctions(AnnotationHandlerImpl.java:42)
at com.microsoft.azure.maven.function.PackageMojo.findAnnotatedMethods(PackageMojo.java:89)
at com.microsoft.azure.maven.function.PackageMojo.doExecute(PackageMojo.java:61)
at com.microsoft.azure.maven.AbstractAzureMojo.execute(AbstractAzureMojo.java:265)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:993)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:345)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:191)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: java.lang.ClassNotFoundException: net.jonathangiles.azure.functions.interfacebug.db.DataStore
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
at org.reflections.ReflectionUtils.forName(ReflectionUtils.java:388)
... 28 more
[INFO] 1 Azure Function entry point(s) found.

I'm attaching the code that caused this for you to reproduce the issue locally.

interface-bug.zip

Feature Request: ServiceBusTopicTrigger

Checking beta2 in azure, here is my function and config:

package com.hillingk;

import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {

    @FunctionName("hello")
    public void hello(@ServiceBusTopicTrigger(name = "message", topicName = "hello", 
         connection = "servicebusconnection", subscriptionName = "world") String message,
                                     final ExecutionContext context) {
        context.getLogger().info(message);
    }
}

Configuration:

{
  "scriptFile" : "..\\functions-beta2-1.0-SNAPSHOT.jar",
  "entryPoint" : "com.hillingk.Function.hello",
  "bindings" : [ {
    "type" : "serviceBusTrigger",
    "name" : "serviceBusTrigger",
    "direction" : "in",
    "topicName" : "hello",
    "subscriptionName" : "world",
    "connection" : "servicebusconnection",
    "access" : "MANAGE"
  } ],
  "disabled" : false
}

The error message

Error:

Function ($hello) Error: The binding type 'serviceBusTrigger' is not registered. Please ensure the type is correct and the binding extension is installed.
Session Id: 02247ada41494083b798465a1ca7bfe6

Timestamp: 2017-11-28T21:29:11.950Z

Raw Response/Request

(follow-up: #16 (comment))

How can I return a string (or byte array) left untouched?

@FunctionName("hello")
public HttpResponseMessage<String> hello(@HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<String> req, ExecutionContext context) {
  context.getLogger().info("started");
  context.getLogger().info(req.getBody());
  HttpResponseMessage<String> response = req.createResponse(200, "{\"test\": \"test\"}");
  response.addHeader("Content-Type", "application/json");
  return response;
}

curl -v -H "Accept: application/json" http://localhost:7071/api/hello
returns "{\"test\": \"test\"}" instead of {"test": "test"}

curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST http://localhost:7071/api/hello
logs (looks like it was de-serialized and re-serialized)

{
  "key1": "value1",
  "key2": "value2"
}

curl -d '{"broken' -H "Content-Type: application/json" -X POST http://localhost:7071/api/hello
crashes (which kind of proves that it's not passed as is)

Malformed JSON input causes the function to never complete

...and subsequent (valid) invocations to block.

At least on the local test platform (I've yet to spin up an actual azure instance).

node -v

9.5.0

mvn -v

Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T00:58:13-07:00)
Maven home: C:\tools\apache-maven\bin..
Java version: 9.0.1, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk-9.0.1
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

Very minimal reproduction project. Start it up as per the usual instructions, then supply something like:

{
	"keyValue":"asdasd"

(missing ending bracket)
...and.... wait.
What's strange is that Postman, at least, isn't timing out either - it seems to be expecting it'll get something back, which would indicate there's still some communication (unfortunately since the test runner operates on localhost, I'm not able to snoop on it with wireshark).

Java output formatting

currently, Application.LOGGER logs in the form:

 Aug 31, 2017 3:45:32 PM com.microsoft.azure.webjobs.script.handler.MessageHandler handle
 INFO: message generated by "class com.microsoft.azure.webjobs.script.rpc.messages.RpcLog$Builder"

On the host side, these are processed as two separate lines, which leads to this clutter:
info: Host.Worker[0]
=> java f6e8457f-2ebe-4dad-b906-9bb0bb268508
Aug 31, 2017 3:45:32 PM com.microsoft.azure.webjobs.script.handler.MessageHandler handle
info: Host.Worker[0]
=> java f6e8457f-2ebe-4dad-b906-9bb0bb268508
INFO: message generated by "class com.microsoft.azure.webjobs.script.rpc.messages.RpcLog$Builder"

Changing the formatting to a single line would make things cleaner - in the future, we might want to have some worker defined formatting logic so the host can try to intelligently display this stuff

Unable to get JPA working in a fatjar azure function

When using Azure Functions with Java, I am trying to use JPA to access a database. I have a non-JPA implementation working, but I would like to work out why the JPA implementation doesn't work. All my code is available here: https://github.com/JonathanGiles/azure-functions-java-shortcode

To test, you can simply clone the repo, and modify the DataStoreFactory class to return a JPADataStore, rather than the SQLDataStore. Once this is modified, you can run the code locally with mvn clean package azure-functions:run. When the server is running, you can then test by doing an HTTP post to http://localhost:7071/api/shortcode with a url query parameter of a given url, e.g. http://www.azure.com.

When I do this on my machine with JPA, I get the following output:

[17/01/18 6:12:06 AM] Function started (Id=2513c795-f074-45b4-b986-98bbcb5a8b9a)
[17/01/18 6:12:06 AM] Executing 'Functions.shortcode' (Reason='This function was programmatically called via the host APIs.', Id=2513c795-f074-45b4-b986-98bbcb5a8b9a)
info: Worker.Java.7d7162ec-e688-46f5-ac6f-55126621a850[0]
Jan 17, 2018 7:12:06 PM javax.persistence.spi.PersistenceProviderResolverHolder$DefaultPersistenceProviderResolver log
info: Worker.Java.7d7162ec-e688-46f5-ac6f-55126621a850[0]
WARNING: javax.persistence.spi::No valid providers found.
[17/01/18 6:12:06 AM] A ScriptHost error has occurred
[17/01/18 6:12:06 AM] Exception while executing function: Functions.shortcode. System.Private.CoreLib: Result: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Exception: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Stack: javax.persistence.PersistenceException: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.impls.JPADatabase.(JPADatabase.java:35)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.DataStoreFactory.getInstance(DataStoreFactory.java:20)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.functions.ShortcodeFunction.shortcode(ShortcodeFunction.java:28)
[17/01/18 6:12:06 AM] .
[17/01/18 6:12:06 AM] Exception while executing function: Functions.shortcode. System.Private.CoreLib: Result: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Exception: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Stack: javax.persistence.PersistenceException: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.impls.JPADatabase.(JPADatabase.java:35)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.DataStoreFactory.getInstance(DataStoreFactory.java:20)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.functions.ShortcodeFunction.shortcode(ShortcodeFunction.java:28)
[17/01/18 6:12:06 AM] .
[17/01/18 6:12:06 AM]
[17/01/18 6:12:06 AM] Exception while executing function: Functions.shortcode
[17/01/18 6:12:06 AM] Exception while executing function: Functions.shortcode. System.Private.CoreLib: Result: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Exception: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Stack: javax.persistence.PersistenceException: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.impls.JPADatabase.(JPADatabase.java:35)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.DataStoreFactory.getInstance(DataStoreFactory.java:20)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.functions.ShortcodeFunction.shortcode(ShortcodeFunction.java:28)
[17/01/18 6:12:06 AM] .
[17/01/18 6:12:06 AM] Function completed (Failure, Id=2513c795-f074-45b4-b986-98bbcb5a8b9a, Duration=345ms)
[17/01/18 6:12:06 AM]
[17/01/18 6:12:06 AM] Executed 'Functions.shortcode' (Failed, Id=2513c795-f074-45b4-b986-98bbcb5a8b9a)
[17/01/18 6:12:06 AM] System.Private.CoreLib: Exception while executing function: Functions.shortcode. System.Private.CoreLib: Result: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Exception: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Stack: javax.persistence.PersistenceException: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.impls.JPADatabase.(JPADatabase.java:35)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.DataStoreFactory.getInstance(DataStoreFactory.java:20)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.functions.ShortcodeFunction.shortcode(ShortcodeFunction.java:28)
[17/01/18 6:12:06 AM] .
[17/01/18 6:12:06 AM] Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '2513c795-f074-45b4-b986-98bbcb5a8b9a'
[17/01/18 6:12:06 AM] System.Private.CoreLib: Exception while executing function: Functions.shortcode. System.Private.CoreLib: Result: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Exception: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] Stack: javax.persistence.PersistenceException: No Persistence provider for EntityManager named shortcodes
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
[17/01/18 6:12:06 AM] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.impls.JPADatabase.(JPADatabase.java:35)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.db.DataStoreFactory.getInstance(DataStoreFactory.java:20)
[17/01/18 6:12:06 AM] at net.jonathangiles.azure.shorturl.functions.ShortcodeFunction.shortcode(ShortcodeFunction.java:28)
[17/01/18 6:12:06 AM] .

It is possible to run the main method in the JPADataStore class and see that it can communicate successfully when not running as part of Azure Functions - so I am not sure why it doesn't work under Azure Functions. I'm guessing something to do with the fat jar is not correct, but I am unable to determine what. Any insights into what Azure Functions is doing would be much appreciated, so I can get to the bottom of this! Thanks.

Reading base64 encoded PNG using PDFbox fails in Azure

High level description I have code that gets triggered by a storage queue. It then reads JSON from a blob. In this blob is a base64 encoded image.
The blob store invents two extra Unicode character.(that will be another issue) We strip those away. Then we decode the image and add it to a PDF using PDFBox. On the simulator and in integration tests it works on Real Azure it crashes on some PNGs in the Sun PNG decoder.

Known or should this require stacktrace and sample code?

Unable to run functions locally

I'm not sure what has happened, but I am unable to run Azure Functions locally to test any longer. I am now presented with the following output when I run mvn azure-functions:run:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Azure Java Functions 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- azure-functions-maven-plugin:0.1.9:run (default-cli) @ functions-test ---
AI: INFO 17-01-2018 12:47, 1: Configuration file has been successfully found as resource
AI: INFO 17-01-2018 12:47, 1: Configuration file has been successfully found as resource
[INFO] Azure Functions stage directory found at: /Users/jonathan/Code/azure/test/functions-test/target/azure-functions/functions-test-20180117124644248
[INFO] Azure Functions Core Tools found.
[INFO] Starting running Azure Functions...

              %%%%%%
             %%%%%%
        @   %%%%%%    @
      @@   %%%%%%      @@
   @@@    %%%%%%%%%%%    @@@
 @@      %%%%%%%%%%        @@
   @@         %%%%       @@
     @@      %%%       @@
       @@    %%      @@
            %%
            %

Listening on http://localhost:7071/
Hit CTRL-C to exit...
Object reference not set to an instance of an object.

From this point it just appears to freeze with no feedback about how to resolve this issue. The code being executed here is simply the generated code from the Java tutorial here: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.