6

Я создал стартовый веб-браузер maven. Кроме того, у меня встроенный сервер приставок в моем приложении, используя плагин причал.Джерси терпит неудачу при создании uber jar с maven-assembly-plugin

Мой проект отлично работает, когда я запускаю проект, используя команду mvn jetty: run.

Но когда я упаковываю свой проект с использованием команды mvn clean package и запускаем файл jar с именем jar-with-dependencies, проект генерирует это исключение, возвращая ответ json из ресурса трикотажа.

SEVERE: MessageBodyWriter не найден для носителя type = application/json, type = class com.nitish.freecharge.model.Count, genericType = класс com.nitish.freecharge.model.Count.

Вот мой 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> 

Я создал свой Главный драйвер класс как App.java в пакете по умолчанию. Вот мой контент 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(); 
     } 
    } 
} 

Вот мой onl у класса джерси ресурса, который запускается на выполнении, когда доступ к моему проекту URL после запуска сервера:

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(); 
     } 
    } 
} 

После упаковки и запустить полный внедренный проект, используя команду Java -jar awesomeProject.jar

я получаю этот выход на сервере оперативной

enter image description here

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

ответ

15

Если вы заглянете в банку MOXy, вы увидите папку META-INF/services. В этой папке вы увидите файл с именем org.glassfish.jersey.internal.spi.AutoDiscoverable. Содержание этого файла должно быть одной строкой

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

Что этот файл на это, чтобы позволить Джерси, чтобы открыть для MoxyJsonAutoDiscoverable, который регистрирует Moxy для Джерси. Этот шаблон загрузчика услуг позволяет Джерси обнаруживать функции и регистрировать их, без необходимости регистрировать их самостоятельно.

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

Итак, у вас есть куча банок с одним и тем же файлом, но когда вы создаете банку uber, вы не можете иметь несколько файлов с тем же именем. Это просто невозможно. Таким образом, только один из файлов попадает в финальную банку. Какой ... кто знает. Но это означает, что если файлы MOXy не являются одним файлом, то его функция не будет автоматически обнаружена, и нам необходимо зарегистрировать ее самостоятельно. Таким образом, классы упаковываются в банку uber, но основной компонент функции просто не зарегистрирован.Вы можете просто зарегистрировать его самостоятельно

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

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

По этой причине вместо плагина сборки вы должны использовать maven-shade-plugin, который имеет трансформаторы, которые позволяют нам конкатенировать содержимое файлов с одинаковыми именами в файл.

конфигурация будет выглядеть как

<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 что сцепляет файлы. Эта конкретная конфигурация плагина взяла с Dropwizard getting started. Вы можете проверить это для дальнейшего объяснения.

+0

Большое спасибо. jerseyServlet.setInitParameter ("jersey.config.server.provider.classnames", "org.glassfish.jersey.moxy.json.MoxyJsonFeature"); Решил проблему. Но при использовании maven-shade-plugin конечный результат - файл awesomeProject.war, но вместо этого мне нужен файл jar. Как получить исполняемый файл jar с основным классом с помощью mave-shade-plugin? –

+0

Посмотрите на свой '' в вашем файле pom.xml. Это должно быть 'jar' не' war'. Я понимаю, что вам нужна «война», чтобы использовать «jetty-maven-plugin», но чтобы получить банку, вам нужно будет запомнить ее, чтобы изменить ее на банку. –

+0

Спасибо peeskillet! это сработало отлично. –