Sending objects as JSON vs Objects of defined class - java

I have multiple web services running on Tomcat servers with Java backend. When one of the services queries for something from one of the other services, it returns the payload as a JSON string. Now i need to parse this and get the info that i need. I use the JSON library provided by json.org
What I wanted to ask is that, will be faster (wrt to processing) if i have a template class (i class with just attributes and their get/setters) as a library class in both the services and then pass the payload as an object of that class, and then accept it as by type casting to that object.
WebResource localWebResource = localClient.resource(url);
ClientResponse localClientResponse = (ClientResponse) localWebResource
.accept(new String[] { "application/json" }).get(ClientResponse.class);
//Scenario 1 - accept it as String
String jsonString = (String) localClientResponse.getEntity(String.class);
MyObject myObj = parseJson(jsonString);
//Scenario 2 - accept it as object of 'MyObject'
MyObject myObj = (MyObject) localClientResponse.getEntity(MyObject.class);
Using scenario 2, will it be any faster compared to scenario 1. Converting to 'MyObject' in scenario 2, will the compiler take the same amount of time as for manual parsing like in scenario 1?.
Note that the payload is transferred over the network. Will either of this approach have any effect on the network transfer time?

In theory, both methods would take the same amount of time. They both have to transform the JSON string into an object graph. However, my experience is that getting the object from the framework is much faster than trying to do it myself. (using Jersey 1.17, no Jackson, Jaxb/Json conversion)

Related

Can we create an object in Java with out class like in js or python with random key and values

Like in other programing languages - python or JS, when we create a rest api specifically post for the request body we attract some JSON Object
EX:
url: .../employee (Post)
request body: {option: {filter: "suman"}}
In Python or JS we can just do request_body.option.filter and get the data
How can I achieve the same with Java ?
Do I need need to create a class for the reqeust_body and for option and make an instance object request_body
This depends with other framework elements you use in your application. For example if you bring Spring into the scene, you would be looking to use in built features like dependency injection and support for hibernate (JPA implementation), which depends on the concept of entities that are POJOs with extra annotations. So yes you would need to define entity classes and DTOs for those.
I was able to parse the request body with JSONObject like below
#PostMapping("/customers")
public List<Customer> getCustomerById(#RequestBody Map<String, Object> req) {
// {option: {filter: "alf"}}
JSONObject json = new JSONObject(req);
System.out.println(json.toString(4));
System.out.println(json.getJSONObject("option").get("filter"));
-----------------------
-----------------------
-----------------------
}
Output

Java Serialization with JPA and Rest APIs

