Не удается использовать подход «обработчик» для добавления URLStreamHandler в AWS Lambda - PullRequest
1 голос
/ 30 апреля 2020

В настоящее время я пытаюсь добавить URLStreamHandler, чтобы обрабатывать URL-адреса с помощью пользовательских протоколов. Это работает нормально, когда запускается локально. При развертывании на AWS Lambda я получаю:

java.net.MalformedURLException: unknown protocol: baas

Я следую «Обработчику» подхода к регистрации URLStreamHandler .

Я даже зашел так далеко как копирование кода из URL.getURLStreamHandler(String) и добавление регистрации в мой собственный код, который запускается Lambda:

(Примечание: это из источника Java 8 - теперь я понимаю, что это может быть не представительным, потому что AWS Lambda использует Java 11 среды выполнения).

URLStreamHandler handler = null;
String packagePrefixList = null;

packagePrefixList
    = java.security.AccessController.doPrivileged(
    new sun.security.action.GetPropertyAction(
            "java.protocol.handler.pkgs",""));
if (packagePrefixList != "") {
    packagePrefixList += "|";
}

// REMIND: decide whether to allow the "null" class prefix
// or not.
packagePrefixList += "sun.net.www.protocol";

LOG.debug("packagePrefixList: " + packagePrefixList);

StringTokenizer packagePrefixIter =
    new StringTokenizer(packagePrefixList, "|");

while (handler == null &&
       packagePrefixIter.hasMoreTokens()) {

    String packagePrefix =
      packagePrefixIter.nextToken().trim();
    try {
        String clsName = packagePrefix + "." + "baas" +
          ".Handler";
        Class<?> cls = null;
        LOG.debug("Try " + clsName);
        try {
            cls = Class.forName(clsName);
        } catch (ClassNotFoundException e) {
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            if (cl != null) {
                cls = cl.loadClass(clsName);
            }
        }
        if (cls != null) {
            LOG.debug("Instantiate " + clsName);
            handler  =
              (URLStreamHandler)cls.newInstance();
        }
    } catch (Exception e) {
        // any number of exceptions can get thrown here
        LOG.debug(e);
    }
}

Это печатает (в журналах Cloudwatch):

packagePrefixList: com.elsten.bliss|sun.net.www.protocol (BaasDriver.java:94, thread main)
Try com.elsten.bliss.baas.Handler (BaasDriver.java:108, thread main)
Instantiate com.elsten.bliss.baas.Handler (BaasDriver.java:118, thread main)
com.elsten.bliss.baas.Handler constructor (Handler.java:55, thread main) 

Итак, при запуске из моего собственного кода, в Lambda , это работает.

Однако следующая строка записи:

java.lang.IllegalArgumentException: URL is malformed: baas://folder: java.lang.RuntimeException
java.lang.RuntimeException: java.lang.IllegalArgumentException: URL is malformed: baas://folder
    ...
Caused by: java.net.MalformedURLException: unknown protocol: baas
    at java.base/java.net.URL.<init>(Unknown Source)
    at java.base/java.net.URL.<init>(Unknown Source)
    at java.base/java.net.URL.<init>(Unknown Source)

Так что странно, что при запуске в URL код не работает. Основное различие, которое я могу вспомнить, заключается в том, что родительский загрузчик классов используется для загрузки URL, и мой код отличается, и поэтому существует какая-то проблема загрузки классов.

Подход SPI может ' не может использоваться, потому что Lambda не извлекает META-INF папок !

1 Ответ

0 голосов
/ 30 апреля 2020

Первоначально я думал, что старого подхода URL.setURLStreamHandlerFactory(URLStreamHandlerFactory) следует избегать, но оказывается, что он был улучшен в последних Java версиях, и поэтому я вернулся к этому.

В частности, откат по умолчанию URLStreamHandlerFactory, способный обрабатывать потоки до http, https, file и др., используется как запасной вариант, если предоставленный пользовательский не может обработать поток.

Это обходной путь хотя - было бы интересно узнать, почему класс не может быть загружен.

...