Java consume JSON list from Rest service GET - java

The error I receive:
SEVERE: A message body reader for Java class java.util.List,
and Java type java.util.List<com.testapp.Category>,
and MIME media type text/html; charset=utf-8 was not found
Trying to consume a JSON response from a Rest service using the GET method with Jersey. The response from the server looks like this when I use curl:
[{"category":{"id":"4d9c5dfc8ddfd90828000002","description":"Cows"}},
{"category":{"id":"4d9c5dfc8ddfd90828000023","description":"Dogs"}},
...
{"category":{"id":"4d9c5dfc8ddfd90828000024","description":"Mules"}}]
Consuming the service with:
public List<Category> getAnimalCategories(Cookie cookie) {
Client client = Client.create(new DefaultClientConfig());
ClientResponse response = client
.resource(Constants.BASE_URL)
.path(Constants.CATEGORIES_ANIMALS)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.cookie(cookie)
.get(ClientResponse.class);
return response.getEntity(new GenericType<List<Category>>(){});
}
Where Category.java is:
public class Category {
public String id;
public String description;
public Category() {
}
public Category(String id, String description) {
super();
this.id = id;
this.description = description;
}
The service uses cookie based authentication - that part works and I have other service calls working with the cookie.

Used the Jackson 1.9.6 lib to resolve the issue - see the 2nd line below:
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getClasses().add(JacksonJsonProvider.class);
Client client = Client.create(clientConfig);
return client
.resource(Constants.BASE_URL)
.path(Constants.CATEGORIES_ANIMALS)
.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.cookie(cookie)
.get(new GenericType<List<AnimalCategoryResponse>>(){});
Also needed to use a new response class:
public class AnimalCategoryResponse {
public Category[] category;
public AnimalCategoryReponse() { }
}

Related

How to parse a Java object which contains a list of a custom java POJO from REST Api call in component.ts file in angularJs

I am new to angular. I stuck to parse the response from the Java REST service to my angular UI. I can see the expected list came from REST API call in Network tab of inspector but not able to parse it to my respective component.ts file in angular. I am getting Response is undefined in console log of UI. Below are the details
REST API Response Object
public FinalResponse(int statusCode, String statusMessage, Object objects) {
super();
this.statusCode = statusCode;
this.statusMessage = statusMessage;
this.objects = objects; // This Object holds the Array List of Persons Object
}
In My componet.ts file, I used below code
export class Person {
constructor( public personId: number, public personName: string,){
}
}
export class FinalResponse {
constructor( public statusCode: number, public statusMessage: string,
public objects:any){
}
}
export class PersonListComponent implements OnInit {
persons: Person[]
message: string
finalResponse: FinalResponse
constructor(private personDataService: PersonDataService, private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
this.refreshPersonList();
}
refreshPersonList(){
this.personsDataService.retrieveAllPersons().subscribe(
response =>{
console.log("Backend service response"+response)
this.finalResponse =response;
this.persons = this.finalResponse.objects
console.log("Backend service response1 "+this.persons)
console.log("Backend service response1 "+this.finalResponse.statusCode)
console.log("Backend service response1 "+this.finalResponse.statusMessage)
console.log("Backend service response1 "+this.finalResponse.objects)
}
);
}
}
Here I can see the status code & status message perfectly but am not able to see the List of Person object. In the UI console log, I can see it is undefined.
Can anyone please help me with this?
Thanks in advance, any advice is highly appreciated.
you are assinging wrongly from the response first.data keyword is needed for accessing the response data.
try this: this.persons = this.finalResponse.data.objects
Here it is:
this.personsDataService.retrieveAllPersons().subscribe(
response =>{
console.log("Backend service response"+response)
this.finalResponse =response;
this.persons = this.finalResponse.data.objects
console.log("Backend service response1 "+this.persons)
console.log("Backend service response1 "+this.finalResponse.statusCode)
console.log("Backend service response1 "+this.finalResponse.statusMessage)
console.log("Backend service response1 "+this.finalResponse.objects)
}
);

Passing a BODY of a POST request to the server

I have built a Restful-API Java(SpringBoot) and created the needed requests.
The following request is a POST Request to add new Category.
I have tested the POST request by POSTMAN, and it working as expected.
I am building the client-side in ASP.NET 5.x.x.
Now the problem appear when I am calling the post request, it seems the API doesn't receive the data (#RequestBody category) that has been send from the client.
Here is a code simple of how I have created them
Server Side:
#ResponseStatus(HttpStatus.CREATED)
#PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public CategoryDTO create(#RequestBody CategoryDTO category) {
log.info("Adding new Category Name: " + category.getName());
return categoryMapper.asCategoryDTO(categoryService.save(categoryMapper.asCategory(category)));
}
Client Side
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Category category)
{
Category newCategory = new Category();
// Serialize the concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(category);
// Wrap the JSON inside a StringContent which then can be used by the HttpClient class
StringContent content = new StringContent(stringPayload);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.PostAsync("http://localhost:8080/category/add", content))
{
string apiResponse = await response.Content.ReadAsStringAsync();
newCategory = JsonConvert.DeserializeObject<Category>(apiResponse);
}
}
return RedirectToAction("Index");
}
I don't know what is wrong there, could anybody help!
EDIT--
Here is the request via postman
EDIT
I have created another POST request but as a RequestParam instead of RequestBody
#ResponseStatus(HttpStatus.CREATED)
#PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
public CategoryDTO addCategory(#RequestParam(name = "categoryName") String categoryName){
return categoryMapper.asCategoryDTO(categoryService.addCategory(categoryName));
}
and created in the client side the request as following
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Category category)
{
Category newCategory = new Category();
var parameters = new Dictionary<string, string> { { "categoryName", category.Name } };
var encodedContent = new FormUrlEncodedContent(parameters);
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.PostAsync("http://localhost:8080/category/add", encodedContent))
{
string apiResponse = await response.Content.ReadAsStringAsync();
newCategory = JsonConvert.DeserializeObject<Category>(apiResponse);
}
}
return RedirectToAction("Index");
}
And It's works fine!
So the problem is how to pass the data via the httpClient, which need to be of type RequestBody (the data in the body not in the header!) also as a application/json.
So how to pass the data?
I suppose that your spring boot application just blocks POST request because you didn't provide instruction how to handle requests. Try to disable csrf protection like it did here: https://stackoverflow.com/a/48935484/13314717
It might be a problem in the naming convention. Starting with capital letters in properties in C#, and starting with lowercase in Java.
If your class looks like this in C#
class Category {
int Id;
string Name;
...
}
And like this in Java
class Category {
int id;
string name;
...
}
It is not going to work so you have to match the property names. So make either both id or both Id.

