java - ejecutar - no hay ningún atributo de manifiesto principal en maven
MessageBodyProviderNotFoundException mientras ejecuta jar desde la línea de comandos (1)
Estoy usando el marco Java Jersey (con Maven), y uso IntelliJ como mi IDE. Me he encontrado con esta excepción de tiempo de ejecución que SOLO sucede cuando intento ejecutar el código desde la línea de comandos (usando maven para compilar y luego java -jar) pero NO cuando se ejecuta dentro de IntelliJ, lo cual es extraño.
Tengo un código Java que intentará hacer un HTTP GET en alguna URL remota e intentará leer el JSON devuelto en algún POJO de Lombok:
String targetUrl = "some valid URL";
WebTarget webTarget = client.target(targetUrl);
Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE).get();
ParseResponse parseResponse = response.readEntity(ParseResponse.class);
No estoy seguro de por qué, pero cuando llegue a la última línea que hace el método "readEntity ()", obtendré el siguiente error:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/json; charset=utf-8
Esto es extraño, porque definitivamente tengo la dependencia jersey-media-json-jackson especificada en mi pom.xml:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23</version>
</dependency>
y esta es mi clase POJO en la que estaba tratando de leer Entity ():
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ParseResponse {
@JsonProperty("id")
private Integer id;
...Other params...
}
Y como mencioné antes, es extraño que esto solo ocurra cuando intento ejecutar en la línea de comando de esta manera, pero no hay ningún error al ejecutar en IntelliJ:
mvn clean package
java -jar target/NameOfJar.jar
¿Me perdí algo obvio aquí? He mirado a otras personas con problemas similares como este en línea, pero no he encontrado una solución.
Gracias es
Si miras dentro del frasco
jersey-media-json-jackson
deberías ver un archivo
META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
El contenido de este archivo debe ser un único nombre completo de una clase que implemente el nombre del archivo, es decir
org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable
Este archivo es utilizado por el mecanismo de detección automática de Jersey para registrar características automáticamente sin que tengamos que registrarlas explícitamente. Brevemente, cómo funciona, es que todos los módulos / frascos de Jersey que tienen componentes que deben registrarse automáticamente, deben tener el archivo mencionado anteriormente ubicado en la jarra, cuyo contenido es el / los nombre (s) del componente auto-descubrible. Jersey luego usará el patrón de Service Loader para cargar las clases nombradas en el archivo y registrarlas.
El problema que esto causa al crear frascos uber es que solo puede tener una copia de un archivo, no puede tener duplicados.
Entonces, ¿qué pasa si tenemos varios frascos con el archivo anterior?
Bueno, solo uno de esos archivos se incluirá en el uber jar.
¿Cúal?
Quién sabe, pero solo hay un afortunado ganador.
Entonces, para el resto de los frascos, su mecanismo de autodescubrimiento nunca se activa. Este es el caso de su función Jackson, donde el autodescubrimiento registra la característica
JacksonFeature
.
Puede intentar registrarse explícitamente con su aplicación, y debería ver que ahora funciona.
Pero, ¿qué pasa con otros frascos / módulos que pueden tener este archivo? Es por esta razón que al crear frascos uber, debe usar el maven-shade-plugin . Lo que este complemento le permite hacer es combinar el contenido de los archivos para que todos los descubrimientos se incluyan en ese único archivo. A continuación se muestra un ejemplo de uso
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.YourApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Este ejemplo fue tomado de
la Introducción
de
Dropwizard
.
Puede consultarlo para obtener más explicaciones.
La parte principal de preocupación es
ServicesResorceTransformer
, que es lo que concatena los archivos de servicios.