Entity Serialization

Hi all,

I have a generic service that serves data to an external mobile interface, via the REST-API.

My problem is that I return quit a heavy entity with several related instances, and when the platform serializes the object into a Map, I get Lazy initialization exception because the the object has not been fully retrieved with the items populated according to the view specified upon retrieval.

Is there any way I can fully preload the object before serializing in order to avoid that exception?

Many thanks for your insights.

Regards,

Carlos.

found a workaround. What I finally do is to not specify any view on retrieval, which I presume by default applies a “_base” view. Then after retrieving the object I make calls to the related instances via their getter methods to automatically retrieve the related instances before closing the transaction and returning the object.

Hope this helps anyone. However a more elegant solution would be greatly appreciated.

Thanks,

Carlos.

1 Like

Why didn’t you create a special named view for entity extraction?

Also, did you use EntitySerializationAPI to serialize entities?

Hi Andrey,

thanks for the answer. I have tried, not creating a specific view, but specifying a different one, and get the same error at the very exact point in code. I omitted an info that might be relevant, the error is raised inside a method annotated as _MetaProperty and _Transient ( _ = @, can’t use @ then the forum platform believes I am referencing other users and max number is two).

Can I somehow ask the EntitySerialization routine not to take into account @MetaProperties? Or can I annotate the property in such a way so that the property is not attempted to be serialized?

Thanks for your attention.

Regards,

Carlos.

Hi,

In the EntitySerializationAPI you can see the following method: String toJson(Entity entity, View view, EntitySerializationOption... options);

Please have a look at the EntitySerializationOption enum, maybe you will find what you need.

Hi Andrey thanks,

but the point is that I am not calling it directly… I return a standardentity from a rest-api service call, so the json transformation is done in the background. I do that for the rest of entitities and works fine. I have even tried to analyze down what is the lazy initialized property that is triggering the error and load it through a view, but it is not working either.

The only option I see is to remove the MetaProperty, but I need it there for other purposes (table columns for example).

Any ideas?

Regards,

Carlos.

Hi,

Spring JSON converter knows nothing about views, meta properties, unfetched attributes, etc. Therefore, if you have a method similar to this:

@GetMapping
public List<MyCubaEntity> getEntitiesList() {...}

Then you may want to change its signature to use EntitySerializationAPI or use separate DTO objects that do not extend entities.

Hi Andrey,

thanks for your answer. I am not an expert, have programmed in Java for many years, but don’t know this framework in depth. Could you please extend a bit your answer about changing the method’s signature to use EntitySerializationAPI?

EntitySerializationAPI is an interface, hence any implementation needs to be done at Entity level. StandardEntity seems not to implement it in anyway, so I presume another object takes care of the serialization. Do you mean I should implement on my own the interface inside the affected Entity?

That involves implementing a bunch of methods. Isn’t there an annotation or similar that I can add to the MetaProperty method, and skip that property from being serialized?

Regards,

Carlos.

Hi,

DataManager is an interface too, but you can inject it into a controller :slight_smile: Just inject EntitySerializationAPI as a service and use it.
Here is an example from the pet clinic application that does not serialize meta-properties:

@RestController
@RequestMapping("/api")
public class VisitRestController {

    @Inject
    private VisitService visitService;

    @Inject
    private EntitySerializationAPI entitySerializationAPI;

    @GetMapping(value = "consumables/used", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    public String getUsedConsumables() {
        return entitySerializationAPI.toJson(visitService.getUsedConsumables(), null, EntitySerializationOption.DO_NOT_SERIALIZE_RO_NON_PERSISTENT_PROPERTIES);
    }

}

Hi Andrey,

thanks for the answer. I know that, but thanks anyway for clarifying. I had already considered using EntitySerializationAPI in the service attending rest-api calls from the very moment I realized it was a component.

However, what I like of the current approach is that for other entities my service returns a plain StandardEntity and in the background the platform accomplishes the entity serialization and transfers it over being the whole thing very intuitive. In this approach I must serialize the entity in advance and return a String, which will do the work, but at the same time will be incongruent with the rest of service calls, because some how there’s no way prevent the serialization component from traversing @MetaProperty’s.

Do you think mine is a very unconventional approach? it balances scalability, maneuver capacity and minimizes network traffic.

Regards,

Carlos.

You can use one of methods: EntityStates.isLoaded() or isLoadedWithView() inside of your MetaProperty method to avoid unfetched attribute exception when corresponding property is not loaded.
Example:

@Entity(name = "playground_Card")
public class Card extends StandardEntity {

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "DECK_ID")
    protected Deck deck;

//...
    @MetaProperty
    public String getDeckName() {
        EntityStates entityStates = AppBeans.get(EntityStates.NAME);
        if (!entityStates.isLoaded(this, "deck")) {
            return null;
        }
        if (deck == null || !entityStates.isLoadedWithView(deck, "deck-view")) {
            return null;
        }

        return deck.getName();
    }


}

Very cool Alex.

That looks exactly to a solution to my problem!

Thanks to all of you for this enriching discussion!

Best regards,

Carlos.

1 Like

Confirmed! Both solutions work. However will adopt Alex’s solution then that enables to keep returning the entities as plain entity objects instead of previously serializing the object. Thanks Andrey for your contributions.

Best regards,

Carlos.