How to send JSON object to rest webservice? - java

I have a rest webservice at http://localhost:8600/rest/student/details which will update the details of student into database. I have to send the details as JSON format in method post.
The below is the method to generate that json message
private void createOrUpdateStudent(WebResource service) {
Gson gson = new Gson();
StudentImpl student= new StudentImpl ();
student.setId(6);
student.setName("Godwin");
student.setSex("Male");
StudentView view = new StudentView(student);
System.out.println("::::::"+service.path("/rest/student").path("/details").type("application/json").post(ClientResponse.class, gson.toJson(view)));
}
where studentView class is as below.
#XmlRootElement(name="clusterZipcode")
public class StudentView {
public Integer id;
public String name;
public String sex;
public StudentView() {}
public StudentView(StudentImpl student) {
this.id = student.getId();
this.name = student.getName();
this.sex = student.getSex();
}
while sending like above i am getting an error stating Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'Name' cannot be null
Is i am passing the json values correctly or if there is an alternate method to send the json message please suggest me.

I cannot see on your post where are you doing the call to the database. All I can see is that you are creating a Student and then, from there, creating a view (assuming this method is being called). The error you are getting is related to the fact that, at some point, you are calling the database to enter a new row in (probably) your student Model. If you have got hibernate, can you make sure that you are not calling .save or .update at any point between the call you get for the student and before you call setName?

Related

Why this HashMap not formatted correctly in Jersey/Tomcat?

I'm testing Jersey, I wanted to mack a mock endpoint that produces this JSON object
{
"Flight1" : 757,
"Flight2" : 107,
"Flight3" : 637,
}
so I've written written this resource:
#GET
#Path("myjson")
#Produces(MediaType.APPLICATION_JSON)
public String getMyJson(#QueryParam ("test1") String lat, #QueryParam("test2") String lng) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Flight 1", 765);
map.put("Flight 2", 657);
map.put("Flight 3", 908);
return map.toString();
}
But then I get this response when I call /myjson
{
Flight 1=765,
Flight 2=657,
Flight 3=908
}
Jersey already knows which element is a String and which element is an Integer, yet it format then as if they're all numbers.
Also the Json as it stands can not be formatted by the "pretty" formatter, and I believe this makes parsing it difficult by http clients.
So my question are:
Why is this happening?
How to avoid it and write simple mock JSON object for testing that is correctly formatted
You can add the Jaxb annotations to serialize and deserialize the response object directly without converting. For this you need to add the jersey's jaxb library so that when you jersey environment is getting booted, it can enable the auto conversion feature.
Example:
#Path("jaxbResource")
#Produces("application/xml")
#Consumes("application/xml")
public class UserResource {
#GET
public User[] getUserArray() {
List<User> userList = new ArrayList<User>();
userList.add(new User(1, "John"));
………
return userList.toArray(new User[userList.size()]);
}
}
#XmlRootElement
public class User {
private int id;
private String name;
public User() {}
public User(int id,String name) {
this.id = id;
this.name = name;
}
………
}
Hope this helps!!!
Why is this happening?
Because you are only making a toString of your HashMap.
Ex.
HashMap<String,String> stringStringHashMap = new HashMap<String, String>();
stringStringHashMap.put("a","b");
stringStringHashMap.put("b","b");
stringStringHashMap.put("c","b");
Will print {b=b, c=b, a=b}
How to avoid it and write simple mock JSON object for testing that is
correctly formatted
You can do this by using a lot of libraries(Gson, Jackson, JsonSimple,etc).
As this already answered what you want to make HashMap to Json
This has nothing to do with Jersey/Tomcat. For core Java programming, that is how best toString() method could process the map to String.
In order to do so you can convert to JSONObject using
String jon = JSONObject.valueToString(map);
System.out.println(jon);
OR even using the gson like
Gson gson = new Gson();
String json = gson.toJson(map);
System.out.println(json);

Using Gson to elegantly handle nested json objects?

I'm using Gson to parse responses from a server on Android. Each response has some useless (to me) data on it that complicates my Gson models. Here is the general hierarchy of json returned:
response: {
date: 1406253006807,
otherUselessData1: "This is some useless data",
otherUselessData2: "This is some useless data",
usefulJsonObject: { <---- This is really the object that I care about
}
}
Everything above or at the same level as usefulJsonObject I could really do without. The useless data is returned for every request, and the actual response is embedded beneath as the usefulJsonObject. This wouldn't be a big problem but it's really cluttering up my gson model objects.
For example:
Let's say I have 3 requests I can make: A, B, and C. For each response it seems I need to make a minimum of 3 custom classes.
public class ResponseA {
#SerializedName("response") ResponseObjectA responseObject;
public static class ResponseObjectA {
#SerializedName("usefulJsonObject") UsefulObjectA usefulObject;
}
public static class UsefulObjectA {
}
}
I've tried a few solutions, but I haven't found anything elegant that wouldn't add an extra step to my process. I'm using retrofit to do my http requests and it's really nice that it just returns the fully parsed gson object to me. I've thought of other solutions like having the useful object just be a JsonElement and then doing a 2nd gson call after the first comes back. Again, not ideal.
I just wanted to know if I was missing something. Surely I'm not the only one who's encountered something like this, and so I thought I'd ask how other people would handle something like this.
It is initialization Instance value, not NULL value. Check my example.
Address.java
public class Address {
public Address(){
}
}
Person.java
public class Person {
private String name;
private String nrc;
private Address address;
public Person(String name, String nrc, Address address) {
this.name = name;
this.nrc = nrc;
this.address = address;
}
}
The following Json string is equalvent to
Person person = new Person("Zaw Than Oo", "11111", null);
{
"name": "Zaw Than Oo",
"nrc": "11111"
}
The following Json string is equalvent to
Person person = new Person("Zaw Than Oo", "11111", new Address());
{
"name": "Zaw Than Oo",
"nrc": "11111",
"address": {} <-- here use less object for you.
}
Even if you don't create new Instance, Other lib/api(you used) may be create that instance by Reflection.
Short to the Point
{
...
"xxx": {} --> new instance without data/value
...
}
{
...
--> null value
...
}
I never found an elegant way dealing with just Gson. I tried several options with Generics, all of which didn't work or left something to be desired.
Since I'm using Retrofit, I decided to override the GsonConverter, and just filter out the unnecessary information from all my requests. It ends up not being as flexible, as in I can't use the same Retrofit network interface for calls to other servers, but I'm not really doing that, and it also has the down side of having 2 rounds of json parsing calls (meh). You could probably do this more efficiently, but this is working for me for now.
public class CustomGsonConverter extends GsonConverter {
private Gson mGson;
public CustomGsonConverter(Gson gson) {
super(gson);
this.mGson = gson;
}
public CustomGsonConverter(Gson gson, String encoding) {
super(gson, encoding);
this.mGson = gson;
}
#Override public Object fromBody(TypedInput body, Type type) throws ConversionException {
try {
CustomResponse customResponse = mGson.fromJson(new InputStreamReader(body.in()), CustomResponse.class);
return mGson.fromJson(customResponse.responseObject.data, type);
} catch (IOException e) {
throw new ConversionException(e);
}
}
public static class CustomResponse {
#SerializedName("rsp") ResponseObject responseObject;
public static class ResponseObject {
// #SerializedName("date") long date;
#SerializedName("data") JsonElement data;
}
}
}
Maybe there is a better way that I'm just not realizing.

