1

I'll give you the short story first. If I, in Eclipse, export my jar file with jar files (the Runnable Jar wizard and select "Package required libraries...") instead of "Extract required libraries", every thing works, but it is excruciatingly slow to get going. If I build my jar with the extracting method the code will cause an eventual

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json

I'm not using Maven. I don't know it yet. I am mostly inexperienced with Eclipse for the most part, but I am getting there. I thought Genson would give me what I need to create JSON.

If I list my jar file and grep for MessageBodyWriter, I get

1220 Tue Nov 15 10:29:02 CST 2016 javax/ws/rs/ext/MessageBodyWriter.class             
  47 Tue Nov 15 10:29:02 CST 2016 META-INF/services/javax.ws.rs.ext.MessageBodyWriter 

To get to the longer story, I created a simple Java project in Eclipse, added external jars to my build path. Eclipse doesn't complain about anything missing. There is only one or two warnings about unused this-and-thats in my code. The export works fine either way I do it, no problems. Only execution reveals some irritation.

In my request class, I believe I have set up everything correctly. This is the simplest POST client imaginable. I have the requisite empty constructor, the correct annotations.

@XmlRootElement
@Produces(MediaType.APPLICATION_JSON)

public class QQNotificationRequest {

    @JsonProperty("id")
    private int id;
    @JsonProperty("subId")
    private int subId;
    @JsonProperty("type")
    private int type;
    @JsonProperty("scode")
    private int scode;
    @JsonProperty("datetime")
    private String datetime;
    ...

This is my ultimate call that fails

Response resp = m_webTarget.request(MediaType.APPLICATION_JSON).post(Entity.json(message));

These are my external jars

javax.ws.rs-api-2.0.1.jar
aopalliance-repackaged-2.5.0-b05.jar
hk2-api-2.5.0-b05.jar
hk2-locator-2.5.0-b05.jar
hk2-utils-2.5.0-b05.jar
javassist-3.20.0-GA.jar
javax.annotation-api-1.2.jar
javax.inject-2.5.0-b05.jar
javax.servlet-api-3.0.1.jar
jaxb-api-2.2.7.jar
jersey-guava-2.24.jar
org.osgi.core-4.2.0.jar
osgi-resource-locator-1.0.1.jar
persistence-api-1.0.jar
validation-api-1.1.0.Final.jar
jersey-client.jar
jersey-common.jar
jersey-container-servlet.jar
jersey-container-servlet-core.jar
jersey-media-jaxb.jar
jersey-server.jar
jargs.jar
genson-1.4.jar
jt400.jar
log4j-api-2.7.jar
log4j-core-2.7.jar

I feel like there is something in the jar that isn't being 'exported' correctly, but I'm not sure. Just guessing here that because Java has to go through the process of exploding all of the jars inside the big jar, that it finds what it needs to begin execution, whereas with the .classes inside the big jar, it doesn't.

Lost for the moment, but plugging along. I appreciate any pointers.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Kelly Beard
  • 684
  • 1
  • 8
  • 20

1 Answers1

2

The problem is that there are files in the META-INF/services directory of each Jersey jar, that need to be present at runtime. These files are used to automatically load and register provider classes.

When all the jars are kept separate and just add to the classpath, all the files remain in tact. But when you create a single jar, those files overlap (they all have the same name), so only one of each file with the same name will be included. So the file with Genson is probably not the one included.

You could just explicitly register Genson as a provider with the application. I don't really use Genson, so I'm not sure the correct way to do this. But quickly looking through the codebase, it looks like you need to register the GensonJsonConverter.

This may work, but it doesn't solve the main problem about the services files not being included. There may be other automzatically registered components that aren't being registered.

I'm not really an Eclipse user, so I'm not sure how to fix this problem. I know that if you are using Maven, you would use the maven-shade-plugin, as mentioned here. What this plugin would do is concatenate all the files content into one single file. This would solve the problem.

So I guess this is only really half the answer, since I am not sure how to do something similar when using Eclipse. But at least you know the problem now.

FYI, this file, is the one you are mainly concerned about. If you look through other Jersey jars, you will see that there are similar files. This is what I'm talking about when I say only one will be used. You need to find a way to concatenate their contents into one file when you build the jar

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • As @peekskillet explained the problem is that only one of those services declaration file is exported - you need a way to merge them. Regarding Genson you can also register it manually, check the jersey doc [here](http://owlike.github.io/genson/Documentation/Extensions/#jax-rs-jersey--cie). – eugen Nov 15 '16 at 22:21
  • I don't fully understand @peekskillet answer yet and your link says that just dropping Genson into the classpath will cause automatic happiness. :-) What I don't really understand is why the program will work when the jar is a bunch of jars vs a jar of extracted jars. I will plow through it some more, I guess. – Kelly Beard Nov 16 '16 at 15:18
  • 1
    No more than 2 minutes after I typed the above comment I got it to work via the extracted jars method. I went into Build Path->Configure Build Path and on the "Order and Export" tab, moved genson-1.4.jar to the top of the list and exported my project into a runnable jar and tested. So far, so good. – Kelly Beard Nov 16 '16 at 15:29
  • 1
    @KellyBeard the link I posted above also explains you how to explicitly register Genson (in case where the auto discovery magic doesn't work). – eugen Nov 16 '16 at 16:16
  • @eugen, I understand that but the promise is to add Genson to your jars and world peach emerges. ;-) I don't fully understand everything Java by my own admission. Haphazardly moving the genson jar to the top of my list in the Order And Export tab seems to have done the trick. Now to understand the whys and hows of it. – Kelly Beard Nov 16 '16 at 16:21