Spring MVC and json serialization - json

I am developing web application with spring mvc and Data sent to client in json format.
I want to have some views of same model object thus i can return only needed data ,not more.Jackson library #JsonIgnore , #JsonIgnoreProperties not suit this .Jackson library have also #JsonView and #JsonFilter annotations but they didnt help too.How can handle this problem.For example ,i will need possibleTarget list in some pages of UI and sometimes dont need.This is the same question but answer not help me
#Entity
public class Warrant implements Serializable {
#Column
String name;
#JsonIgnore
#ManyToOne
private User owner;
#Column
private String value;
#OneToMany(mappedBy = "warrant", targetEntity = com.endersys.lims.model.Target.class)
private List<Target> possibleTargets;
.....
}

You're mixing application layers. Don't send entities from your persistence layer to the view. Use Transfer Objects, that way you can easily control what you show the world.
You might want to use a framework like Dozer to automate data transfer between layers.

Related

Fetch related entities as Base Type

I'm currently trying to setup a database – using Java only. Given this simple class that might appear in the average social network app:
#Entity
class User {
#Id
private String email;
private String name;
private String otherInfo;
#ManyToMany
private List<User> contacts;
}
When the user logs in, he should receive the basic information and the list of contacts with their basic info, but not their contacts. To reduce the amount of boiler-plate code, I want to use a standard solution like Gson. However, even with lazy fetch the whole user is loaded on gson.toJson(user).
Therefore I thought of extracting the basic infos into a base class BasicUser and changing the contacts to List<BasicUser>. Now I only need to somehow circumwent the discriminator column when I fetch the contacts – of course they are all saved as complete users on the server. Unfortunately, I don't know how to archieve that. Any ideas?
If you need to get only part of the entity you can use projections. In your case it can be, for example, like this:
public interface BaseUser {
String getEmail();
String getName();
String getOtherInfo();
}
public interface UserRepo extends JpaRepository <User, String> {
List<BaseUser> findAllBy();
}
Using Jackson for serialization, the problem can be solved without writing custom serialization code. BasicUser contains the getters of the attributes, I want to serialize:
public interface BasicUser {
String getEmail();
String getFirstName();
String getLastName();
}
With a single annotation the contacts attribute is interpreted as a list of BasicUsers:
#Entity
public class User implements BasicUser {
#Id
private String email;
private String firstName;
private String lastName;
#ManyToMany
#JsonSerialize(contentAs = BasicUser.class)
private List<User> contacts = new ArrayList<>();
// ... implemented getters
}
You shouldn't have to modify your domain model just to accomodate a serialization library.
If you only want certain fields of a collection to be exposed to JSON, you could use Jackson with #JsonView (see here: How to serialize using #Jsonview with nested objects) not sure if Gson provides a similar feature as I have never used it extensively.

Pattern to map JPA Objects to DTO for Conversion to JSON

