Jersey: A message body writer for Java Class and MIME mediatype application/json was not found - eclipse

after trying to figure out what's my problem I finally decided to ask you how to solve my problem. I've seen different people with the same problem and I tried all the things they were adviced to do but nothing helped with my issue. So basically I'm having a RESTful Service which I build using Jersey. For my client I would like to return an object in JSON Format. I read through different tutorials and decided that it makes sense to use jersey-json-1.8 library. I added everything to my project as usual and tried to run it but each time I'm calling the service (via get request atm.) I'm getting HTTP Error Code 500 (internal server error) and my server responds that no message body writer could be found.
If I'm returning XML it works just fine and everything is great. I also tried copying jersey-json-1.8.jar to my Tomcat lib folder because I had to do this with the mysql lib I'm using but it didn't help either.
I would be really glad if you could help me out to get this stuff working!
If you need any more information just leave a comment and I'll provide it as quickly as humanly possibly :)
My project setup is:
3 Different packages
1. My RESTfulServices
2. My Java Work where i handle SQL connections etc.
3. A package where I store all my models that I need to work with and that I want to return in JSON Format (in my example a route for a testdrive)
A Tomcat Webserver
IDE: Eclipse
I'm using Maven
No matter what or how I'm trying to return the Object it just won't work and I'm constantly getting the error message :
Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class com.mykong.models.Teststrecke, and Java type class com.mykong.models.Teststrecke, and MIME media type application/json was not found
EDIT:
Here's my JSON Service Method
#Path("/hellojson")
public class JSONService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public ArrayList<Route> getJSONMsg()
{
Route ts = new Route();
ts.setId(1);
ts.setName("HelloWorld");
Route ts2 = new Route();
ts2.setId(2);
ts2.setName("HelloWorld");
ArrayList<Route> availRoutes = new ArrayList<Route>();
availRoutes.add(ts);
availRoutes.add(ts2);
return availRoutes;
}
}

Try adding Genson library to your classpath http://owlike.github.io/genson/.
It is a json<>java streaming and databinding api. It integrates well with jersey, to get you running you need 0 configuration. Jersey detects that the library is in your classpath and enables json mapping by delegating to Genson.

Include this dependencies in your POM.xml and run Maven -> Update
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>0.99</version>
</dependency>

Adding below dependency solved my issue. As per #eugen I tried adding Genson dependency which helped get rid of the exception, however my server was throwing 400 bad request for some reason. It seems like Genson was not able to stream the json request properly. But below dependency worked fine. Hope it helps others as this problem was driving me nuts!
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.0</version>
</dependency>

Moving jersey-json dependency to the top of the pom.xml solved this problem for me.
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18.1</version>
</dependency>
<!-- other dependencies -->
</dependencies>

Check under Maven Dependencies in the Package Explorer, if you don't see that or jersey-bundle-1.8.jar, then you probably have specified just jersey-server. Change the dependency in pom.xml to jersey-bundle and it should work.

