How deserialize, if lack of some date? - java

We have two systems: external and internal, which are sharing information in JSON format (GSON library).
Information from an external system comes in internal and processed here.
Everything was very good, coming from an external system data in JSON format in the internal system data deserialize and processed. For example:
come string:
{UserLogInEvent:{userName:'Name', time:'00.00.00'}}
this string deserialize in object of this class:
UserLogInEvent implement Event {
private String userName;
private Date time;
public UserLogInEvent (String userName, Date time)
{
this.userName = userName;
this.time = time;
}
private UserLogInEvent()
{
this.userName = null;
this.time = null;
}
public String getUserName()
{
return this.userName;
}
public Date time()
{
return this.time;
}
}
or other example:
{UserModifyFile: {userName:'Name',fileName: 'index.txt' time:'00.00.00'}}
UserModifyEvent implement Event {
private String userName;
private String fileName;
private Date time;
public UserLogInEvent (String userName, String fileName, Date time)
{
this.userName = userName;
this.fileName = fileName;
this.time = time;
}
private UserLogInEvent()
{
this.userName = null;
this.fileName = null;
this.time = null;
}
public String getUserName()
{
return this.userName;
}
public Date time()
{
return this.time;
}
public String getFileName ()
{
return this.fileName;
}
}
The algorithm is very simple:
string -> deserialization -> object events created.
But .. further problems began. These problems I can not decide ..
Added new events.
Information that comes with an external system does not contain all necessary data about the event, for example:
{UpdateProductInfoEvent: {userName:'name', time: '00.00.00', product: {id:'123', name: '???', type: '???', cost:'???'}}}
As you can see, the line does not contain all the data ... just deserialized not give a desired result ...
To do this, I still need to call a method that will receive information about a product by its Id.
The algorithm is as follows:
JSON string -> processing line -> product information from ID -> object creation * Event.
The following example:
{ModifyProductCatalogEvent:{userName: 'Name', time: '00.00.00', catalog:{id:'321', catalogType:'???', catalogName: '????'}}}
Again I not have all info about catalog...
So, I ask for help, how do I properly construct an algorithm to create objects in case of lack of data?

You can write your own serialization and deserialization methods by overwriting:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
which enables you to handle those cases yourself. You can still use the default methods by using out.defaultWriteObject/in.defaultReadObject to only have to handle the cases where data may be missing (or if you have default values for invalid objects, read all fields with the normal methods and then overwrite the invalid fields with the correct data).

The first question that I would ask is if the code is throwing exceptions? If not, then inspect the object and set the properties/objects to a defaulted state since there is not way to retrieve the data if they did not send it. Or in the constructor of the objects, add initialization code so that the deserializer will have an initialized object to work with.

Related

Java JSON library supporting getting and setting deep values without schema?

I'm calling an API of some service and they return a gigantic JSON with literally around a hundred of fields and a dozen of nested objects. However, I don't need all of them. In fact, when doing GET or POST I really need from 3 to 7 fields. I very much want to avoid having this complex model in my application just to serialize/deserialize a couple of fields.
Essentially, I wanted to achieve:
Deserialize their gigantic nested JSON string to my flat POJO.
Work in my code with my flat POJO projection.
Serialize my flat POJO to their complex nested schema.
My solution so far was to rely on JsonPath:
Create a custom annotation for fields in my flat POJO, like:
#JsonPathField("$.very.deeply.nested.field.value")
private String theOnlyFieldIneed;
Create a util method that uses reflection to produce a map of <fieldName, JsonPath.readValue()> which I give to Jackson objectMapper to produce my POJO. So deserialization to a flat POJO part works.
For serialization, however, things are worse, because JsonPath throws an exception if the path doesn't exist in the String. Like,
// This will throw an exception:
DocumentContext document = JsonPath.using(jsonPathConfig).parse("{}");
document.set("$.not.even.deepest", value);
To workaround that, I added kinda original schema as a string to feed to JsonParh.parse(Pojo.Prototype) but this is ugly, tedious and error-prone.
Basically, I'm looking for Immutable.JS kind of behaviour: Collection.SetIn
You could use Kson (https://github.com/kantega/kson) which has a pretty straighforward support for extracting values from nested structures.
public class DecodeExample {
public static class Address {
final String street;
final String zip;
public Address(String street, String zip) {
this.street = street;
this.zip = zip;
}
}
static class User {
final String name;
final Address address;
User(String name, Address address) {
this.name = name;
this.address = address;
}
}
public static void main(String[] args) {
final JsonDecoder<Address> adressDecoder =
obj(
field("street", stringDecoder),
field("zip", stringDecoder.ensure(z -> z.length() < 5)), //You can add constraints right here in the converter
Address::new
);
JsonResult<JsonValue> json =
JsonParser.parse(jsonString);
Address address =
json.field("model").field("leader").field("address").decode(adressDecoder).orThrow(RuntimeException::new);
System.out.println(address);
JsonResult<Address> userAddress =
json.field("model").field("users").index(0).field("address").decode(adressDecoder);
System.out.println(userAddress);
}
}

Is it possible to build an object like this at runtime in java?

As the title says....
I want to build a POJO with four field variables and at certain runtime events create an instance of this POJO with access to possibly maybe two or three of the fields.
public class Category implements Serializable {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Lets say I create a new Category object but I only want to be able to have access to the name field during runtime. Is there a design pattern I can use to achieve this? I thought about the strategy pattern and looked at the builder but I am still confused if I can do this in java.
Basically the overall goal is to grab an object from a database and return it as a JSON response in jax rs. But sometimes I dont want a complete object returned but only lets say halve of the object to be accessible at during certain runtime events. My apologies if this seems like a dumb question but I know what I want to do but just don't know the best way.
I have the same problem with you, and my project was used springmvc,and the json tool is jackson.With the problem solved, I just use #JsonIgnore.For more details,just read jackson-how-to-prevent-field-serialization
So someone correct me if I am wrong or see a better option than this...with alot of objects this can be alot of extra code for serialization and deserialization...Jackson Provisions is what I need. I can use the annotation #JsonView(DummyClass.class) on the field variable. I will accept this a the best answer in a day or two unless someone else posts a better response.
// View definitions:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
public class Bean {
// Name is public
#JsonView(Views.Public.class) String name;
// Address semi-public
#JsonView(Views.ExtendPublic.class) Address address;
// SSN only for internal usage
#JsonView(Views.Internal.class) SocialSecNumber ssn;
}
With such view definitions, serialization would be done like so:
// short-cut:
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
// or fully exploded:
objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
// (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
objectMapper.writeValue(out, beanInstance); // will use active view set via Config
// or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
This information was pulled from http://wiki.fasterxml.com/JacksonJsonViews
with jackson 2.3, I can do this with JAX-RS
public class Resource {
#JsonView(Views.Public.class)
#GET
#Produces(MediaType.APPLICATION_JSON )
public List<Object> getElements() {
...
return someResultList;
}
}

How to Process Versioned Objects in Event Handlers and Callbacks

My Question:
Is there a best known method for processing different versions of objects that have been deserialized in handlers or callbacks?
Some Background Info:
We are going to be using serialized objects as messages to communicate between various components in a software suite. These could be in JSON form or using something like protobufs. Anytime you start to serialize objects, either for long term storage or between different versions of an application, you have to be able to handle different versions of those objects (maybe using Annotations-Java or Attributes-C#).
I'm trying to avoid code like this:
onRecvMyMsg(MyMsg msg)
{
if (msg.version == 1.0)
// process it here
else if (msg.version < 1.5)
// process it here
else if (msg.version < 2.0)
// process part of it in the 1.5 handler and the other part here
else if // etc...
}
It seems like this would be a maintenance nightmare after many additions/enhancements/changes...
Surely, someone must have been solved this since this seems like a very common practice in software engineering. Any help or suggestions would be appreciated!
The problem with my original approach is that the solution is oriented towards the wrong direction. We are thinking that the processing entity, or consumer of the object, is required to know versions so it can properly handle the differences between them. What we could be thinking about, instead, is how we can get the object to express itself based on the version of the processor (or consumer).
If we use a serialization technology like Protocol Buffers, Apache Thrift, or Apache Avro we are half way there in obtaining what we want. Libraries like these handle versioning for us, in a sense. Generally speaking they behave like this:
if a field is received but not defined it is simply dropped
if a field is defined but not received, a flag indicates that it is
not present and an optional default value can be supplied
These libraries also support "required" fields; however, most people (including the authors) don't recommend using "required" fields on the protocol objects themselves because a "required" field will break comparability for all time, both ways (send and receive) if there is a "required" field not present. They suggest handling required fields on the processing side.
Since the libraries mentioned handle all of the work required to serialize and deserialize objects in a backward and forward compatible manner, all we really need to do is wrap those protocol objects into something else that can expose the data in the form that the consumer expects.
For example, here are 3 versions of the same message that can be processed.
ReviewCommentMsg // VERSION 1
{
string : username
string : comment
}
ReviewCommentMsg // VERSION 2 (added "isLiked")
{
string : username
string : comment
bool : isLiked
}
ReviewCommentMsg // VERSION 3 (added "location", removed "isLiked")
{
string : username
string : comment
string : location
}
The following demonstrates how we could incrementally update the client code to process those messages.
/*******************************************************************************
EXAMPLE OBJECT V1
*******************************************************************************/
class ReviewComment
{
private final String username;
private final String comment;
ReviewComment(ReviewCommentMessage msg)
{
// Throws exception if fields are not present.
requires(msg.hasUsername());
requires(msg.hasComment());
this.username = msg.getUsername();
this.comment = msg.getComment();
}
String getUsername() { return this.username; }
String getComment() { return this.comment; }
}
/*******************************************************************************
EXAMPLE PROCESSOR V1
*******************************************************************************/
public void processReviewComment(ReviewComment review)
{
// Simulate posting the review to the blog.
BlogPost.log(review.getUsername(), review.getComment());
}
/*******************************************************************************
EXAMPLE OBJECT V2
*******************************************************************************/
class ReviewComment
{
private final String username;
private final String comment;
private final Boolean isLiked;
ReviewComment(ReviewCommentMessage msg)
{
// Throws exception if fields are not present.
requires(msg.hasUsername());
requires(msg.hasComment());
this.username = msg.getUsername();
this.comment = msg.getComment();
if (msg.hasIsLiked())
{
this.isLiked = msg.getIsLiked();
}
}
String getUsername() { return this.username; }
String getComment() { return this.comment; }
// Use Java's built in "Optional" class to indicate that this field is optional.
Optional<Boolean> isLiked() { return Optional.of(this.isLiked); }
}
/*******************************************************************************
EXAMPLE PROCESSOR V2
*******************************************************************************/
public void processReviewComment(ReviewComment review)
{
// Simulate posting the review to the blog.
BlogPost.log(review.getUsername(), review.getComment());
Optional<Boolean> isLiked = review.isLiked();
if (isLiked.isPresent() && !isLiked.get())
{
// If the field is present AND is false, send an email telling us someone
// did not like the product.
Stats.sendEmailBadReview(review.getComment());
}
}
/*******************************************************************************
EXAMPLE OBJECT V3
*******************************************************************************/
class ReviewComment
{
private final String username;
private final String comment;
private final String location;
ReviewComment(ReviewCommentMessage msg)
{
// Throws exception if fields are not present.
requires(msg.hasUsername());
requires(msg.hasComment());
requires(msg.hasLocation());
this.username = msg.getUsername();
this.comment = msg.getComment();
this.location = msg.getLocation();
}
String getUsername() { return this.username; }
String getComment() { return this.comment; }
String getLocation() { return this.location; }
}
/*******************************************************************************
EXAMPLE PROCESSOR V3
*******************************************************************************/
public void processReviewComment(ReviewComment review)
{
// Simulate posting the review to the blog.
BlogPost.log(review.getUsername(), review.getComment());
// Simulate converting the location into geo coordinates.
GeoLocation geoLocation = GeoLocation.from(review.getLocation());
// Simulate posting the location to the blog.
BlogPost.log(review.getUsername(), geoLocation);
}
In this example:
PROCESSOR V1 can receive messages (V1, V2, and V3)
PROCESSOR V2 can receive messages (V1, V2, and V3)
PROCESSOR V3 can receive messages (V3)
This approach puts the compatibility concern in the message objects themselves and alleviates clients/processors from having a bunch of version checking.
Admittedly, you still have to perform some semantic checking; however, that seems far less cumbersome than building in version logic to every client.

java trouble making a correct interface

I want to make a class that can interact with a database, which has the following desired functionality:
It has a method to return all fields from the database, later can be changed such that it can also limit with it returns.
It has a method to insert a specific instance of this class.
It has a method to update a specific instance of this class.
I will show the code in a moment after further explanation.
Now I want to extract an interface, or rather an abstract class I think might be more appriopiate, to be sure that all classes/datafields follow the same 'interface', and to be able to use them as a supertype in Lists etc.
The data class, in this case Account.java, should represent a table in a database which stores {Username, Password}, I am omitting an explicite unique identifier for now, still not sure if I will make an additional ID field or use the uniqueness of the Username field.
It would be best if the abstract class itself would handle all the MySQL interaction 'mess'.
Account.java so far:
package testthing;
import java.util.Map;
/**
*
* #author Frank
*/
public class Account {
private final static String ALL_QUERY = "SELECT * FROM accounts";
private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";
private String username;
private String password;
public Account(final String username, final String password) {
this.username = username;
this.password= password;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public static Map<String, Account> getAll() {
//return a map using the ALL_QUERY string
}
public void insert() {
//insert this using INSERT_QUERY
}
public void update() {
//update this using UPDATE_QUERY
}
}
I know that I haven't been that clear I'm afraid, but I hope this is enough to help me get going.
Basically I want to always be able to use the followings methods when working with a TableObject, which Account would be a subset of:
Account.getAll();
new Account("test", "test").insert();
currentAccount.setPassword("newPassword"); currentAccount.update();
All the nasty SQL stuff should be hidden inside the proposed abstract class. The only thing you cannot escape in a TableObject class is the definition of the SQL queries.
Regards.
EDIT: In current example Account.getAll() returns a Map<String, Account>, but in reality the first generic argument should be the type of the key in the database. So if you would use an unique ID then it would need to return a Map<Integer, Account>. I hope this change makes it in time for people to read it.
Is it not more logical, to have the connection code and all the "nasty" stuff in the superclass, but simply have a more general method in the superclass, that is used by it's sub classes. For example:
public void executeUpdate(String query)
{
// Code to execute update.
}
public Map<String, Data> getData(String query)
{
// Code to get data.
return data;
}
This way, these methods are more general. It means that you can implement several classes that simply pass query data, rather than constantly having to update a superclass every single time you want to add new functionality.
Obviously I've just assumed a type Data here, but that might be something to look into. The aim here is to decouple your classes as much as possible. This means you can add as many new classes as you want, and they can use their supertype without hinderence.
This also means things like
Account.getAll();
is a little less complicated, because if you have getAll in your superclass, where is the reference that you want to get all accounts? If the code is actually in the Account class, you can customize the query, and send it off to the getData method to be executed.

Passing parameters made easy in java

public class Model {
public void updateEvent(String name, Date date,String start, String venue, String details,
String opportunity, String more, String end, String row) {
//do stuff here
}
public class Controller {
public void someMethod() {
if(button==view.saveButton) {
model.updateEvent(view.txtEventName.......);
} }
}
public class View {
public JTextField txtEventName;
//10 more consisting of textarea, datechooser, etc
}
How can I pass a bunch of parameters to for Controller to pass to Model to update its state. Well, if the View is acting as form, it will have lots of text fields, text area etc. for data entry. rather than dealing with them individually how can controller gain access to all of them easily to pass to model. I dont want to simply keep adding view.txtWhere.getText() which is long.
Create an "Event" class that has String name, Date date,String start, String venue, String details,
String opportunity, String more, String end, String row and use it instead ?

Categories