Inherited class doesn't get stored in Windows Azure Mobile Service

I am in a process of creating a library for Windows Azure. So, here is a simple generic method to insert a new record:
public <TEntity extends SyncableBase> void addRemoteItem(TEntity itemToAdd) {
MobileServiceTable<TEntity> remoteTable = (MobileServiceTable<TEntity>)mobileServiceClient.getTable(itemToAdd.getClass());
Gson gson = new Gson();
String json = gson.toJson(itemToAdd);
remoteTable.insert(itemToAdd, new TableOperationCallback<TEntity>() {
public void onCompleted(TEntity entity, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
Log.e("SuccessMe", "Success");
// Insert succeeded
}
else {
Log.e("SuccessMe", "Nah "+ exception.getMessage());
// Insert failed
}
}
});
}
Now, here is my SyncableBase class:
public class SyncableBase {
#SerializedName("Bingo")
private int localId;
//#SerializedName("id")
private String remoteId;
private boolean isDeleted;
}
And my ToDoItem class:
public class ToDoItem extends SyncableBase {
private String name;
}
Now, the problem is: This fails with Error processing request. But if I don't extend ToDoItem from SyncableBase and move all those members directly to the former, everything works just fine. As can be seen, I tried serializing my Java object just before calling inset. The serialized json is exactly the same in both the cases. What am I doing wrong?
After days of debugging, I have come up with a potential problem and it's definite solution. This holds valid for the Android Azure SDK valid at the time of writing this. A couple of notes:
For seamless transactions, the id member must be present in the inherited class and not the super class. While validating the object, Azure SDK uses reflection and tries to find a filed with name (or serialized name) equal to id or Id. Somehow, the member isn't found if it is present in super class and we get error.
GSON (the thing which serializes Java object to JSON) is configured inside SDK so that it serializes even the null members. So, when there are no columns in WAMS table (fresh table) and try to insert an item with null fields, the error is thrown. The filed must hold a value so that the type of corresponding column to be generated can be determined. A new field with null value will give you an error.
Here's an example of an item being put in a fresh table.
{
"id": "Awesome unique id",
"name": Beautiful Wallpaper",
"description": null
}
Here, the WAMS would know that it has to generate a column called description; however, it wouldn't know the type of this column. Hence, first object must always have non-null values.
In my particular case, both the problems are there. Taking care of these things solved them.