how to send json object from REST client using javax.ws.rs.client.WebTarget

I have a POJO given below which I want to PUT to the server as JSON or XML.
This is what I have done
CLIENT:
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI());
public void putFriend(String uri , Friend friend)
{
System.out.println(friend.toString());
target = target.path(some_path).path(uri);
ClientResponse response = target.request(MediaType.APPLICATION_JSON).put(Entity.entity(friend,MediaType.APPLICATION_JSON),ClientResponse.class);
}
Examples I found on web were using WebResource.
I don't know how to do using WebTarget. What I have done is taken from some example found on SO but Entity.entity() gives error undefined method entity(friend, String).
POJO
#XmlRootElement
public class Friend{
private String friendURI;
private String event;
private String uri;
String getUri() {
return uri;
}
void setUri(String uri) {
this.uri = uri;
}
String getFriendURI() {
return friendURI;
}
void setFriendURI(String friendURI) {
this.friendURI = friendURI;
}
String getEvent() {
return event;
}
void setEvent(String event) {
this.event = event;
}
public String toString() {
return "Friend [friendURI=" + friendURI + ", uri=" + uri + ", event=" + event
+ "]";
}
Please guide how to do this.
Thanks
There are two different Jersey major versions, 1.x and 2.x, You seems to be trying to use a combination of both, which won't work. The 2.x versions don't have some classes as in 1.x and vice versa.
If you want to use Jersey 2.x, then you should be using Response, rather than ClientResponse
Response response = target.request().put(Entity.json(friend));
// .json == automatic 'application/json'
See Working with the Client API for 2.x
Also as mentioned in your previous post, the getters and setters should be public for the Friend class
Also see the WebTarget API
Basic breakdown.
Calling request() on WebTarget returns an Invocation.Buidler
Invocation.Builder builder = target.request();
Once we call put, we get back a Response
Response response = builder.put(Entity.json(friend));
To extract a known type from the response, we could use readEntity(Class type)
String responseString = response.readEntity(String.class);
response.close();

send XML string to web service in Jersery

I am new to web service in jersey. I have created a web service the code is below
#Path("/remotedb")
public class RemoteDb {
#GET
#Path("/save/{xmlData}")
#Produces(MediaType.TEXT_XML)
public String saveData(#PathParam("xmlData") String xml) {
return xml;
}
}
I have this code at client side
public class WebServiceClient {
public static void callWebService() {
String xml = "<data>" +
"<table><test_id>t4</test_id><dateprix>2013-06-06 22:50:40.252</dateprix><nomtest>NOMTEST</nomtest><prixtest>12.70</prixtest><webposted>N</webposted><posteddate>2013-06-06 21:51:42.252</posteddate></table>" +
"</data>";
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
System.out.println(service.path("restful").path("remotedb").path("save").path(xml).accept(MediaType.TEXT_XML).get(String.class));
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/WebServiceModule").build();
}
}
Now when i called the web service i got the following exception
Exception in thread "main" com.sun.jersey.api.client.UniformInterfaceException: GET http://localhost:8080/WebServiceModule/restful/remotedb/save/%3Cdata%3E%3Ctable%3E%3Ctest_id%3Et4%3C/test_id%3E%3Cdateprix%3E2013-06-06%2022:50:40.252%3C/dateprix%3E%3Cnomtest%3ENOMTEST%3C/nomtest%3E%3Cprixtest%3E12.70%3C/prixtest%3E%3Cwebposted%3EN%3C/webposted%3E%3Cposteddate%3E2013-06-06%2021:51:42.252%3C/posteddate%3E%3C/table%3E%3C/data%3E returned a response status of 404 Not Found
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:686)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
at com.main.WebServiceClient.callWebService(WebServiceClient.java:25)
at com.main.Test.main(Test.java:7)
Passing XML data in a path segment is very unorthodox and likely to raise all kind of issues. You should pass it as a query parameter, e.g. /WebServiceModule/restful/remotedb/save?xmlData=
%3Cdata...
#GET
#Path("/save")
#Produces(MediaType.TEXT_XML)
public String saveData(#QueryParam("xmlData") String xml) {
return xml;
}
}
or even better if it is a write operation as the name suggests then it should be a POST /WebServiceModule/restful/remotedb/save with the xmlData passed in the request body.
#POST
#Path("/save")
#Produces(MediaType.TEXT_XML)
public String saveData(String xml) {
return xml;
}
}
or even better yet, if you can map your xmlData to a POJO with JAXB's #XmlRootElement annotation, then you can get jersey to parse it for you:
#POST
#Path("/save")
#Consumes(MediaType.APPLICATION_XML)
public String saveData(YourXmlDataObject obj) {
return obj.getField();
}
}

