Jersey Client Fails To Deserialize to Object - java

So I am trying to implement a simple Jersey Client that hits a public API to get movie times etc..
https://api.eventcinemas.co.nz/Api/Movies/GetMovies
I have gone through tutorials on how to do this and have implemented two methods that deserialzse the JSON response into:
A String
An Object (POJOs)
The issue is this: the JSON to String method is working correctly, printing the String to console gives me the expected result. However when trying to deserialize to my Java Objects I am always getting null.
I have tried a few simple things such as different dependency versions, different API calls etc but no luck. To save time I have used an online converter to take the JSON response and populate the necessary POJOs for deserialization, I have taken this to be correct.
Would someone be kind enough to point me in the right direction on why I am always getting null, I feel like its something small or silly that I have missed. Thanks in advance!
So starting with my pom.xml dependencies...
pom.xml
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.26</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.26</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.26</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.26</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
My Client is as follows:
MoviesClient:
package nz.co.brownbridge.application;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
public class MoviesClient {
protected MoviesResponse getMovieDetails() {
/*JSON to POJO*/
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("https://api.eventcinemas.co.nz/Api/Movies/GetMovies");
MoviesResponse response = webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).get(MoviesResponse.class);
return response;
}
protected String getMovieDetailsString() {
/*JSON to String*/
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("https://api.eventcinemas.co.nz/Api/Movies/GetMovies");
String response = webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
return response;
}
}
and finally the main() class:
Application Class:
package nz.co.brownbridge.application;
public class Application {
public static void main(String[] args) throws InterruptedException {
MoviesClient moviesClient = new MoviesClient();
String stringResponse = moviesClient.getMovieDetailsString();
MoviesResponse pojoResponse = moviesClient.getMovieDetails();
System.out.println("Printing String Response...");
System.out.println();
System.out.println(stringResponse);
System.out.println();
System.out.println();
System.out.println("Printing POJO Response...");
System.out.println();
System.out.println(pojoResponse);
}
}
Would output the following:
Printing String Response...
//super long but correct string response goes here
Printing POJO Response...
ClassPojo [Data = null, Success = null]

Related

Jersey 2.x post call MessageBodyWriter not found for media type=application/xml

