Serializing a Part of an Object Graph

I have a problem with Java serialization. I have a graph of objects and you want to configure where to stop when I serialize the root object from client to server.

Let me make this a little concrete, understandable, by providing a sample script. I have classes like


Company Employee (abstract)
Manager expands staff
Secretary expands staff
Analyst expands project staff

Here are the ratios:
Company (1) --- (p) Employee
Manager (1) --- (p) Project
Analyst (1) --- (p) Project

Imagine, I am on the client side, and I want to create a new company, assign it to 10 employees (new or some existing) and send this new company to the server. What I expect in this scenario is to serialize the company and all the bounding employees on the server side, because I will save the relationships in the database. There is still no problem, because the Java serialization engine by default serializes the entire graph of an object, excluding a field that is static or temporary.

My goal is the following scenario. Imagine, I downloaded the company and its 1000 employees from the server to the client side. Now I only want to rename the company name (or another field that directly belongs to the company) and update this record. This time I want to send only the company’s object to the server side, and not the entire list of employees (I just update the name, the employees are irrelevant in this case). My goal also includes the configuration of the utterance, the transfer of the company AND employees, not Project-Relations, you should stay there.

Do you know any possibility of achieving this in a general way without implementing writeObject, readObject for each Entity-Object? What will be your suggestions?

I would really appreciate your answers. I am open to any ideas and ready to answer your questions if something is unclear.

+4
source share
3 answers

You can create another class (data transfer object) in which you have only the fields that you want to transfer.

Custom serialization method implements Externalizable

+1
source

I would say that the short answer to your question is no, such a diverse logic for serialization cannot be easily implemented without writing serialization yourself. However, an alternative could be to write several pairs of serializer / deserializer (XML, JSON, regardless of your favorite format, instead of the standard input of built-in serialization). and then run your objects through these pairs, sending some kind of meta-information preamble.

for example, following your scenarios above, you can have these pairs of serialization mechanisms (de)

  • (de) serializeCompany (Company c) - for information about the base company.
  • (de) serializeEmployee (Employee e) - for employee information
  • (de) serializeEmployee (Company c) - basic information of employees in the company.
  • (de) serializeRelationships (Company c) - for project relationships

For XML, each of them can generate a dom tree, and then you place them all in the root directory of the node containing the meta information, i.e.

 <Company describesEmployees="true" describeRelationships="false"> [Elements from (de)serializeCompany] [Elements from (de)serializeEmployee(Company c)] </Company> 

One of the potential “gains” with this approach is to make sure that you are deserializing in the correct order depending on your model (that is, make sure that you first deserialize the company, then the employees, and then the relationships). But this approach should provide you with the opportunity to write only the “actual” serialization once, and then you can create your own various transport models based on the compositions of these works.

0
source

You can use the swizzling object, where you send the stub object to your customer.

Pros

  • The same object graph is logically available on the client side without the overhead of serializing / deserializing unnecessary data.
  • Full / stubs can be replaced as needed without changing the client code.

against

  • The overhead when calling recipients, which lead to the dynamic loading of additional attributes by calling the server, is hidden from the client, which can be problematic if you do not control the client code; for example, an involuntary user can repeatedly make an expensive call in a narrow cycle.
  • If you decide to cache data locally on the client side, you need to make sure that it is synchronized with the server.

Example

 /** * Lightweight company stub that only serializes the company name. * The collection of employees is fetched on-demand and cached locally. * The service responsible for returning employees must be "installed" * client-side when the object is first deserialized. */ public class CompanyStub implements Company, Serializable { private final String name; private transient Set<Employee> employees; private Service service; public Service getService() { return service; } public void setService(Service service) { this.service = service; } public String getName() { return name; } public Set<? extends Employee> getEmployees() { if (employees == null) { // Employees not loaded so load them now. this.employees = server.getEmployeesForCompany(name); } return employees; } } 
0
source

Source: https://habr.com/ru/post/1305537/


All Articles