How to access JSON request body of POST/PUT Request in Apache Camel/CXF REST webservice

I am trying to pass a JSON request body to a REST Webservice which is made using CXFRS in my Apache Camel application.
I want to access the request JSON passed in my Processor.
REST URL:
http://localhost:8181/mywebservice/Hello/name/{request_param}
Though i am posting a JSON in request body, still in my processor exchange.getIn().getBody() always return the {request_param} not the Request JSON.
My REST webservice is as follows:
#Path("/name/")
#Consumes({"application/json" ,"application/xml"})
public class HelloRest {
#POST
#Path("/{name}")
public TestPojo sayHi(#PathParam("name") String name) {
return new TestPojo(name);
}
}
Server part:
#POST
#Path("/")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String add(MappingUser newUser){
UserEntity userEntity = new UserEntity(newUser.getNickname(), newUser.getPassword());
boolean ret = myDB.addUser(userEntity);
//sends the return value (primitive type) as plain text over network
return String.valueOf(ret);
}
Client part:
public boolean addUser(User user){
WebResource resource = client.resource(url).path("/");
String response = resource
//type of response
.accept(MediaType.TEXT_PLAIN_TYPE)
//type of request
.type(MediaType.APPLICATION_JSON_TYPE)
//method
.post(String.class, user);
return Boolean.valueOf(response);
}

Categories

Resources