JaVers - how to add extra fields to reference entity in JSON - java

I was trying to add JaVers library to my current project. And I wondered Is there any ways to add to reference entity fields some field which will be shown instead of Id when I fetch changes?
For example snapshot of User class:
{
"owner": {
"entity": "Owner",
"cdoId": 1
},
"username": "TMP",...
}
and if I change Owner reference and fetch for changes, I will get:
ReferenceChange{ 'owner' changed from 'Owner/1' to 'Owner/2' }
What I want is some thing like:
{
"owner": {
"entity": "Owner",
"cdoId": 1
"cdoName": "OWN"
},
"username": "TMP",...
and changes like this:
ReferenceChange{ 'owner' changed from 'OWN' to 'FOO' }
Is there any way to achieve this? I`m using Javers 3.11.3

You can't add more fields to a Reference. In JaVers, a Reference is just a global identifier of an entity. Try to describe the problem you have, maybe there is a better solution than changing javers-core model.

Related

Is there any way to work with flexible JSON in java? (Spring Boot API)

So I need to create an API with Spring Boot to manage different JSON. My problem is that these JSON can and will change in the future their structure, saying something like this:
Today's structure:
{
"name" : "example",
"surname" : "example"
}
Possible future structure:
{
"name" : "example",
"surname" : "example",
"data_array" : [
{
"path": "example"
}
]
}
So, my question is, is there any way to manipulate this kind of JSONs (the "flexible" ones), I don't know if this is possible.
Thank you in advance
Edit.
I don't know if I'm explaining this well enough, right now, to work with those JSONs I need to parse them into an object that I've already created with those fields as parameters. I would like to know if there is a way to not limit those JSONs with a defined object in java.

How to handle self-reference in Spring Data JPA with Spring Boot 2?

I have a Spring Boot 2 application in which I have the following User entity:
#Data
... JPA and other annotations
class User {
... many fields including Integer id
#ManyToOne(fetch = FetchType.LAZY)
public User createBy;
#ManyToOne(fetch = FetchType.LAZY)
public User updateBy;
}
Now, the main problem I am facing right now is the self-reference of User (from User) and this either is causing StackOverflow Exceptions or InvalidDefinitionException depending on the certain annotations I am using on User. This issue is very common and several solutions are discussed over the internet which are:
1. Annotate both fields with #JsonBackReference
Annotating with #JsonBackReference omits the updateBy and createBy fields altogether, meaning I am not getting them when desired in my API responses.
2. Annotate class with #JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") or None.class or IntSequenceGenerator.class or UUIDGenerator.class
This approach works fine, until the serializer finds the same user object somewhere down the json and instead of putting it up there again, it puts a reference of that object based on the class selected above. e.g.
[
{"id": 1, ..., "createBy": {"id": 2, ...},
2 // <- Let's ignore how user 1 is created by user 2 and notice that instead of a user object, I get an integer ID reference.
]
This means, the client parsing this data will often there to be an object and not a number, causing parsing errors.
3. Implementing a custom serializer (or extending an existing one)
Now, I am really unsure if this is the right way to go about achieving my goals (mentioned below). But if this is the right approach, how would I go about handling this self-reference?
GOALS:
Serialize the data so that, at least certain fields in the child object (user) are passed back, preventing further recursive calls.
{
"id": 1, "name": "old user", .. many other fields .., "createBy": {id: 2, "name": "2nd user"}
}
When the client sends a user object as request body, the application needs only the id of the child entity and not the whole object, as below:
{
"name": "new user", ...., "createBy": {id: 1}
}
I know that self-referencing is integral to ORMs and there are a lot of use cases for self-referencing. But how do professional developers/applications handle this issue, especially in Spring Framework? If a custom serializer is the only way to go, how do I make it function appropriately?
Also, is it advisable to exclude these fields (createBy and updateBy) from EqualsAndHashCode and ToString methods?

For hibernate entity class, can i pick property from instance variable class to set a column

I want to persist JSON objects in Db with hibernate and spring boot.
I have sample JSON with me with which i want to generate POJO and Hibernate Entity class. I will ignore some fields using #transient property. But i want some field's property as a column in by db.
eg:
{
"CompanyName": "Books by Bessie",
"DisplayName": "Books by Bessie",
"PrintOnCheckName": "Books by Bessie",
"Active": true,
"PrimaryPhone": {
"FreeFormNumber": "(650) 555-7745"
},
}
I want to persist this JSON . For PrimaryPhone I want to fetch FreeFormNumber and put it in db under the column name PrimaryPhone . Of course I am trying to avoid writing separate pojo and entity class and a mapper.
PS: Is there a tool to generate hibernate entity classes from JSON?

GSON how to exclude a property at second level of serialization

I building a web api with Jersey and JaxRs and I am searching a way to prevent GSON from serializing à circular reference. I have found a lot of answers saying that in the case of a "parent > child" relation, we could add the transient keyword to the parent property so it won't be serialized. However, my situation is not this kind of relation and I haven't found how to achieve what I need.
I have a situation where one User have a list of many other Users (their friends):
public class User {
public int id;
public String name;
public List<User> friends;
}
Now, let's suppose that user1 is friend with user2 so they are both added in each others friend list :
user1.friends.add(user2);
user2.friends.add(user1);
This causes a circular reference when serializing (and eventually a StackOverflowException). Indeed, user1's friends contain user2, and user2 friends contains user1, who contains user2.... and so on !
However I cannot just make transient the friends property of the User class, because I need those friends names and ids. I would rather like the friend property to be excluded at the second level of serialization (by serializing the name and id of each friends, but not the friends' friends).
Here's an exemple of a serialized JSON I would need :
[
{
"id":1,
"name":"user1"
"friends": [
{
"id":2,
"name": "user2"
}
]
},
{
"id":2,
"name":"user2"
"friends": [
{
"id":1,
"name": "user1"
}
]
}
]
How could I achieve this ?
Thanks a lot in advance !

Jackson - Lazy List initialization error when deserializing a ManyToOne relation

I have 2 simple classes:
Cat
CatStore
Cat has nothing particular, and CatStore has a List<Cat>, the relation mapped as:
In Cat class:
#ManyToOne
private CatStore catstore;
In CatStore:
#OneToMany(mappedBy="catstore", fetch=FetchType.EAGER)
private List<Cat> cats;
The relation seems to work OK, as Jackson can generate me a correct JSON when I run
String json = mapper.writeValueAsString(catStore);
But if I try to deserialize the JSON I just generated, with this line:
CatStore c2 = mapper.readValue(json, CatStore.class);
I get a JsonProcessingException saying
failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: fr.truc.java.cleanspringbootMVC.model.CatStore["cats"]
The deserialization actually works if there is no cats in the CatStore like with the following JSON:
{
"id":123,
"cats":["org.hibernate.collection.internal.PersistentBag",[]],
"name":"NO cats"
}
But this one triggers the error:
{
"id": 121,
"cats": ["org.hibernate.collection.internal.PersistentBag", [
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 118,
"name": "luc",
"nbPattes": 4
}],
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 119,
"name": "andré",
"nbPattes": 4
}],
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 120,
"name": "cheval",
"nbPattes": 4
}]
]],
"name": "Cat en kit"
}
I really do not know why a lazy loading exception would trigger here as the data is contained in the JSON string.
Is this related to the PersistentBag?
Is this because I do not use a custom serializer/deserializer?
If you use JPA, all your entities will be enhanced by bytecode to allow lazy loading and such. They are not really suitable for serialization, except by hibernate, who is aware of it. But Jackson doesn't know about it, so it will screw up the enhanced bytecode.
It's also not a good idea to use the same class for JPA mapping and for Jackson mapping. The JPA classes have fields that map to columns and such, whereas the classes for Jackson map to a javascript schema. If you use them in the same class, you can never change your database schema without affecting your JSON schema and possible breaking backwards compatibility with whoever is using the JSON.
It's better to have separate classes (DTO's) to use for Jackson, and do some mapping between them. Or use mapstruct to generate a mapper automatically.
The error seems to be related to mapper.enableDefaultTyping();
When enabled, the typing of each class is outputted in the JSON. (which I wanted)
For some reason, it causes the above error on a #ManyToOne
When disabled, PersistentBag no longer appears in my serialized JSON, and the deserializing works...

Categories

Resources