Azure-sdk-for-java: [Ошибка] бесконечная итерация по blobList

Созданный на 24 мар. 2020  ·  53Комментарии  ·  Источник: Azure/azure-sdk-for-java

Запрос / вопрос
Когда я звоню по следующему коду

    PagedIterable<BlobItem> items = azure.listBlobsByHierarchy(path);
    ArrayList<String> strings = new ArrayList<>();
    for (BlobItem item : items) {
      strings.add(item.getName());
    }
    return strings;

получается, что цикл бесконечен, постоянно повторяется item1 → item2 → item3 → item1 → …

Почему это не ошибка или запрос функции?
Это не похоже на ошибку, потому что я не могу воспроизвести ее в чистой среде. Моя настраиваемая среда - это плагин для просмотра хранилища BLOB-объектов Azure в IDEA.

Настройка (пожалуйста, заполните следующую информацию, если применимо):

  • ОС: Manjaro Linux, 19.0.2, ядро ​​5.5.8-1-MANJARO
  • IDE: IntelliJ
  • Используемая версия библиотеки: 12.5.0
Azure.Core Client Storage customer-reported

Самый полезный комментарий

Если мы будем следовать инструкциям, перечисленным в вышеупомянутой ветке плагина IntelliJ, Джексон сможет использовать ServiceLoader:

Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

не уверен, что это оптимальное решение для плагина.

Все 53 Комментарий

Привет, @ asm0dey. Это действительно звучит как довольно неожиданное поведение. Могу вас заверить, что результаты листинга не повторяются таким образом! Можете ли вы вообще фиксировать какие-либо сетевые трассировки, чтобы мы могли видеть, выдает ли PagedIterable повторяющиеся запросы или просто генерирует повторяющиеся кешированные значения? И у вас в контейнере только эти три капли? Или вы не видите других ожидаемых результатов?

PS Похоже на аккуратный плагин :)

Я абсолютно могу, но я не знаю, почему тела запросов и ответов не регистрируются.

Но еще раз - я не могу воспроизвести это поведение в чистой среде, поэтому я не думаю, что это настоящая ошибка, просто что-то с classpath / classloader / чем-то еще.

PS И да, этот плагин обязательно понравится, это https://plugins.jetbrains.com/plugin/12494-big-data-tools
Надеюсь, что Azure будет реализована в следующем выпуске EAP после 6-го

Было бы здорово. Спасибо! Я не думаю, что тела запросов и ответов обычно регистрируются, потому что они могут быть довольно большими.

Если вы подозреваете какую-то ошибку пути к классам, мы могли бы начать с mvn d ependency: tree и посмотреть, что происходит? Могут быть конфликты, вызывающие что-то странное.

Вау, это было бы здорово! Спасибо за работу над этим проектом, и, если мы можем оказать какую-либо поддержку, сообщите нам об этом. Нам нравится видеть, как другие участники сообщества создают инструменты для Storage и Azure в целом!

Это не так просто, потому что у нас нет традиционной системы сборки, такой как maven или gradle, мы строим наш проект с самой IDEA (и на сервере CI тоже).

Но , пожалуйста, найти UML диаграммы зависимостей здесь .

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

Говоря о ведении журнала: есть возможность регистрировать заголовки и тела, но тело может быть зарегистрировано, если размер тела известен из заголовков, но, согласно журналам, заголовка нет.

Вот небольшой фрагмент журнала:

2020-03-25 09:43:08,627 [57159248]   INFO - rvice.listBlobHierarchySegment - --> GET https://pavelfinkelshteynjb.blob.core.windows.net/testcontainer1?prefix=&delimiter=/&marker=REDACTED&restype=REDACTED&comp=REDACTED
Date:Wed, 25 Mar 2020 06:43:08 GMT
Authorization:REDACTED
Content-Length:0
x-ms-version:REDACTED
x-ms-client-request-id:c4016194-f020-45fc-b254-11a04fd65d52
User-Agent:azsdk-java-azure-storage-blob/12.5.0 (11.0.6; Linux 5.5.8-1-MANJARO)
(empty body)
--> END GET

2020-03-25 09:43:08,639 [57159260]   INFO - rvice.listBlobHierarchySegment - <-- 200 https://pavelfinkelshteynjb.blob.core.windows.net/testcontainer1?prefix=&delimiter=/&marker=REDACTED&restype=REDACTED&comp=REDACTED (68 ms, unknown-length body)
Date:Wed, 25 Mar 2020 06:43:07 GMT
Server:Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
Transfer-Encoding:chunked
x-ms-version:REDACTED
Content-Type:application/xml
x-ms-request-id:REDACTED
x-ms-client-request-id:7836d3ae-cf10-4432-a511-479dbf4ec09d
(body content not logged)
<-- END HTTP 

В классе com.azure.core.http.policy.HttpLoggingPolicy мы можем найти метод logResponse , и там

                String contentTypeHeader = response.getHeaderValue("Content-Type");
                long contentLength = this.getContentLength(logger, response.getHeaders());
                if (this.shouldBodyBeLogged(contentTypeHeader, contentLength)) {
// snip

                } else {
                    responseLogMessage.append("(body content not logged)").append(System.lineSeparator()).append("<-- END HTTP");
                    return this.logAndReturn(logger, responseLogMessage, response);

и в методе getContentLength

    private long getContentLength(ClientLogger logger, HttpHeaders headers) {
        long contentLength = 0L;
        String contentLengthString = headers.getValue("Content-Length");
        if (CoreUtils.isNullOrEmpty(contentLengthString)) {
            return contentLength;
// snip

Таким образом, этот API не поддерживает регистрацию тел.

@ asm0dey Извините за задержку. Можете ли вы обновить HttpLogOptions в построителях клиентов, чтобы добавить «маркер» в качестве allowedQueryParameter? Похоже, что это редактируется из ваших журналов, и я подозреваю, что, возможно, что-то снова и снова запускает вызов списка с одним и тем же маркером. Мы случайно наблюдали подобное поведение в некоторых разработках, которые мы здесь проводим, и я думаю, что это может быть та же причина.

Я не вижу ничего выделяющегося на диаграмме UML, но я никогда не смотрел ни на что раньше.

Абсолютно. Полный журнал прилагается:
idea.log
Маркер полностью пуст

grep marker= idea.log | more сообщает нам, что постоянно повторяется запрос GET https://pavelfinkelshteynjb.blob.core.windows.net/testcontainer1?prefix=&delimiter=/&marker=&restype=REDACTED&comp=REDACTED выполняется

Также мы видим огромное количество запросов: 673. Было как будто 2-4 запроса со стороны клиента.

@ rickle-msft есть идеи по этому поводу?

@ rickle-msft просто дружеское напоминание

Привет, @ asm0dey. Прошу прощения за задержку! Мои электронные письма с GitHub какое-то время неправильно фильтровались, и когда я заметил и исправил это, я, должно быть, также пропустил эту проблему. Еще раз извиняюсь и благодарю за напоминание.

Да, интересно, что все запросы имеют этот пустой параметр запроса marker= . Единственный способ воспроизвести это конкретное поведение - явно передать пустую строку в качестве токена продолжения, и даже это не может быть бесконечным.

@anuchandy Есть ли у вас какое-либо представление о том, может ли это быть причиной какой-то проблемы с зависимостью? Похоже, он использует закрашенную банку 12.5.0, и я не слишком знаком с ее затенением и тем, как это может повлиять на взаимодействие с путем к классам и загрузчиком классов.

Собственно, я даже пробовал его отменить, и это буквально ничего не меняет
в этом поведении. Также я не меняю имена пакетов или что-то вроде
что.

Я даже связывался с одним из разработчиков проекта реактора, но его единственная идея
был тот итератор, который воссоздается при каждом вызове.
20.04.29, 10:53 Рик Лей написал:

Привет, @ asm0dey. Прошу прощения за задержку! Мои электронные письма с GitHub какое-то время неправильно фильтровались, и когда я заметил и исправил это, я, должно быть, также пропустил эту проблему. Еще раз извиняюсь и благодарю за напоминание.

Да, интересно, что все запросы имеют этот пустой параметр запроса marker= . Единственный способ воспроизвести это конкретное поведение - явно передать пустую строку в качестве токена продолжения, и даже это не может быть бесконечным.

@anuchandy Есть ли у вас какое-либо представление о том, может ли это быть причиной какой-то проблемы с зависимостью? Похоже, он использует закрашенную банку 12.5.0, и я не слишком знаком с ее затенением и тем, как это может повлиять на взаимодействие с путем к классам и загрузчиком классов.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/Azure/azure-sdk-for-java/issues/9465#issuecomment -621366540

-
С уважением,
Паша

Инструменты для больших данных @ JetBrains

@ asm0dey

не могли бы вы запустить следующий код в своей настройке и поделиться тем, что вы видите в качестве вывода. Да, он будет работать бесконечно, просто остановитесь после того, как вы увидите Processing Page:start 3-4 раза.

BlobContainerAsyncClient blobContainerClient = new BlobContainerClientBuilder()
        .endpoint("<your-storage-account-url>")
        .sasToken("<your-sasToken>")
        .containerName("mycontainer")
        .buildAsyncClient();

PagedFlux<BlobItem> flux = blobContainerClient.listBlobsByHierarchy(path);
flux.byPage()
        .doOnNext(new Consumer<PagedResponse<BlobItem>>() {
            <strong i="9">@Override</strong>
            public void accept(PagedResponse<BlobItem> response) {
                System.out.println("Processing Page:start");
                List<BlobItem> items = response.getValue();
                for (BlobItem item : items) {
                    System.out.println(item.getName());
                }
                if (response.getContinuationToken() == null) {
                    System.out.println("ContinuationToken: null");
                } else if (response.getContinuationToken().length() == 0) {
                    System.out.println("ContinuationToken: empty");
                } else {
                    System.out.println("ContinuationToken: non-empty:" + response.getContinuationToken());
                }
                System.out.println("Processing Page:end");
            }
        }).blockLast();

кстати, пожалуйста, отредактируйте имя элемента, если хотите, меня интересуют атрибуты null | empty | non-empty для continueToken.

Извините за задержку, я считаю, что разница в ТЗ.
Вот

Processing Page:start
.travis.yml
build.sh
.git/
KateTest12/
KateTest1234/
KateTest12345/
KateTestRenamed/
Test1/
demo/
plugins/
ContinuationToken: empty
Processing Page:end
Processing Page:start
.travis.yml
build.sh
.git/
KateTest12/
KateTest1234/
KateTest12345/
KateTestRenamed/
Test1/
demo/
plugins/
ContinuationToken: empty
Processing Page:end
Processing Page:start
.travis.yml
build.sh
.git/
KateTest12/
KateTest1234/
KateTest12345/
KateTestRenamed/
Test1/
demo/
plugins/
ContinuationToken: empty
Processing Page:end

Я пишу на котлине, поэтому мой код выглядит немного иначе:

    BlobServiceClientBuilder()
      .endpoint(endpoint)
      .apply { authProvider(this) }
      .httpClient(NettyAsyncHttpClientBuilder().build())
      .buildAsyncClient()
      .getBlobContainerAsyncClient(container)
      .listBlobsByHierarchy("")
      .byPage()
      .doOnNext { response ->
        println("Processing Page:start")
        val items = response.value
        for (item in items) {
          println(item.name)
        }
        when {
          response.continuationToken == null -> println("ContinuationToken: null")
          response.continuationToken.isEmpty() -> println("ContinuationToken: empty")
          else -> println("ContinuationToken: non-empty:" + response.continuationToken)
        }
        println("Processing Page:end")
      }
      .blockLast()

А также я уже жаловался, что http-клиент не определяется автоматически из-за проблем с загрузчиком классов, поэтому мне приходится создавать его вручную.

Надеюсь, это ничего не изменит.

@ asm0dey, спасибо, что поделились этим!

@ rickle-msft - на выходе похоже, что маркер (он же continueToken) для последней страницы пуст "" а не null . Критерий выхода для «цикла загрузки страницы» - токен продолжения null .
Я думаю, это объясняет, почему это зацикливается.

Если я запустил приведенный выше код локально, последняя страница всегда будет иметь значение свойства маркера как null поэтому оно не воспроизводится в моей учетной записи хранения. Результат выглядит следующим образом:

Processing Page:start
foo.jpeg
ContinuationToken: null. <------  [In Paul's case this is an empty string ""]
Processing Page:end

если мы вручную установим (в режиме отладки) это на пустую строку "" то я вижу, что она попадает в бесконечный цикл.

Может ли служба хранения по сети вернуть свойство marker в виде пустой строки, указывая, что это последняя страница?

@anuchandy Я думаю, что служба всегда возвращает пустой xml-элемент <NextMarker /> когда нет следующей страницы. В остальных документах указано: «Обратите внимание, что элементы Prefix, Marker, MaxResults и Delimiter присутствуют только в том случае, если они были указаны в URI запроса. Элемент NextMarker имеет значение, только если результаты списка не завершены». Я считаю, что это означает, что NexMarker всегда будет присутствовать, но не всегда может иметь ценность.

Есть ли шанс, что другая среда каким-то образом заставляет десериализатор выдавать пустую строку вместо нуля? Мы также могли бы сделать проверку на ноль или пусто, а не просто на нуль?

Любые идеи по минимальному тесту для воспроизведения замены "" на нуль в нашей среде?

@ rickle-msft спасибо за ссылку. Позвольте мне обратиться к нескольким людям и вернуться, но я вижу, что предыдущая среда выполнения действительно обрабатывала пустую строку как условие выхода ref .

while (nextPageLink != null && nextPageLink != "") {

не совсем уверен, но это, вероятно, указывает на то, что когда следующий токен имеет тип String тогда некоторые службы Azure могут использовать пустую строку для обозначения завершения.

Я вижу ту же проблему с Iterable, возвращаемым методом DataLakeServiceClient.listFileSystems. Когда я использовал асинхронный клиент и печатал маркеры, как в предложении выше, я вижу пустые строки.

@rodburgett Я полагаю, это может помочь, если вы разместите информацию о своей среде. Возможно, мы могли бы найти обычные вещи в нашем окружении.

@ asm0dey Я думаю, что единственный общий элемент в наших средах - это банка хранилища BLOB-объектов, и даже там мы используем разные версии. Я работаю над Window 10, используя Gradle для выполнения. Впервые я столкнулся с этой проблемой с версией 12.3.0 jar-файла azure-storage-blob. Недавно я обновился до 12.6.0 и по-прежнему вижу проблему.

@ asm0dey , @rodburgett - внутри команды мы обсуждали, как обрабатывать "", а также сигнал о завершении пейджинга, учитывая, что это имеет место со многими azure-сервисами. Открыл для него черновик . (эта проблема приводит к выявлению другой недостающей функции на базовом уровне)

Хотя проблема бесконечного цикла, с которой вы столкнулись, исчезнет как побочный эффект этого изменения, интересно понять, почему ваша среда обрабатывает пустой узел XML как "" вместо null .

Вы можете поделиться версией Джексона, которая загружается в путь к классам приложения?

Я использую банки Jackson v2.10.2.

@anuchandy вот мой полный

accessors-smart-1.2.jar
aircompressor-0.15.jar
annotations-17.0.0.jar
asm-5.0.4.jar
avro-1.8.0.jar
avro-1.8.2.jar
aws-java-sdk-bundle-1.11.375.jar
azure-core-1.4.0.jar
azure-core-http-netty-1.5.0.jar
azure-storage-blob-12.6.0.jar
azure-storage-common-12.6.0.jar
bigdatatools.jar
commons-beanutils-1.9.3.jar
commons-beanutils-1.9.4.jar
commons-cli-1.2.jar
commons-codec-1.11.jar
commons-codec-1.5.jar
commons-collections-3.2.2.jar
commons-collections4-4.4.jar
commons-compress-1.4.1.jar
commons-compress-1.8.1.jar
commons-configuration2-2.1.1.jar
commons-io-2.5.jar
commons-lang-2.6.jar
commons-lang3-3.7.jar
commons-lang3-3.9.jar
commons-logging-1.1.3.jar
commons-logging-1.2.jar
commons-math3-3.1.1.jar
commons-net-3.6.jar
commons-pool-1.5.4.jar
commons-text-1.4.jar
commons-text-1.8.jar
curator-client-2.12.0.jar
curator-framework-2.12.0.jar
curator-recipes-2.12.0.jar
diff-match-patch-1.2.jar
dnsjava-2.1.7.jar
fastutil-6.5.7.jar
google-cloud-storage-1.105.2.jar
guava-11.0.2.jar
hadoop-annotations-3.2.0.jar
hadoop-auth-3.2.0.jar
hadoop-aws-3.2.0.jar
hadoop-client-3.2.0.jar
hadoop-common-3.2.0.jar
hadoop-distcp-3.2.1.jar
hadoop-hdfs-client-3.2.0.jar
hadoop-mapreduce-client-common-3.2.0.jar
hadoop-mapreduce-client-core-3.2.0.jar
hadoop-mapreduce-client-jobclient-3.2.0.jar
hadoop-yarn-api-3.2.0.jar
hadoop-yarn-client-3.2.0.jar
hadoop-yarn-common-3.2.0.jar
hive-storage-api-2.6.0.jar
htrace-core4-4.1.0-incubating.jar
jackson-annotations-2.10.1.jar
jackson-core-2.10.1.jar
jackson-core-asl-1.9.11.jar
jackson-core-asl-1.9.13.jar
jackson-databind-2.10.1.jar
jackson-dataformat-xml-2.10.1.jar
jackson-datatype-jsr310-2.10.1.jar
jackson-mapper-asl-1.9.11.jar
jackson-mapper-asl-1.9.13.jar
jackson-module-jaxb-annotations-2.10.1.jar
jakarta.activation-api-1.2.1.jar
jakarta.xml.bind-api-2.3.2.jar
javax.servlet-api-3.1.0.jar
jaxb-api-2.2.11.jar
jcip-annotations-1.0-1.jar
jersey-client-1.19.jar
jersey-core-1.19.jar
jersey-servlet-1.19.jar
json-smart-2.3.jar
jsoup-1.12.1.jar
jsp-api-2.1.jar
jsr305-3.0.0.jar
jsr311-api-1.1.1.jar
kerb-admin-1.0.1.jar
kerb-client-1.0.1.jar
kerb-common-1.0.1.jar
kerb-core-1.0.1.jar
kerb-crypto-1.0.1.jar
kerb-identity-1.0.1.jar
kerb-server-1.0.1.jar
kerb-simplekdc-1.0.1.jar
kerb-util-1.0.1.jar
kerby-asn1-1.0.1.jar
kerby-config-1.0.1.jar
kerby-pkix-1.0.1.jar
kerby-util-1.0.1.jar
kerby-xdr-1.0.1.jar
log4j-1.2.17.jar
moshi-1.7.0.jar
moshi-adapters-1.7.0.jar
moshi-kotlin-1.7.0.jar
netty-buffer-4.1.45.Final.jar
netty-codec-4.1.45.Final.jar
netty-codec-http-4.1.45.Final.jar
netty-codec-http2-4.1.45.Final.jar
netty-codec-socks-4.1.45.Final.jar
netty-common-4.1.45.Final.jar
netty-handler-4.1.45.Final.jar
netty-handler-proxy-4.1.45.Final.jar
netty-resolver-4.1.45.Final.jar
netty-tcnative-boringssl-static-2.0.27.Final.jar
netty-transport-4.1.45.Final.jar
netty-transport-native-epoll-4.1.45.Final-linux-x86_64.jar
netty-transport-native-unix-common-4.1.45.Final.jar
nimbus-jose-jwt-4.41.1.jar
nv-websocket-client-2.9.jar
okhttp-2.7.5.jar
okhttp-3.14.7.jar
okio-1.17.2.jar
opencsv-5.1.jar
orc-core-1.6.2.jar
orc-shims-1.6.2.jar
paranamer-2.7.jar
parquet-avro-1.9.0.jar
parquet-column-1.9.0.jar
parquet-common-1.9.0.jar
parquet-encoding-1.9.0.jar
parquet-format-2.3.1.jar
parquet-hadoop-1.9.0.jar
parquet-jackson-1.9.0.jar
protobuf-java-2.5.0.jar
re2j-1.1.jar
reactive-streams-1.0.3.jar
reactor-core-3.3.3.RELEASE.jar
reactor-netty-0.9.5.RELEASE.jar
snappy-java-1.1.1.3.jar
snappy-java-1.1.1.6.jar
snappy-java-1.1.7.3.jar
stax2-api-3.1.4.jar
stax2-api-4.2.jar
token-provider-1.0.1.jar
woodstox-core-5.0.3.jar
woodstox-core-6.0.2.jar
xz-1.0.jar
xz-1.5.jar

Я вижу количество повторяющихся зависимостей. Как вы думаете, это может что-то сломать?

export.zip

@rodburgett @anuchandy Здесь я прикрепляю минимальный плагин, воспроизводящий бесконечную итерацию. Его можно построить с помощью gradle, и есть конфигурация запуска для запуска объединенной идеи

@ asm0dey - Мне удалось создать проект, как я могу его запустить, я вижу ниже ошибку, указывающую «не указан плагин», ничего не указано в параметре «использовать путь к классам модуля», я использую здесь правильную конфигурацию, если нет не могли бы вы предоставить подробные инструкции?

Screen Shot 2020-05-11 at 1 25 43 PM

Самый простой способ - просто вызвать задачу gradle runIde . Если вы запустите его по идее - wull.be в состоянии отладить его

@ asm0dey спасибо за подсказку, мне удалось загрузить плагин.

Я потратил некоторое время на отладку кода плагина, проблема не связана с SDK хранилища.

В изолированной программной среде IntelliJ Джексон не может найти синтаксический анализатор XML. Джексон использует ServiceLoader для загрузки фабрики синтаксического анализатора XML. Вне среды плагина он может загружать WstxInputFactory [com.fasterxml. woodstox: woodstox-core ], но не в песочнице, поэтому Джексон переключается на реализацию по умолчанию Stax2ReaderAdapter которая не имеет возможности обнаружить пустой узел . @ asm0dey Я думаю, вам нужно будет увидеть, как заставить плагин ClassLoader знать об этой зависимости, которая загружается по запросу.

Вот обновленный проект плагина, в котором есть только зависимость от Jackson export-2.zip, если это помогает.

Кстати, в обновленном выше коде плагина следующую зависимость Gradle не нужно явно указывать

group: 'com.fasterxml.woodstox', name: 'woodstox-core', version: '6.0.3'

это транзитивная зависимость от "jackson-dataformat-xml", поэтому ее можно удалить.

Я наткнулся на этот пост, если он помогает: https://intellij-support.jetbrains.com/hc/en-us/community/posts/206761975-How-to-load-classes-in-a-plugin-with-ServiceLoader -

Если мы будем следовать инструкциям, перечисленным в вышеупомянутой ветке плагина IntelliJ, Джексон сможет использовать ServiceLoader:

Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

не уверен, что это оптимальное решение для плагина.

Ух ты! Очень впечатляющее исследование, спасибо вам за это большое! И это действительно работает. Даже подумать не мог, что это тоже про загрузчик классов.

@anuchandy есть ли надежда, что вы сможете добавить перегруженный метод, который будет принимать другой загрузчик классов в качестве аргумента? Этот ответ на SO дает представление о том, почему это может быть полезно.

У меня есть простой пример воспроизведения Java / Gradle, IDE не требуется. После добавления этой зависимости woodstox-core к build.gradle первый ContinuationToken, возвращаемый во время итерации, теперь равен нулю. И мой цикл итераций завершается, как и ожидалось.

Запуск вне среды IDE выглядит как проблема зависимости, а не проблема загрузчика классов.

Спасибо @anuchandy

@rodburgett рад слышать, что вы разблокированы.

@ asm0dey - у нас есть некоторые незавершенные работы, чтобы пользователи могли настроить JacksonAdapter. См. Эти модули 1 , 2 . Надеюсь, библиотеки позволят пользователю в ближайшее время предоставить настроенный адаптер, мы тестируем это с некоторыми выбранными SDK (например, космос).

Учитывая, что плагин имеет конфликтующие зависимости, другой вариант для изучения - это затенение.

Я чувствую, что структура плагинов должна обеспечивать способ обработки стандартной возможности загрузки поставщика услуг Java, вместо того, чтобы разработчики работали над этим. Если мы посмотрим на мир плагинов / сборщиков OSGi, он предоставляет схему посредника загрузчика службы для обработки того же случая, это позволяет загрузке работать в сторонних библиотеках без изменения разработчиками приложений.

Я потратил некоторое время, чтобы изучить, как работает плагин IntelliJ, и открыл проблему в репро плагина IntelliJ: https://intellij-support.jetbrains.com/hc/en-us/community/posts/360008239419-How-to-make -the-plugin-CCTL-знающий-о-тип-провайдера-услуг-который-java-utils-ServiceLoader-ищет-для

@anuchandy Я считаю, что будет слишком сложно ввести Classloader, который будет правильно вести себя в IDEA, потому что существует много плагинов и много потоков, но ContextClassLoader настраивается для каждого потока.

И да, и OSGi, и JBoss Modules предоставляют способ правильной работы с загрузчиками сервисов, но способы, которыми они это делают, не слишком просты. Неужели мы действительно хотим большей сложности в нашей IDE? :)

Основная причина, по которой меня беспокоит установка CCL в библиотеках z, заключается в том, что это может быть обходным путем для одного случая, но, учитывая, что это библиотека и будет использоваться во многих средах, установка CCL без понимания того, что находится под env, рискованно.

Даже если мы хотим пойти по пути передачи загрузчиков классов сторонними библиотеками, не все сторонние библиотеки могут это поддерживать. Jackson XMLMapper является примером.

Да, посредник OSGi непрост, но я думаю, что функциональность, предоставляемая фреймворком, всегда безопасна и гарантирует, что ничего не сломается. Итак, я подумал, что это должно быть решено аналогичным образом в плагине InteillJ plugin fx, отсюда и проблема .

Думаю, как только у нас появится возможность настроить JackonAdpater (как я уже упоминал в предыдущем комментарии), пользователи смогут предоставить фабрику, поэтому обходного пути CCL не существует.

Или, альтернативно, затенение - еще один возможный вариант, который следует рассмотреть, вот связанный поток https://github.com/Azure/azure-sdk-for-java/issues/11104 , но в этом случае также возникла проблема конфликта.

Я считаю, что вы даже можете создать реальную проблему на youtrack.jetbrains.com.

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

Благодарим вас за правильную ссылку для сообщения о проблеме, открытую здесь: https://youtrack.jetbrains.com/issue/IDEA-241229

@ asm0dey @anuchandy Каков статус этой проблемы? Нужно ли нам держать его открытым для отслеживания или мы довольны тем, что открываем проблему с помощью jetbrains?

@ rickle-msft большое спасибо за вопрос и отслеживание! Я абсолютно доволен текущим состоянием.

Звучит отлично. В этом случае я закрою его, и мы можем открыть его снова, если нам понадобится дальнейшее обсуждение здесь. Спасибо за вашу работу!

Я столкнулся с той же проблемой в моем настраиваемом плагине. Какое решение? @anuchandy

@ tooptoop4 В моем случае это была проблема с загрузчиком классов, вы проверили?

У меня такая же проблема со listBlobs (). Есть ли другое решение, кроме изменения загрузчика классов?

    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-storage-file-datalake</artifactId>
      <version>12.1.1</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.woodstox</groupId>
        <artifactId>woodstox-core</artifactId>
        <version>6.2.1</version>
    </dependency>

@nkanala, мой обходной путь заключался в том, чтобы добавить каждое имя

@ tooptoop4 @nkanala Спасибо за вашу готовность сотрудничать в этой области. Один заголовок, который я дам вам, заключается в том, что если вы делаете иерархический список, возможно, добавьте дополнительный тестовый пример для сценария, где одно имя большого двоичного объекта является префиксом для другого имени большого двоичного объекта. например, случай 1: foo и foo / bar. Случай 2: foo / и foo / bar. Я считаю, что в первом случае возвращаемыми элементами будут foo и foo /, а во втором случае будет возвращено только foo /, но я подумал, что лучше упомянуть, если у вашего приложения есть другая логика для преобразования этих результатов перед сравнением.

К вашему сведению, у меня возникла эта проблема при обновлении с jackson-databind 2.11.4 (декабрь 2020 г.) до 2.12.0 (ноябрь 2020 г.) cf https://mvnrepository.com/artifact/com.fasterxml.jackson .core / jackson-databind

Итак, мое решение в этом случае - остаться на 2.11.4 . :)

У меня возникла та же проблема, когда я написал плагин для интеграции серого журнала с Azure EventHubs. Добавление Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); как указывает @anuchandy , перед созданием клиента решило проблему.

Вот код, создающий экземпляр BlobContainerAsyncClient:

//Instantiating the BlobContainerAsyncClient
119               BlobContainerAsyncClient blobContainerAsyncClient =
120                   new BlobContainerClientBuilder()
121                       .connectionString(STORAGE_CONNECTION_STRING)
122                       .containerName(STORAGE_CONTAINER_NAME)
123                       .httpClient(httpClient)
124                       .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS))
125                       .buildAsyncClient();
// Instantiating the event processor
129               BlobCheckpointStore blobCheckpointStore = new BlobCheckpointStore(blobContainerAsyncClient);
130               EventProcessorClientBuilder eventProcessorClientBuilder =
131                   new EventProcessorClientBuilder()
132                       .connectionString(EH_CONNECTION_STRING)
133                       .consumerGroup(EH_CONSUMER_GROUP)
134                       .processEvent(eventContext -> {
135                         LOG.info(
136                             "Processing event from partition {} with sequence {} %n",
137                             eventContext.getPartitionContext().getPartitionId(),
138                             eventContext.getEventData().getBodyAsString());
139                         if (eventContext.getEventData().getSequenceNumber() % 10 == 0) {
140                         }
141                       })
142                       .processError(errorContext -> {
143                         LOG.error(
144                             "Error occurred in partition processor for partition {}, {}.%n",
145                             errorContext.getPartitionContext().getPartitionId(), errorContext.getThrowable());
146                       })
147                       .checkpointStore(blobCheckpointStore);

Результатом будет бесконечно:

graylog_1 2021-01-22 23:25:11,690 INFO : com.azure.storage.blob.implementation.ContainersImpl$ContainersService.listBlobFlatSegment - --> GET https://shgraylog.blob.core.windows.net/shgraylog?prefix=REDACTED&marker=REDACTED&include=REDACTED&restype=REDACTED&comp=REDACTEDDate:Fri, 22 Jan 2021 23:25:11 GMTAuthorization:REDACTEDContent-Length:0x-ms-version:REDACTEDx-ms-client-request-id:e94e4822-d575-4172-9967-5f040598af7cUser-Agent:azsdk-java-azure-storage-blob/12.9.0 (1.8.0_265; Linux; 4.19.121-linuxkit)(empty body)--> END GET
graylog_1 2021-01-22 23:25:11,692 INFO : com.azure.storage.blob.implementation.ContainersImpl$ContainersService.listBlobFlatSegment - --> GET https://shgraylog.blob.core.windows.net/shgraylog?prefix=REDACTED&marker=REDACTED&include=REDACTED&restype=REDACTED&comp=REDACTEDDate:Fri, 22 Jan 2021 23:25:11 GMTAuthorization:REDACTEDContent-Length:0x-ms-version:REDACTEDx-ms-client-request-id:3309ac6e-33ef-46f5-b64b-60b1b0a98cd8User-Agent:azsdk-java-azure-storage-blob/12.9.0 (1.8.0_265; Linux; 4.19.121-linuxkit)(empty body)--> END GET
graylog_1 2021-01-22 23:25:11,700 INFO : com.azure.storage.blob.implementation.ContainersImpl$ContainersService.listBlobFlatSegment - <-- 200 https://shgraylog.blob.core.windows.net/shgraylog?prefix=REDACTED&marker=REDACTED&include=REDACTED&restype=REDACTED&comp=REDACTED (19 ms, unknown-length body)Date:Fri, 22 Jan 2021 23:25:11 GMTServer:Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0Transfer-Encoding:chunkedx-ms-version:REDACTEDContent-Type:application/xmlx-ms-request-id:REDACTEDx-ms-client-request-id:fa182abe-03bc-48cd-b981-de7246bb1ee9(body content not logged)<-- END HTTP
graylog_1 2021-01-22 23:25:11,703 INFO : com.azure.storage.blob.implementation.ContainersImpl$ContainersService.listBlobFlatSegment - --> GET https://shgraylog.blob.core.windows.net/shgraylog?prefix=REDACTED&marker=REDACTED&include=REDACTED&restype=REDACTED&comp=REDACTEDDate:Fri, 22 Jan 2021 23:25:11 GMTAuthorization:REDACTEDContent-Length:0x-ms-version:REDACTEDx-ms-client-request-id:88b6b377-092a-4eee-9fdd-6d00a4c07e22User-Agent:azsdk-java-azure-storage-blob/12.9.0 (1.8.0_265; Linux; 4.19.121-linuxkit)(empty body)--> END GET
graylog_1 2021-01-22 23:25:11,713 INFO : com.azure.storage.blob.implementation.ContainersImpl$ContainersService.listBlobFlatSegment - <-- 200 https://shgraylog.blob.core.windows.net/shgraylog?prefix=REDACTED&marker=REDACTED&include=REDACTED&restype=REDACTED&comp=REDACTED (20 ms, unknown-length body)Date:Fri, 22 Jan 2021 23:25:11 GMTServer:Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0Transfer-Encoding:chunkedx-ms-version:REDACTEDContent-Type:application/xmlx-ms-request-id:REDACTEDx-ms-client-request-id:3309ac6e-33ef-46f5-b64b-60b1b0a98cd8(body content not logged)<-- END HTTP

Извините за подробный комментарий, надеюсь, он поможет кому-то, кто сталкивается с той же проблемой.

К вашему сведению, у меня возникла эта проблема при обновлении с jackson-databind 2.11.4 (декабрь 2020 г.) до 2.12.0 (ноябрь 2020 г.) cf

Я испытал ту же проблему при обновлении до 2.12.0 , проблема, похоже, в том, что поведение по умолчанию в этой версии изменилось (https://github.com/FasterXML/jackson-dataformat-xml/issues/411 ), а для пустого блока теперь возвращает пустую строку вместо null . Я не думаю, что есть способ ввести собственный SerializerAdapter . Исправление должно быть довольно тривиальным для реализации в JacksonAdapter#JacksonAdapter и настройки синтаксического анализатора для работы должным образом.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги