maven jersey jersey-2.0 embedded-jetty jar-with-dependencies

Jersey falla al crear uber jar con maven-assembly-plugin



jersey-2.0 embedded-jetty (1)

Si mira dentro del contenedor MOXy, verá una carpeta META-INF/services . En esa carpeta, verá un archivo llamado org.glassfish.jersey.internal.spi.AutoDiscoverable . El contenido de ese archivo debe ser una sola línea.

org.glassfish.jersey.moxy.json.internal.MoxyJsonAutoDiscoverable

El objetivo de este archivo es permitir que Jersey descubra el MoxyJsonAutoDiscoverable , que registra MOXy para Jersey. Este patrón de cargador de servicios permite a Jersey descubrir características y registrarlas, sin que tengamos que registrarlas nosotros mismos.

El problema que esto plantea al crear un jar súper es que puede haber varios archivos jar con el mismo archivo, ya que los archivos jar diferentes tienen características diferentes para descubrir, pero el archivo debe tener ese nombre exacto, ya que así es como funciona el patrón del cargador de servicios.

Por lo tanto, tiene un montón de jarras con el mismo archivo, pero cuando crea el jar uber, no puede tener varios archivos con el mismo nombre. Simplemente no es posible. Entonces, solo uno de los archivos se coloca en el frasco final. Cuál ... quién sabe. Pero eso significa que si los archivos de MOXy no son ese único archivo, entonces su característica no se descubrirá automáticamente, y debemos registrarlo nosotros mismos. Por lo tanto, las clases se empaquetan en el archivo uber, pero el componente principal no está registrado. Podrías registrarlo tú mismo

jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", "org.glassfish.jersey.moxy.json.MoxyJsonFeature");

pero, ¿qué pasa con todas las otras características posibles que posiblemente se omiten porque su archivo de detección automática no está incluido?

Por esta razón, en lugar del complemento de ensamblaje, debe usar el maven-shade-plugin , que tiene transformadores que nos permiten concatenar el contenido de los archivos de servicio en un solo archivo.

La configuración se vería algo así

<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>

ServicesResorceTransformaer es lo que concatena los archivos. Esta configuración particular del complemento estaba tomando del Dropwizard para comenzar . Es posible que desee comprobar eso para obtener más explicaciones.

He creado una aplicación web maven jersey starter. También he incrustado el servidor de embarcadero en mi aplicación usando el complemento de embarcadero.

Mi proyecto funciona bien cuando ejecuto mi proyecto usando el comando mvn jetty: run.

Pero cuando empaquete mi proyecto usando el comando mvn clean package y ejecuto el archivo jar que tiene el nombre jar-with-dependencies, el proyecto arroja esta excepción mientras devuelve una respuesta json de un recurso jersey.

SEVERO: MessageBodyWriter no encontrado para media type = application / json, type = class com.nitish.freecharge.model.Count, genericType = class com.nitish.freecharge.model.Count.

Aquí está mi archivo pom.xml

http://maven.apache.org/maven-v4_0_0.xsd ">

<modelVersion>4.0.0</modelVersion> <groupId>com.nitish.freecharge</groupId> <artifactId>wordcount</artifactId> <packaging>war</packaging> <version>2.0</version> <name>wordcount</name> <build> <finalName>wordcount</finalName> <resources> <resource> <directory>src/main/java</directory> </resource> <resource> <directory>src/main/resources</directory> </resource> <resource> <directory>src/main/webapp</directory> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <inherited>true</inherited> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.0.v20150612</version> <configuration> <scanIntervalSeconds>5</scanIntervalSeconds> <webApp> <contextPath>/wordcount</contextPath> </webApp> <httpConnector> <!--host>localhost</host --> <port>9999</port> </httpConnector> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>package-jar</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <configuration> <finalName>awesomeProject</finalName> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <appendAssemblyId>false</appendAssemblyId> <archive> <manifest> <mainClass>App</mainClass> </manifest> </archive> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>${jersey.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.3.8.v20160314</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.3.8.v20160314</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.4</version> </dependency> </dependencies> <properties> <jersey.version>2.22.2</jersey.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>

He creado mi clase de controlador principal como App.java en el paquete predeterminado. Aquí está mi contenido de App.java

import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; public class App { public static void main(String []gg){ Server server = new Server(9999); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); context.setContextPath("/"); server.setHandler(context); ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/wordcount/*"); jerseyServlet.setInitOrder(1); jerseyServlet.setInitParameter("jersey.config.server.provider.packages","com.nitish.freecharge.resources"); try { System.out.println("Starting the server.."); server.start(); System.out.println("Server started"); server.join(); } catch(Exception e) { System.out.println("Exception in starting the server "); e.printStackTrace(); } } }

Aquí está mi única clase de recurso jersey que se ejecuta cuando accedo a la URL de mi proyecto después de iniciar el servidor:

package com.nitish.freecharge.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import com.nitish.freecharge.dao.FileDAO; import com.nitish.freecharge.model.Count; /** * Root resource (exposed at "count" path) which handles HTTP GET method and returns the count value; */ @Path("/count") public class CountResource { private FileDAO fileDAO=new FileDAO(); /** * Method handling HTTP GET requests. The returned object will be sent * to the client as "application/json" media type. * * @return String that will be returned as a application/json response. */ @GET @Produces(MediaType.APPLICATION_JSON) @QueryParam("query") public Response getWordCount(@QueryParam("query")String query) { Error error=null; Count count=null; try{ if(query!=null){ query=query.trim(); if(query.length()>0 && query.matches("^[A-Za-z]+$")){ long c=fileDAO.getCount(query.toLowerCase()); count=new Count(c); }else{ error=new Error("Some Error Occured.Please Try Again With a new word!"); } }else{ error=new Error("Some Error Occured.Please Try Again!"); } }catch(Exception e){ error=new Error(e.getMessage()); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build(); } if(count!=null){ return Response.status(Status.OK).entity(count).build(); }else{ return Response.status(Status.BAD_REQUEST).entity(error).build(); } } }

Después de empaquetar y ejecutar el proyecto integrado completo usando el comando java -jar awesomeProject.jar

Obtengo esta salida en el indicador del servidor

He intentado mucho y no he podido empaquetar mi aplicación web integrada de tal manera que este problema se resuelva. Soy nuevo en maven y packaging. Ayuda amablemente donde estoy cometiendo un error.