As we know Serialization in java ,to quote from a blog here is used
to convert the state of an object into a byte stream, which can be
persisted into disk/file or sent over the network to any other running
Java virtual machine.
REST API CASE :
Now considering the second case , to send over a network to another running jvm , if we consider an example of a Rest API , i.e "host:port/path/resource".
Usually I use Spring's #RequestMapping to return the resource model pojo class as ResponseEntity. I do not implement Serializable interface in the model class and all works fine , I get the response of the API in json.
ModelX.java
public class ModelX {
private int x = 2 ;
private String xs = "stringx";
// getters and setters
}
Controller method :
#RequestMapping(value = "/test",method=RequestMethod.POST)
public ResponseEntity<ModelX> getTestModel(#RequestBody ModelX mox){
ModelX mx = new ModelX();
mx.setX(mox.getX());
mx.setXs(mox.getXs());
return new ResponseEntity<ModelX>(mx, HttpStatus.OK) ;
}
Is it because Spring framework makes it Serializable under the hood with those RestAPI annotations ? If not , how without making it serializable we are able to send over a network .
Persistence Case :
Just for more thought , Even in the case of persisting the Objects in database , we use #Entity from JPA , now I tested if the instance of any #Entity annotated class IS-A Serializable or not . and it gives false.
#Entity
class Car {
int id ;
String name ;
//getters and setters
}
testMethod -
Car c = new Car();
System.out.println(c instanceof Serializable);
O/p - false
So even when we try to save this object's state in a database , ORM also does some kind of Serialization under the hood ?
Serialization is a general notion:
In computer science, in the context of data storage, serialization (or serialisation) is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).
Serializable is used for a single specific implementation of serialization, which happens to be built into JVM and called "Java serialization". But conversion to JSON, or to whatever protocol database uses for communication are also serialization; they just have nothing to do with Serializable.
are there any specific scenarios or applications (maybe if you are aware of )where sending bytestream is more beneficial
For one, binary formats are smaller than JSON and can be read/written faster. And they can still be cross-platform. But for this you generally would use a different binary format than Java serialization: e.g. Protocol Buffers or Thrift (or many others).
so if the app that sends the data goes down , data will still be available for the other jvm . (won't happen in case of API)
This works perfectly well with JSON as well (or PB or Thrift as above).

Good practices in REST / Java

I'm currently trying to acquire skills in REST, and specifically in "good" Rest, hypermedia and all the good practices that comes with it.
In order to do so, I was asked to develop a prototype REST server containing data of my choice and implementing everything I'll have to use in a real project coming after that.
So I made a server using Spring boot and Jackson for json handling.
My data architecture is close to this : I have a collection of LaunchVehicle (I like space =D) like Ariane V, Falcon 9, etc. I can retrieve the JSON object flawlessly
{ "name":"Ariane V","country":"Europe","firstFlight":null,"GTO_Payload":1.0,"LEO_Payload":2.3,"weight":136.0 }
The thing is, I'd like to add a "space agency" field which would be an object containing some Strings and Floats, inside my LaunchVehicle. However, when the client retrieve a LaunchVehicle, I don't want it to retrieve the full SpaceAgency object, just the name for exemple. From here, he would be able to follow the link to the space agency via an hypermedia link included in the response it would have received.
How can I do this ? Right now I'm only able to send to the client my full LaunchVehicle object with the SpaceAgency object and all his fields. Is there any annotations doing what I want ? Thanks ;)
public class LaunchVehicle {
private String name;
private String country;
private Date firstFlight;
private Map<String, Float> characteristics;
private SpaceAgency spaceAgency;
#JsonCreator
constructor...
#JsonProperty(required=false)
getters and setters...
}
Thanks a lot, don't hesitate if I'm not precise or understandable enough.
Try #JsonIgnoreProperties annotation at the class level. That should provide you the feature that you want.
Otherwise, you could always use some kind of DTO object to create your response model, and there just have the fields that are going to be used at the API layer.
I would rather prefer to use an appropiate DTO/ApiModel for your API layer than having a full domain object with JSON annotations in it.
If your SpaceAgency class only defines the properties that you need to deserialize, Jackson will only deserialize those. It will forget the unmapped properties.
Try jax-ws-rs!
It's a standart REST implementation in Java.
Oracle docs
Very good tutorial by Mkyong
You can use the Gson API for this
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(spaceAgency).getAsJsonObject();
String agencyName = obj.get("agencyName").getAsString();
I think you should reference the space agency as a hyperlink.
So the JSON will look like:
{ "name":"Ariane V",
"country":"Europe",
< other fields omitted >
"_links": {
"agency": { "href": "agencies/ESA" },
< other links omitted >
}
}
To achieve this you need to specify the link in your data transfer object. Don't make this a reference to an actual object of that type -- to do so would mean populating that object, even when the client doesn't ask for it.
How you achieve this depends on what technology you're using. In Jersey it's
public class LaunchVehicle {
...
#InjectLink(resource=AgencyResource.class)
URI agencyLink;
...
}
https://jersey.java.net/documentation/latest/declarative-linking.html
Linking like this is what "real" REST is all about. However note that plenty of real-world solutions claim to be doing REST without actually using hyperlinks. A more hacky solution would be to have a String agencyId field in your JSON, which could be put into a URL template to get agency details.

How can I get values from #GET using #QueryParam("list") final List<MyDTO> listDTO

I have an service that should receive a List<Object>, in my case, FaturamentoDTO... ex:
#GET
#Path(value="/teste")
#Produces(MediaType.APPLICATION_JSON)
public List<FaturamentoDTO> teste(#QueryParam("list") final List<FaturamentoDTO> listFatsDTO) {
for (FaturamentoDTO f : listFatsDTO) {
// do my stuff...
}
return listFatsDTO;
}
So my question is, how can I send and receive the values.
JAX-RS specification says:
The following types are supported:
1 Primitive Types
2 Types that have a constructor that accepts a single String argument.
3 Types that have a static method named valueOf with a single String argument.
4 List, Set, or SortedSet where T satisfies 2 or 3 above.
But even with the constructor I can't get the values.
If you are sending anything other than simple strings I would recommend using a POST with an appropriate request body. However it must be possible with a GET.
How does your client send the request?
Your client should send a request corresponding to:
GET http://example.com/services/teste?list=item1&list=item2&list=item3
Query parameters don't have any specific support for complex data structures, so you are going to need to implement that yourself. I was facing something similar, and ended up using JSON representations of the data as the query parameter values. For example (note that the JSON should be URL encoded, but I left that out to make it readable)
http://service?item={"foo" : "value1", "bar" : "value2"}&item={"foo" : "value3", "bar" : "value4"}
You could then write a ParamConverter<T> to unmarshal the JSON into your FaturamentoDTO. I am using JAXB/MOXy, but this could be done using your JSON handling library of choice.

JSON Polymorphism

I have a List of javascript objects on my client side, which are a list of "events" that a user has executed. When the user is ready, I want to send this to the server. The order of events is important, so preserving the list order is necessary.
What I would like to do is to have a JSON library (don't mind which one) to bind the JSON to some Event objects in my Java code, where Event is an abstract class, and I have 3 concrete classes that all extend Event (lets say EventA, EventB and EventC).
Ideal scenario would be something like
List<Event> events = jsonlibrary.deserialise(jsonString);
which may contain a list of items such as
[eventA, eventC, eventA, eventA, eventB]
Is this possible, or do I have to inspect the JSON tree manually, and deserialise the individual elements of the json array?
JSON objects are just key/value pairs and contain no type information. That means identifying the type of a JSON object automatically isn't possible. You have to implement some logic on the server-side to find out what kind of event you are dealing with.
I would suggest to use a factory method which takes a json string, parses it to find out what kind of Event it is, builds an Event object of the correct subclass and returns it.
You could use Genson library http://code.google.com/p/genson/.
It can deserialize to concrete types if the json was produced using Genson. Otherwise you only need to add something like [{"#class":"my.java.class", "the rest of the properties"}...]
// an example
abstract class Event {
String id;
}
class Click extends Event {
double x, y;
}
// you can define aliases instead of plain class name with package (its a bit nicer and more secure)
Genson genson = new Genson.Builder().setWithClassMetadata(true).addAlias("click",
Click.class).create();
String json = "[{\"#class\":\"click\", \"id\":\"here\", \"x\":1,\"y\":2}]";
// deserialize to an unknown type with a cast warning
List<Event> events = genson.deserialize(json, List.class);
// or better define to which generic type
GenericType<List<Event>> eventListType = new GenericType<List<Event>>() {};
events = genson.deserialize(json, eventListType);
EDIT
here is the wiki example http://code.google.com/p/genson/wiki/GettingStarted#Interface/Abstract_classes_support
Why not using jackson json library ?
It is a full Object/JSON Mapper with data binding functionnality.
It is fast, small footprint, documented, overused, and many others things you will enjoy!
I began a library that implements the desired fonctionality (for json and xml) if the json is encoded by the same library :
https://github.com/giraudsa/serialisation
to use it,
MyObject myObject = new SpecialisedObject();
String json = JsonMarshaller.ToJson(myObject);
MyObject myClonedObject = JsonUnMarshaller(json);

Categories

Resources