Convert an object to a JSON string with thrift json serialization

I'm new to the thrift. I need to convert my data object to a JSON string with Thrift JSON serialization.
I tried in this way.
TSerializer serializer = new TSerializer(new TSimpleJSONProtocol.Factory());
String json = serializer.toString(object_name);
In here is an error, that object_name should be in TBase. How can I resolve this ?
In here is an error, that object_name should be in TBase.
Next time, please post the exact error message (use copy+paste), this makes it easier for all of us.
How can I resolve this?
Whatever you want to serialize with Thrift, must be an descendant of Thrift's TBase class. You achieve this by writing some Thrift IDL and save it as a file (e.g. MyDataStructs.thrift):
struct Employee {
1: string name
2: string surname
3: i32 age
}
Next, you pass that file to the Thrift compiler and tell him to generate some C# code from it:
thrift -gen csharp MyDataStructs.thrift
This gives you a class derived from TBase:
public partial class Employee : TBase
{
private string _name;
private string _surname;
private int _age;
// properties
public string Name {... }
public string Surname { ... }
public int Age { ... }
// some details omitted
public void Read (TProtocol iprot)
{
// generated code for Read() method
}
public void Write(TProtocol oprot) {
// generated code for Write() method
}
public override string ToString() {
// generated code for ToString() method
}
}
This is what Thrift expects.
If below is what your are doing then it should work. Check if you are doing this. Employee is a demo call here, you have to use your actual class.
Employee object_name= new Employee();
object_name.setAge(27);
object_name.setName("Test");
TSerializer serializer = new TSerializer(new TSimpleJSONProtocol.Factory());
String json = serializer.toString(object_name);

JAXB : How to manipuulate the Data during Unmarshalling process

I am using jaxb for the Unmarshalling Process
This is my Request
<kiran acct = "1234567" />
package com;
#XmlRootElement(name = "kiran")
#XmlAccessorType(XmlAccessType.FIELD)
public class CustAcct {
#XmlAttribute
private String acct;
public CustAcct() {
super();
}
public String getAcct() {
System.out.println("The New Getter Method of Account is called");
return acct;
}
public void setAcct(String s) {
System.out.println("The New Setter Method of Account is called");
acct = s;
}
}
This is the way Jersey (Restful Framework ) automatically binds the data with JAXB
public class HelloService {
#POST
#Produces("application/text")
public String sayPlainTextHello(CustAcct custdata) {
System.out.println("The New Account is " + custdata.getAcct());
return "Hi";
}
}
Here my question is that , why the Setter Method setAcct is not getting called in this case ??
I mean why the Line "The New Setter Method of Account is called" isn't being printed , and where as the Line inside the getMethod is geting called (The New Getter Method of Account is called)
Basically I want to Manupulate Data to an Attribute which is sent in the Request XML .
is there any call back method by which i can control the way Data is being Set ??
Thanks in advance .
why the Setter Method setAcct is not getting called in this case ??
Because you set the access type to field: #XmlAccessorType(XmlAccessType.FIELD). Change it to #XmlAccessorType(XmlAccessType.PROPERTY)
XmlAccessType javadoc.
is there any call back method by which i can control the way Data is being Set ??
Yes. You have complete control on the marshall/unmarshall process when you use adapters.

Categories