MessageBodyProviderNotFoundException durante l’esecuzione di jar dalla riga di comando

Sto usando il framework Java Jersey (con Maven) e uso IntelliJ come IDE. Ho riscontrato questa eccezione di runtime che si verifica SOLO quando provo a eseguire il codice dalla riga di comando (usando maven per compilare e poi java -jar) ma NON quando si esegue in IntelliJ, il che è strano.

Ho un codice Java che proverà a fare un HTTP GET su qualche URL remoto e cercherò di leggere il JSON restituito in qualche POJO di 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); 

Non sono sicuro del perché, ma quando raggiunge l’ultima riga che esegue il metodo “readEntity ()”, visualizzerò l’errore seguente:

 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/json; charset=utf-8 

Questo è strano, perché ho sicuramente la dipendenza jersey-media-json-jackson specificata nel mio pom.xml:

  org.glassfish.jersey.media jersey-media-json-jackson 2.23  

e questa è la mia class POJO che stavo cercando di leggereEntity () in:

 @Data @JsonIgnoreProperties(ignoreUnknown = true) public class ParseResponse { @JsonProperty("id") private Integer id; ...Other params... } 

E come ho detto prima, è strano che questo accada solo quando provo a lanciarmi sulla riga di comando come questa, ma non c’è nessun errore durante l’esecuzione in IntelliJ:

 mvn clean package java -jar target/NameOfJar.jar 

Ho perso qualcosa di ovvio qui? Ho esaminato altre persone con problemi simili come questo online ma non ho trovato una soluzione.

Grazie IS

Se guardi dentro il barattolo jersey-media-json-jackson dovresti vedere un file

 META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable 

Il contenuto di questo file dovrebbe essere un singolo nome completo di una class che implementa il nome del file, ovvero

 org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable 

Questo file è utilizzato dal meccanismo auto-rilevabile di Jersey per registrare automaticamente le funzionalità senza che noi dobbiamo registrarle esplicitamente. In breve, come funziona, è che tutti i moduli / vasi di Jersey che hanno componenti che dovrebbero essere registrati automaticamente, dovrebbero avere il file sopra indicato situato nel barattolo, con il contenuto che è il nome (i) del componente auto-rilevabile. Jersey utilizzerà quindi il pattern Loader di servizio per caricare le classi indicate nel file e registrarle.

Il problema che questo comporta quando si creano i jar uber è che si può avere solo una copia di un file, non è ansible avere duplicati. Quindi, cosa succede se abbiamo più vasi con il file sopra? Beh, solo uno di quei file sarà incluso nel barer di Uber. Quale? Chissà, ma c’è solo un fortunato vincitore. Quindi per il resto dei vasi, il loro meccanismo di auto-discovery non entra mai in azione. Questo è il caso della tua funzionalità di Jackson, in cui l’auto-rilevabile registra la funzione Jackson. Puoi provare a registrarti esplicitamente con la tua applicazione, e dovresti vedere che ora funziona.

Ma per quanto riguarda altri vasi / moduli che possono avere questo file? È per questo motivo che durante la creazione di uber jars, dovresti usare il plugin maven-shade-plugin . Ciò che questo plug-in ti consente di fare è combinare il contenuto dei file in modo che tutti gli oggetti individuabili vengano inclusi in quell’unico file. Di seguito è riportato un esempio di utilizzo

  org.apache.maven.plugins maven-shade-plugin 2.3  true   *:*  META-INF/*.SF META-INF/*.DSA META-INF/*.RSA       package  shade      com.example.YourApp       

Questo esempio è stato effettivamente preso dalla Guida introduttiva di Dropwizard . Puoi verificarlo per ulteriori spiegazioni. La parte principale riguarda il ServicesResorceTransformsr , che è ciò che concatena i file di servizio.