Monday, 25 January 2016

Three approachs to solve JSON recursive dependency (circular dependency) Stackoverflow

Using Jackson to serialize my JPA entities with many-to-many relationship into JSON, I got a wrong JSON response and the application entered in an infinite loop giving as output an infinite recursion Stackoverflow error.

To solve the problem, there are general two ways according to the Jackson documentation.

Approach 1
Before Jackson 2.0, handling of cyclic object graphs was limited to specific case of parent/child(bi-directional) references. Using @JsonManagedReference and @JsonBackReference

Add the @JsonManagedReference in the forward part of the relationship which you want to serialize, and add in the back part of the relationship which will not be serialized. See the following example that Material and Supplier is @ManyToMany relationship.

@Entity
public class Material{
    ...
    @JsonManagedReference 
    private List<Supplier> costSuppliers = new ArrayList<>();
    ...
}
   
@Entity
public class Supplier{
    ...
    @JsonBackReference
    private List<Material> costMaterials = new ArrayList<>();
    ....
}
If we serialize a Material instance to JSON, we will get an Array containing Supplier instances, but the drawback of this approach is that, when we serialize a Supplier instance to JSON, we will not get the Material array instance.

Approach 2
Jackson 2 provides a new annotation @JsonIdentityInfo which is used for indicating that values of annotated type or property should be serializing so that instances either contain additional object identifier, or as a reference that consists of an object id that refers to a full serialization. For the last example will be someting like this:
@Entity
public class Material{
    ...
    private List<Supplier> costSuppliers = new ArrayList<>();
    ...
}
   
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Supplier{
    ...
    private List<Material> costMaterials = new ArrayList<>();
    ....
}

Thus the cyclic dependency and Stackoverflow issue could be solved. But the drawback is that, just as the Jackson documentation says:
"In practice this is done by serializing the first instance as full object and object identity, and other references to the object as reference values."
It means that, say, we serialized a Material object which has an Supplier array, however, only the first  element of the array is Supplier object, the rest elements in the array is not Supplier object but Supplier reference (general the id). This not what a want, cause generally I want to render the whole properties of the Supplier object, but I need to request the Supplier info again with its reference :(

Approach 3
Forget @JsonManagedReference, @JsonBackReference, and @JsonIdentityInfo, we just use the simple  @JsonIgnoreProperties, see below:

@Entity
public class Material{
    ...   
  @JsonIgnoreProperties("costMaterials")
    private List<Supplier> costSuppliers = new ArrayList<>();
    ...
}
   
@Entity
public class Supplier{
    ...
  @JsonIgnoreProperties("costSuppliers")
    private List<Material> costMaterials = new ArrayList<>();
    ....
}

Simple annotation and simple use, NO infinite recursive Stackoverflow and get all the "Object" information in the serialized JSON :)


Tuesday, 12 January 2016

REST API for create-form and update-form resource

Generally, when comes to create a resource using REST, the URI is something looks like:
POST /orders
so how to represent a create and edit forms urls?

According to RFC 6861, we can use create-form and edit-form links to discover the url, say:
{
    ...
    "_links" : {
        "self" : {
            "href" : "/orders/1"
        },
        "createform" : {
            "rel" : "create-form",
            "href" : "/orders/createform"
        },
        "editform" : {
            "rel" : "edit-form",
            "href" : "/orders/1/editform"
        }
}
create-form and edit-form rel have well defined behavior described in IANA Link Registry

In one of my project based on Spring and AngularJS, the create form and edit form share the same template. When the user clicks "New" button returns create-form, it is a same template when user clicks "Edit" button.

In the Angular router configuration file, /orders/:id will redirected to the DETAIL page, which is a form used for creating and editing an order.

Say request GET /orders/123 will get the order information whose id is equals to 123, and these information will be rendered in the DETAIL page.

If the metadata of the create-form resource the same to domain resource, in my view, the URIs for create form and edit form can be simplified to one URI as /orders/createform OR /orders/editform, OR even /orders/:id in my case. So how to distinguish the form is used for creating or editing if I use /orders/:id in my project?

At first, I adopt the RFC 6861 and create a new URL /orders/createform to show the DETAIL page for creating an order, it means that I have to add a new controller to process the added endpoint. However, the URI structure of /orders/createform and /orders/:id is the same, so I modified the current method processing /orders/:id by changing the URI of /orders/createform to /orders/0 to response to the user with the intuition to create an order. SO in:
/orders/:id, if :id equals to 0, it means create a new order, otherwise, it means edit an existing order.
(OR you can use something like /orders/-1 to indicate creating option, for an id > 0)

After filling in the form and clicking the SAVE button, which will be:
PUT /order/:id
in the backend method, if id = 0 will create a new order and returned 201 Created , and if id>0 will update the order.

So the create and update option is processed in one method, without seperating as two methods, say POST /orders for creating and UPDATE /orders/:id for updating, cause PUT can also be used for create a resource and POST can also be used for updating a resource.
======================================================
The fundamental difference between the POST and PUT methods is
   highlighted by the different intent for the enclosed representation.
   The target resource in a POST request is intended to handle the
   enclosed representation according to the resource's own semantics,
   whereas the enclosed representation in a PUT request is defined as
   replacing the state of the target resource.  Hence, the intent of PUT
   is idempotent and visible to intermediaries, even though the exact
   effect is only known by the origin server.

   Proper interpretation of a PUT request presumes that the user agent
   knows which target resource is desired.  A service that selects a
   proper URI on behalf of the client, after receiving a state-changing
   request, SHOULD be implemented using the POST method rather than PUT.
   If the origin server will not make the requested PUT state change to
   the target resource and instead wishes to have it applied to a
   different resource, such as when the resource has been moved to a
   different URI, then the origin server MUST send an appropriate 3xx
   (Redirection) response; the user agent MAY then make its own decision
   regarding whether or not to redirect the request.

   A PUT request applied to the target resource can have side effects on
   other resources.  For example, an article might have a URI for
   identifying "the current version" (a resource) that is separate from
   the URIs identifying each particular version (different resources
that at one point shared the same state as the current version
   resource).  A successful PUT request on "the current version" URI
   might therefore create a new version resource in addition to changing
   the state of the target resource, and might also cause links to be
   added between the related resources.

   An origin server that allows PUT on a given target resource MUST send
   a 400 (Bad Request) response to a PUT request that contains a
   Content-Range header field (Section 4.2 of [RFC7233]), since the
   payload is likely to be partial content that has been mistakenly PUT
   as a full representation.  Partial content updates are possible by
   targeting a separately identified resource with state that overlaps a
   portion of the larger resource, or by using a different method that
   has been specifically defined for partial updates (for example, the
   PATCH method defined in [RFC5789]).

   Responses to the PUT method are not cacheable.  If a successful PUT
   request passes through a cache that has one or more stored responses
   for the effective request URI, those stored responses will be
   invalidated (see Section 4.4 of [RFC7234]).
=========================================================

What is your solution of URI designing for create-form and edit-form resource?