Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
kevinhillinger opened this issue Feb 5, 2018 · 3 comments
Closed

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

kevinhillinger opened this issue Feb 5, 2018 · 3 comments
Assignees

Comments

@kevinhillinger
Copy link
Member

kevinhillinger commented Feb 5, 2018

+ @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.

@JonathanGiles
Copy link
Member

Supporting this is a critical requirement for Azure Functions with Java. I wholeheartedly agree with the approach and would love to see this supported ASAP.

@kevinhillinger
Copy link
Member Author

kevinhillinger commented Feb 8, 2018

@JunyiYi I've worked over the past couple of days on a pull request. In my fork of the worker, you will find that it will work with Jonathan's JPA example.

Support for lib/ folder

My fork supports a lib folder in the root of the Function App directory.

I'm working on providing two complete examples:

  1. with the Fat Jar still working
  2. suppport for dependencies in a lib/ directory as mentioned here

Steps to using the lib/ with

  1. remove the maven-shade-plugin from the pom.xml
  2. add the `maven-dependency-plugin
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>3.0.2</version>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/azure-functions/${functionAppName}/lib</outputDirectory>
        <overWriteReleases>false</overWriteReleases>
        <overWriteSnapshots>false</overWriteSnapshots>
        <overWriteIfNewer>true</overWriteIfNewer>
      </configuration>
    </execution>
  </executions>
</plugin>

@JonathanGiles to unblock you (at least locally), you can compile the azure-functions-java-worker from my repository, and drop it into the tools location.

mvn clean compile package
sudo mv /usr/local/lib/node_modules/azure-functions-core-tools/bin/workers/java/azure-functions-java-worker.jar /usr/local/lib/node_modules/azure-functions-core-tools/bin/workers/java/azure-functions-java-worker.jar.old
sudo mv azure-functions-java-worker/target/azure-functions-java-worker-1.0.0-beta-2.jar /usr/local/lib/node_modules/azure-functions-core-tools/bin/workers/java/azure-functions-java-worker.jar

@JunyiYi
Copy link
Contributor

JunyiYi commented Mar 21, 2018

Supported in pull request #50 .

@JunyiYi JunyiYi closed this as completed Mar 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants