MessageBodyWriter не найдена ошибка для сервера Jersy / Jetty - PullRequest
0 голосов
/ 13 декабря 2018

Я только что следовал этому руководству, чтобы создать REST API с использованием Jersey на Jetty , и мне нравится результат.Все отлично работаетНо если я запускаю задачу Gradle shadowJar, чтобы сгенерировать толстый JAR-файл, это работает нормально, и файл также запускается, но заканчивается запросом об ошибке при выполнении запроса:

$ java -jar build/libs/sample-all.jar 
[main] INFO org.eclipse.jetty.util.log - Logging initialized @161ms to org.eclipse.jetty.util.log.Slf4jLog
[main] INFO org.eclipse.jetty.server.Server - jetty-9.4.z-SNAPSHOT
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@5824a83d{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@2ddc9a9f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[main] INFO org.eclipse.jetty.server.Server - Started @1547ms
Dez 12, 2018 10:05:07 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SCHWERWIEGEND: MessageBodyWriter not found for media type=application/json, type=class com.dovydasvenckus.jersey.greeting.Greeting, genericType=class com.dovydasvenckus.jersey.greeting.Greeting.

Так в скомпилированном JARмне кажется, что не хватает, например, lib.Я посмотрел в Интернете, и все предлагают добавить org.glassfish.jersey.media:jersey-media-json-jackson:2.27 (или некоторые варианты), чтобы это работало.Но это не работает для меня.Мой build.gradle выглядит так:

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'

sourceCompatibility = 1.8
mainClassName = 'com.dovydasvenckus.jersey.JerseyApplication'

ext {
    slf4jVersion = '1.7.25'
    jettyVersion = '9.4.6.v20170531'
    jerseyVersion = '2.27'
}

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
    }
}

repositories {
    jcenter()
}

dependencies {
    compile "org.slf4j:slf4j-api:${slf4jVersion}"
    compile "org.slf4j:slf4j-simple:${slf4jVersion}"

    compile "org.eclipse.jetty:jetty-server:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-servlet:${jettyVersion}"

    compile "org.glassfish.jersey.core:jersey-server:${jerseyVersion}"
    compile "org.glassfish.jersey.containers:jersey-container-servlet-core:${jerseyVersion}"
    compile "org.glassfish.jersey.containers:jersey-container-jetty-http:${jerseyVersion}"
    compile "org.glassfish.jersey.media:jersey-media-json-jackson:${jerseyVersion}"
    compile "org.glassfish.jersey.inject:jersey-hk2:${jerseyVersion}"

    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.27'

    compile "org.glassfish.jersey.media:jersey-media-moxy:2.27"

    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.27'

}

jar { manifest { attributes 'Main-Class': "${mainClassName}" } }

Есть идеи, как заставить это работать?

1 Ответ

0 голосов
/ 13 декабря 2018

Как уже упоминалось в моем ответе в MessageBodyProviderNotFoundException при запуске jar из командной строки , существует «файл служб», а именно org.glassfish.jersey.internal.spi.AutoDiscoverable, который включен во многие jar.Цель этого файла - разрешить банкам Джерси (и других сторонних производителей) предоставлять некоторую автоматическую регистрацию для функций, включенных в эти банки.Это включает в себя регистрацию JacksonFeature, которая регистрирует JSON-провайдеров, которые обрабатывают (де) сериализацию.

Проблема с созданием толстых (uber) jar заключается в том, что может быть только один из этих файлов (вы можете 'не может иметь более одного файла с тем же именем).Таким образом, со всеми банками, включенными в толстую банку, будет включен только один служебный файл.

В Maven мы будем использовать maven-shade-plugin, который имеет преобразователи, которые позволяют преобразовывать части сборки.Плагин Shade имеет ServicesResourceTransformer, который обеспечивает объединение содержимого служебных файлов в один служебный файл.Плагин, который вы используете для Gradle, Shadow , имеет те же возможности.Вы настраиваете это, вызывая mergeServiceFiles() в конфигурации.На самом деле я не работаю с Gradle, но также указал в эту проблему , рекомендуемая конфигурация для обработки как преобразования служебных файлов, так и преобразования манифеста основного класса:

shadowJar {
  mergeServiceFiles()
  manifest {
    attributes 'Main-Class': 'com.my.Application'
  }
}

Таким образом, я предполагаю, что с вышеуказанной конфигурацией вы также можете удалить

jar { manifest { attributes 'Main-Class': "${mainClassName}" } }

, так как плагин Shadow позаботится о создании манифеста.Опять же, я на самом деле не использую Gradle, так что это всего лишь предположение;но это звучит правильно.

...