I am using Jersey version 2.29 /java 1.8 on tomcat version 8.5 and trying to retrurn the hasmap<String,String> from jersey rest post service call.
I am getting below exception on server when it is trying to write the hasmap in response.
Aug 23, 2019 10:20:47 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.LinkedHashMap, genericType=java.util.Map.
Below are the details of pom.xml,server and jersey client side code.
pom.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version> </dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
Client Code
ClientConfig configuration=new ClientConfig();
Client restClientConfig = ClientBuilder.newClient(configuration);
WebTarget webTarget=restClientConfig.target("http://localhost:8080/messenger/webapi/messages/testMap");
HashMap<String,String> mapStr=new HashMap<String,String>();
mapStr.put("a","1");
mapStr.put("b","2");
webTarget.request()
.accept(MediaType.APPLICATION_XML)
.post(Entity.json(mapStr));
Map<String,String> responseMap = new HashMap<String,String>();
GenericType<Map<String,String>> entity = new GenericType<Map<String,String>>() {};
Response xmlResponse = Response.ok(entity).build();
System.out.println("XMLResponse Is :" + xmlResponse + ":"+ responseMap.size());
Jersey Post Service code
#POST
#Path("/testMap")
#Produces(value = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
#Consumes(value = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Map<String,String> postMapMessage(Map<String,String> mapMessage) {
System.out.println("It is been invoked....and this time we will add the new MapMessage");
if(mapMessage!=null)
{
System.out.println("Size of the Map Message:" + mapMessage.size());
mapMessage.put("c","3");
}
return mapMessage;
}
I have tried several solutions found on internet but nothing seems to be working for this.
Can anybody please tell me what wrong I am doing in above code snippet?
I am able to partially fix the issue by creating the below wrapper class.
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class JaxrsMapWrapper<T,K> {
private Map<T,K> map;
public JaxrsMapWrapper(){
}
#Override
public String toString() {
return map .toString();
}
public void setMap(Map<T,K> map) {
this.map = map;
}
public Map<T,K> getMap() {
return map;
}
}
By using the above class below getservice returning the typeof Map is working absolutly fine.
#GET
#Path("/mapWarpperReceive")
#Produces({MediaType.APPLICATION_XML})
public JaxrsMapWrapper<String,String> getWarpperMapMsgStr()
{
System.out.println("Returning the MapMessage as String ");
Map<String,String> originalMap=new HashMap<String,String>(){{put("a","a");put("b","b");}};
JaxrsMapWrapper<String,String> jaxRsMapWrapper=new JaxrsMapWrapper<>();
jaxRsMapWrapper.setMap(originalMap);
return jaxRsMapWrapper;
}
But when I am trying to use the same class JaxrsMapWrapper with type of Map it is throwing Error 500 Internal server error while invoking through postman.
#GET
#Path("/customMap")
#Produces({MediaType.APPLICATION_XML})
public JaxrsMapWrapper<String,BookBo> getWarpperMapMsgWithCustomObject()
{
System.out.println("Returning the MapMessage as String and Custom Message ");
Map<String,BookBo> originalMap=new HashMap<>();
originalMap.put("a",new BookBo(1,"Jinesh"));
JaxrsMapWrapper<String,BookBo> jaxRsMapWrapper=new JaxrsMapWrapper();
jaxRsMapWrapper.setMap(originalMap);
return jaxRsMapWrapper;
}
Below is the code for the User defined Java Object BookBo.
#XmlRootElement
public class BookBo implements Serializable{
private Integer id;
private String name;
public BookBo() {
}
public BookBo(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
//getters and setters of the field
}
What am I missing in the above code due to which while writing the Map in response is not working?

Why isn't my Jax-RS client object deserializing JSON lists in this HTTP response, even though the object mapper does?

I'm starting to write a client for a REST API, and I've started with a simple call that returns a relatively simple JSON object: one resultCode string, one message string, and a list of objects. When I retrieve the object as a string first, and decode it with ObjectMapper, it unmarshals just fine, including the list of objects. However, when I retrieve it using the Client object, it retrieves only the string properties, and not the list of objects. I'd like to model API responses that are more complicated than this, but I don't think it'd be wise until I get past this hurdle.
I have tried using annotations like creating a setResultItems method with the #JsonSetter annotation. My initial example used getters and setters, but the example I'm posting uses public fields to save space -- the result is the same. I've also tried forcing the Client object to use the same ObjectMapper, by registering a JacksonJsonProvider to it. One thing I've noticed is that the ObjectMapper calls the constructor that sets everything up right away, but the Client requires a no-args constructor, and sets the properties after creating the object.
Here is the simplest version of the response object class:
class ResponseObject {
public String resultCode;
public String message;
public List<Map<String,String>> resultItems;
ResponseObject() {
System.out.println("Blank constructor called");
}
ResponseObject(
#JsonProperty("resultItems") List<Map<String,String>> resultItems,
#JsonProperty("message") String message,
#JsonProperty("resultCode") String resultCode ) {
System.out.println("Good constructor called");
this.resultCode = resultCode;
this.message = message;
this.resultItems = resultItems;
}
private void print() {
System.out.println("resultCode: " + resultCode);
System.out.println("message: " + message);
System.out.println("resultItems: " + resultItems.toString());
}
}
My test application runs this method in a try-catch:
private static void doGetVariable() throws IOException {
Client client = ClientBuilder.newClient();
// hey this means the client should decode it the same way right?
ObjectMapper mapper = new ObjectMapper();
JacksonJsonProvider provider = new JacksonJsonProvider(mapper);
client.register(provider);
System.out.println("Getting string and deserializing it");
String sresp = client.target(URL)
.request(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println("string: "+sresp);
ResponseObject resp1 = mapper.readValue(sresp, ResponseObject.class);
resp1.print();
System.out.flush();
System.out.println("\nGetting object directly from the client");
ResponseObject resp2 = client.target(URL)
.request(MediaType.APPLICATION_JSON)
.get(ResponseObject.class);
resp2.print();
}
Since these things seem to matter, here are the dependencies in my pom.xml file. I had to add the Jersey ones because if I don't, I get a ClassNotFoundException because it can't find JerseyClientBuilder. I think that's a hint but I'm not sure what it means.
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.rx</groupId>
<artifactId>jersey-rx-client</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.9</version>
</dependency>
When I run it, here is the output. You can see the raw JSON in the line that starts with string:. I expect resultItems to be the same for both requests, but it is only correct in the first request. Note that it still sets resultCode and message in both attempts, so it's doing something at least.
Getting string and deserializing it
string: {"resultItems":[{"name":"MAX.PACKETSIZE","value":"64512"}],"message":"OK - the variables were successfully retrieved","resultCode":"0"}
Good constructor called
resultCode: 0
message: OK - the variables were successfully retrieved
resultItems: [{name=MAX.PACKETSIZE, value=64512}]
Getting object directly from the client
Blank constructor called
resultCode: 0
message: OK - the variables were successfully retrieved
resultItems: []
Also, I would prefer to get rid of the no-args constructor, so that I can make all the fields private final and encapsulate everything properly.

Jersey test set max http header size

Does any body know how to set the max header size while using Grizzly2 and Jersey Test .
I'm currently using the following dependencies :
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.23.2</version>
</dependency>
and i have a simple Test class extending Jersey test like this :
public class JerseyTestInitializer extends JerseyTest {
#Override
public Application configure() {
// Configuration stuff
}
#Test
public void test() {
WebTarget webTarget = target(URL);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON)
.header("test",SOME VALUE THAT IS MORE THAN 8K Characters);
SomeEntity someEntity = new SomeEntity();
Response response = invocationBuilder.post(Entity.entity(someEntity, MediaType.APPLICATION_JSON));
}
}
While performing the post i'm currently getting a HTTP status 400 with no other information about the bad request. If I use a header value with less than 8K characters , than it's working for me.
Please advice.
Thanks
Mohit
Please check on this question about URI size (this is also a header).
Jersey/Grizzly POST fails for large URI

Can't get json from Swagger + Jersey

I have RESTful service based on Jersey 1.18.1 and I want to show my API via Swagger.
Firstly I have to get JSON. I read this instruction: Swagger Core Jersey 1.X Project Setup 1.5. Swagger allows to set up a configuration different methods and I decided to use custom Application subclass. I did everything step by step but I can't get JSON which I have to use for swagger-ui.
What I did:
My custom Application
#ApplicationPath("api/v1")
public class DiscountsApp extends Application{
public DiscountsApp() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8002");
beanConfig.setBasePath("swaggerapi");
beanConfig.setResourcePackage("alexiuscrow.diploma.endpoints");
beanConfig.setScan(true);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet();
resources.add(ShopsResources.class);
//...
resources.add(com.wordnik.swagger.jaxrs.listing.ApiListingResource.class);
resources.add(com.wordnik.swagger.jaxrs.listing.SwaggerSerializers.class);
return resources;
}
}
ShopsResources
#Path("/shops")
#Api(value="/shops", description="Shops")
public class ShopsResources {
#GET
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "List shops", httpMethod = "GET",
notes = "List nearest or locality shops",
response = Shops.class, responseContainer = "List")
public String getShops(
#ApiParam( value = "Radius", required = false)
#QueryParam("radius") String radiusParam,
#ApiParam( value = "Latitude", required = true)
#QueryParam("lat") String latParam,
#ApiParam( value = "Longitude", required = true)
#QueryParam("lng") String lngParam) throws SQLException{
//The list of Shops objects is serialized to string
//using the custom GSON serializer and I know
//that there is the better method of the solution of this task.
}
}
}
Some dependencies from pom.xml
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey-jaxrs</artifactId>
<version>1.5.1-M2</version>
</dependency>
After deploy application to Tomcat I tried to get http://localhost:8002/swaggerapi but I've got no result.
I didn't find the swagger.json in root of my application (/tomcat8/webapps/app).
What's wrong?
How can I get JSON with my API?
I did not correctly build the url.
Correct:
http://{host}:{port}/{context root of application}/{path from #ApplicationPath}/swagger.json
In my case: http://localhost:8080/app/api/v1/swagger.json
Thx to Ron.
adding a relative path worked for me (this is using .netcore 1.1)
app.UseSwaggerUI(s => {
s.RoutePrefix = "help";
s.SwaggerEndpoint("../swagger/v1/swagger.json", "MySite");
s.InjectStylesheet("../css/swagger.min.css");
});

REST Jersey Client - unable to parse JSON into POJO class

I am trying to build a rest client using jersey 2.13.
The rest endpoint is in : https://gist.githubusercontent.com/richersoon/ff4dd5c5abe414c5ec4c/raw/4ce49c32e57bf071d052f7efa76f332d60308035/user.json
But when I tried to run the application I got:
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain, type=class com.napier.entity.User, genericType=class com.napier.entity.User.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:173)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.ScopedJaxrsResponse.access$001(ScopedJaxrsResponse.java:56)
at org.glassfish.jersey.client.ScopedJaxrsResponse$1.call(ScopedJaxrsResponse.java:77)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:397)
at org.glassfish.jersey.client.ScopedJaxrsResponse.readEntity(ScopedJaxrsResponse.java:74)
at com.napier.service.rest.UsersClient.main(UsersClient.java:20)
Here's the code:
public class UsersClient {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(
UriBuilder.fromUri(
"https://gist.githubusercontent.com/richersoon/ff4dd5c5abe414c5ec4c/raw/4ce49c32e57bf071d052f7efa76f332d60308035/user.json"));
Response response = target.request().accept(MediaType.APPLICATION_JSON).get(Response.class);
User user = response.readEntity(User.class);
System.out.println(user);
}
}
Here's the POJO:
#XmlRootElement
public class User {
private String firstname;
private String lastname;
private String photourl;
... setters and getters...
}
Here's the POM:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.13</version>
</dependency>
Please guide me because I am totally new to webservices.
Your client is accepting results of media type "application/json", but your REST webservice returns "text/plain". Check this post to see a possible solution: MessageBodyReader not found for media type=application/octet-stream
Seems you are trying to access the wring uri, which is plain text.
I was able to get it to work with this uri, which is the actual .json file
"https://gist.github.com/richersoon/ff4dd5c5abe414c5ec4c#file-user-json"

Categories

Resources