I have a somewhat philosophical question relating to mapping JPA Objects to JSON Strings. Of course there is no necessity for the source object to be a persistent object - it is just that that is my situation.
I have a collection of objects that are managed by Eclipse Link. I need to turn some of these objects into JSON Strings, however the mapping is not one-to-one. I am convinced that the conversion should be loosely coupled so as to isolate the JSON objects from changes in the underlying entities.
I am planning to have the JPA entity as such:
#Entity
#Table(name = "AbnormalFlags")
public class AbnormalFlag implements java.io.Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "Code", unique = false, nullable = false)
private String code;
#Column(name = "Description", unique = false, nullable = false)
private String description;
// Getters and setters
}
and the equivalent object to be converted to JSON
public class AbnormalFlagDTO implements java.io.Serializable {
private String code;
private String description;
private Boolean disabled;
// Getters and setters
}
Is there an elegant pattern or methodology I can use to facilitate this process for several types of objects.
Thanks in anticipation
My answer: no, and also you should generally extend DTOs with care (when reusing existing DTOs). But you could use a Map<String, Object> as a DTO (if you do not use the same DTO to read the data back). Besides you could create an APT (annotation processor tool) that generates the code for DTOs from your entities and then you simply modify them.
This is a perfect use case for Blaze-Persistence Entity Views as you will most probably also want to keep an eye on the performance of the query used for fetching the data.
I created the library to allow easy mapping between JPA models and custom interface defined models. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
A mapping for your model could look as simple as the following
#EntityView(AbnormalFlag.class)
interface AbnormalFlagDTO extends Serializable {
String getCode();
String getDescription();
Boolean getDisabled();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
AbnormalFlagDTO dto = entityViewManager.find(entityManager, AbnormalFlagDTO.class, id);
The serialization of the entity view to JSON will work as expected. If you also want to deserialize objects, you will have to construct the object first and also add setters to the interface.

RestyGWT JSON mapping with private fieldVisibility

I am currently prototyping replacing the GWT-RPC based backend of our application to a REST based API using RestyGWT on the frontend and Spring MVC on the backend.
My issue occurs during the Java <-> JSON type conversions that both frameworks attempt to resolve automatically. All of our data objects use private fields, and many of the fields do not provide java bean style setter methods. By default, neither framework would inspect the private fields of a class and so this conversion fails.
For Spring MVC it was simple enough to fix this by adding an annotation to the data objects:
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
For RestyGWT I have not found a suitable fix. The only available workaround I have found is to use default access to all fields and constructors which is far from ideal. Does anybody have a solution that will allow RestyGWT to inspect the private fields of a Java object?
Try using #JsonProperty and #JsonCreator (do not remeber if both are necessary) on your fields.
public abstract class Parent
{
#JsonCreator
public Parent(#JsonProperty("name") String name)
{
this.name = name;
}
public String getName()
{
return name;
}
private String name;
}

Serializing JPA entities to JSON using Jackson

Question regarding combination of Jackson/JPA
If there are about 20 entities in current application and I have add Jackson dependency in POM, does it mean all entities are by default ready to convert to JSON object? I saw a sample project seems only class annotated as #JsonIgnored is skipped by JSON. If so, then how can this happen, what is behind such mechanism? how JACKSON handle those entities which don't have any Jackson annotation, by default ignored or not? I've been looking for resources online but not much luck.
If only one of the 20 entities need to be mapped to JSON object, does it mean I have to add #JsonIgnore to all other 19 entities? If not, how Jackson differentiate with entity to work on?
Thanks.
Jackson and JPA don't have anything to do with each other. Jackson is a JSON parsing library and JPA is a persistence framework. Jackson can serialize almost any object - the only requirement being that the object have some kind of recognizable properties (Javabean type properties, or bare fields annotated with #JsonProperty. There is an additional requirement for deserialization, that the target type have a default (no-arg) constructor. So, for example, this is an object that Jackson can serialize:
// Class with a single Javabean property, "name"
class Person {
private String name;
public String getName() { return name ; }
public String setName(String name) { this.name = name ; }
}
And here is another:
// Class with a single field annotated with #JsonProperty
class Account {
#JsonProperty("accountNumber")
private String accountNumber;
}
And here is yet another:
#Entity
public class User {
#Id
private Long id;
#Basic
private String userName;
#Basic
#JsonIgnore
private String password;
#Basic
#JsonIgnore
private Address address;
// Constructors, getters, setters
}
The last example shows a JPA entity class - as far as Jackson is concerned it can be serialized just like any other type. But, take note of its fields: when this object is serialized into JSON two of the fields will not be included - 'password' and 'address'. This is because they have been annotated with #JsonIgnore. The #JsonIgnore annotation allows a developer to say 'Hey, its ok to serialize this object, but when you do so don't include these fields in the output'. This exclusion only occurs for the fields of this object, so for example, if you included an Address field in another class, but did not mark the field as ignorable, it would be serialized.
To prevent serialization of a type in all cases, regardless of context, use the #JsonIgnoreType annotation. When used on a type it basically means 'I dont care where this type is used, never serialize it'.
No, you don't need to add #JsonIgnore on every class and if you had tried you would have gotten a compile error, since you can't put it there. Jackson will only work on objects you give to it, it's no magic.
The Jackson documentation is easily found online, such at its project page on github or on the codehaus website.

Spring MVC, REST, Jackson, Dojo dojox.data.jsonRestStore, how to make dojo-style references?

Pretty simple question, hard to find an answer:
I want to Serialize in JSON my POJO JPA entities with references being Dojo-like to use it with dojox.data.JsonRestStore.
The server part is made with Spring MVC and HttpConverters to make it a RESTfull web-app. I'm using JacksonJson to convert JPA entities to JSON.
As a lot of people have, I do have problems with multiple references. #JsonBackReference and #JsonManagedReference do not do the trick!
Considering this basic example:
public class A {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable=false)
private String field;
#OneToMany(mappedBy = "b")
private List<B> bs;
}
public class B {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
private A a;
}
With the basic Jackson Json converter you obtain something like this (considering you have put the #JsonBackReference and #JsonManagedReference):
{ id:1, fieldB:"bbbbb", a: { id:1, fieldA: "aaaaaa" }}
In a concrete application, having the list of bs from the A objects is pointless in most cases. But having knowing what kind of A object is in the B.a field is important (at least to me).
Now, the problem lies in the references which are copied and you can end up having some serious big JSON with not much data in it.
The Dojo Framework provides a reference standard explained in here : http://www.sitepen.com/blog/2008/06/17/json-referencing-in-dojo/ and
http://dojotoolkit.org/reference-guide/dojox/data/JsonRestStore.html.
So what I'm searching is a way to define this as the following:
{ id:1, fieldB:"bbbbb", a: { $ref: "getA/1"}}
First problem: Jackson obviously can't know what url you will use for the Reference.
To resolve that problem I made very simple interface like this:
public interface EntityWithId {
public Long getId();
public void setId(Long id);
}
This interface in then implemented by all my entities and I made this very very simple JsonSerializer:
public class EntityIdSerializer extends JsonSerializer<EntityWithId> {
#Override
public void serialize(EntityWithId value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("$ref", "db/" + value.getClass().getSimpleName() + "/" + value.getId().toString());
jgen.writeEndObject();
}
}
With those two I got the desired JSON, adding #JsonSerialize(using = EntityIdSerializer.class) to the #ManyToOne fields.
Is there no more standard approach? The Dojo dojox.data.JsonRestStore sounds really promising as you can combine it with lots of Dijits widgets, but is it really a nice thing to do and try? Won't my REST app be to much Dojo-restrictive?
Thanks for your answers!
Dojo approach sounds like it requires dealing with a complete logical tree, to be able to use location-based references. This will not work well with Jackson, which supports fully incremental data-binding, i.e. only subset of the logical being available at the point where data is read or written.
So Jackson does not support it by default; nor is that approach considered much of a standard in general (AFAIK). At least I havent seen it supported by Java libraries.