Jersey 2.4: I faced this problem too and posting this incase it helps someone. I picked this up from the Jersey API Specification for JSON Integration : (https://jersey.java.net/documentation/latest/user-guide.html#json)
I used Jettison to integration with Jersey with JSON. But even after adding all the libraries I got the error: A message body writer for Java Class and MIME mediatype application/json was not found
Its all about adding the right libraries and also registering features> I added one extra library in addition to all the others that Jersey provides: jersey-media-json-jettison-2.4.jar. And added the below code to register Jettison Feature.
public class MyApplication extends ResourceConfig{
public MyApplication() {
register(JettisonFeature.class);
packages("org.XXX.XXX.XXX");
}

This question was asked a while ago, but for those reading, note that jersey servlet container has it's own POJO mapper.
Enable it by adding the following to your web.xml
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
I did notice some discrepancies in how jersey and genson map objects. For example, if a class has a field of type A which is set to an instance of B, which extends A, genson will not properly serialize B, while jersey does.

Remove #Produces(MediaType.APPLICATION_JSON); and use JSONLibraries.zip file to convert your data to and from JSON. It is working perfectly.The problem with above code is that it is using maven and and jackson combination. So APPLICATION_JSON cannot be found when you are using only jersey.
I worked with to/from JSON conversion stuff, It gave me same error, I tried with this solution and it was working properly.
Code:
#Path("/hellojson")
public class JSONService {
#GET
public ArrayList<Route> getJSONMsg()
{
Route ts = new Route();
ts.setId(1);
ts.setName("HelloWorld");
Route ts2 = new Route();
ts2.setId(2);
ts2.setName("HelloWorld");
ArrayList<Route> availRoutes = new ArrayList<Route>();
availRoutes.add(ts);
availRoutes.add(ts2);
return JSONObject.fromObject(availRoutes.toString()));
}
}

The above issue will be solved by using the jackson library instead of the genson.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.25</version>
</dependency>
As in my case genson was giving an empty json in the response but will be fine if we are converting the json to string.But will create an undesirable output because in the response you will get a string not a json.So better to go with the jackson library which will do it very easily.
Note: Jackson will convert your response to the json only if the class is implementing the Serializable Interface.So if you are sending JSONObject, then better to send the List of JSONObject.

Related

open api swagger-ui giving white label error page (404) after moving the project as a module in a project

I have the working project in Spring boot which was a standalone app. Now, to modularize, I have split the app and put the api in a module. Earlier the swagger-ui.html page was working, but after this, it is not working.
my pom.xml has these 2 dependencies
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.1</version>
</dependency>
My Application.java has the following code
#Bean
#Profile("!prod")
public OpenAPI caffeAPIRegistry() {
return new OpenAPI()
.info(new Info().title("My Awesome API")
.description("Powering UI")
.version("v3.0.0")
.license(new License().name("google Inc.,").url("https://google.com")));
}
The pom.xml fragment for the parent project mapping
<parent>
<artifactId>API_Project</artifactId>
<groupId>com.abc</groupId>
<version>2.0.0.RELEASE</version>
</parent>
I have been searching for a long time in internet if moving api as a module might require any other change, but could not find any help.
Are the interfaces with the REST annotations in a different package? if yes then that is the issue.

REST with JAX-RS tomcat server returning "requested resource is not available"

I was following short tutorial on creating REST api using JAX-RS. I am using Tomcat server v7.0. When I run the application on the server I get error 404-requested resource is not available.
The project is Maven based, and my pom.xml file includes the following line
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
I do not have web.xml file as a result. That was how the tutorial was achieved. I do not have index.html/jsp file. I have created two classes RESTconfig.java and BookResources.java
...import statements
#ApplicationPath("api")
public class RESTconfig extends Application {
}
...import statements
#Path("books")
public class BookResources {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String books() {
return "Hello world";
}
}
My pom.xml file looks like this
<groupId>com.dere</groupId>
<artifactId>myrest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Once I run the application on the server and go to http://localhost:9090 I am able to see Tomcat home page, but if try to get data http://localhost:9090/myrest/api/books I get the 404 error, i.e requested resource is not available, I mentioned above.
Most of the examples or usage I saw online involve using web.xml and providing root of the application and using a servlet. This is my first exposure to building REST api. I may have misunderstood the whole thing or I skipped some step. I look forward for your help.
I am using Eclipse Photon for Java EE
Look at this
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
This is nothing more than basically a bunch of interfaces for the EE spec. There is no implementation. Java EE servers will have the implementation. Tomcat is not an EE server. The only part of the EE spec it will definitely have the implementation for is Servlets and JSP (the web profile). If you want an EE server, checkout Glassfish or Wildfly.
You are trying to work with the JAX-RS spec, where Tomcat for sure by default does not have an implementation for. So you need to add that implementation. The easiest implementation, IMO to get started with, is Jersey. You can simply add this dependency
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25.1</version>
</dependency>
and it will get you up and running. Keep the Jersey User Guide handy. It will come in use.

GWT java.util.Date serialization with CustomFieldSerializer fails in debugger

I had a problem with the way Date was serialized by GWT 2.4.0 and the easiest solution seemed to be to write a Date_CustomFieldSerializer - overloading the original implementation.
But depending on how i start the application i get different results.
Gladly the deployed version seems to work without any trouble. Starting a debugging session from Eclipse on the other hand leads to this message:
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: The response could not be deserialized
at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:221)
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
...
Caused by: com.google.gwt.user.client.rpc.SerializationException: java.util.Date/1659716317
at com.google.gwt.user.client.rpc.impl.SerializerBase.getTypeHandler(SerializerBase.java:153)
I debugged both the server and the client side and the server is using my serializer and the client side fails when it's looking up the serializer by its "type signature": java.util.Date/1659716317
Oddly the client has a map containing a serializer for java.util.Date/965047388.
How does GWT create these type signatures and how can they be different when i am using the GWT debugger?
-- edit --
I now know how the numbers are generated. GWT calculates a CRC32 hash of the class names in the hierachy (and sometimes the methods as well).
java.util.Date
com.google.gwt.user.client.rpc.core.java.util.Date_CustomFieldSerializer
java.lang.Object
--> 1659716317 (server side)
java.util.Date
java.lang.Object
--> 965047388 (client side)
I just can't find the spot when the GWT calculates the hashes for the client side to see why it doesn't know the serializer, because it's somewhere between a CompilingClassLoader and runtime generated classes.
For anyone who is having this same problem, I had the error message for a few days now, yesterday I found the cause!
I had 2 versions of different versions of the class Date_CustomFieldSerializer on my classpath. The wrong one was added in my classpath because it was in the gwt-servlet-2.2.0.jar that was a dependency of the google gin 1.5 library which I use in my project.
I upgraded the google gin in my project to version 2.1.2 with doesn't have a gwt-servlet dependency to. This way no different versions of the Date_CustomFieldSerializer class should be in the classpath. If you have the same cause and you don't want to upgrade your google gin, you can simply exclude the dependency gwt-servlet-2.2.0 from the google gin 1.5 dependency in your pom. Like this:
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
The reason the client side didn't have the serializer was simply that GWT couldn't compile it to JavaScript (because of some server side logging references that were added by accident).
Unless you use "strict" compilation rules, these JavaScript compiles fail silently (or add a single line to the compiler output that gets drowned in other messages) and you won't know what you're missing until you need it.

SOAP web services NPE on redeployment Tomcat 6

I'm using Tomcat 6 and I have a web application that uses a SOAP web service. I generated the client classes to use using cxf-codegen-plugin in maven, my dependencies are :
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-api</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.6.1</version>
</dependency>
Everything works until I redeploy my war on tomcat (or even doing a simple touch on it: no code modification at all). Using the same url to access my page that makes the SOAP service call I have this weird NPE:
java.lang.NullPointerException
at com.ctc.wstx.util.SymbolTable.findSymbol(SymbolTable.java:385)
at com.ctc.wstx.sr.StreamScanner.parseLocalName(StreamScanner.java:1831)
at com.ctc.wstx.sr.BasicStreamReader.handleNsAttrs(BasicStreamReader.java:2997)
at com.ctc.wstx.sr.BasicStreamReader.handleStartElem(BasicStreamReader.java:2941)
at com.ctc.wstx.sr.BasicStreamReader.handleRootElem(BasicStreamReader.java:2078)
at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2058)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1117)
at com.sun.xml.internal.ws.util.xml.XMLStreamReaderFilter.next(XMLStreamReaderFilter.java:81)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:78)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextContent(XMLStreamReaderUtil.java:99)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextElementContent(XMLStreamReaderUtil.java:89)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.hasWSDLDefinitions(RuntimeWSDLParser.java:209)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:119)
at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)
at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)
at javax.xml.ws.Service.<init>(Service.java:56)
at some.package.flightinfo.model.flightstatsv2.soap.AirportsV1SoapService.<init>(AirportsV1SoapService.java:48)
at some.package.flightinfo.adapter.FlightStatsV2ContentAdapter.getAirportsByGPSCoordinate(FlightStatsV2ContentAdapter.java:107)
The only way I can get my web application working again is to restart tomcat which is no option at all.
I am totally clueless on what's going on, has anyone ever experienced this problem before?
Cheers.
Well, you are missing the cxf-rt-frontend-jaxws dependency. Thus, you are ending up using the JAX-WS reference impl built into the JDK, not CXF. If you add the CXF dependencies, does that fix it? Could be a bug in the RI or something.

How to output the generated request and response from Groovy RestClient?

i am currently using the RestClient and cannot seem to figure out how to output the request xml and response xml for debugging and informational purpose...
I tried the solution mentioned here:
http://agileice.blogspot.com/2009/09/pretty-printing-xml-results-returned.html
But that fails to work, any other suggestions?
The accepted answer (turn on wire logging using log4j) is basically correct, but I've had a fair bit of trouble turning on wire logging for HTTP builder in my Groovy script. For some reason, dropping a log4j.xml file in my $GROOVY_HOME/conf directory isn't working. Ultimately, I had to just add the appropriate logging options to the groovy command when I was running it.
groovy
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-Dorg.apache.commons.logging.simplelog.showdatetime=true
-Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG
myscript.groovy
Since it depends on HTTPClient, you could try enabling header and wire logging for your script.
http://blog.techstacks.com/2009/12/configuring-wire-logging-in-groovy-httpbuilder.html
http://hc.apache.org/httpcomponents-client-ga/logging.html
If you're using spring-boot you can set logging.level in your application properties file and use an slf4j back-end.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>