Serializing Entity and Entity collection as a field in POJO returned from REST API Methods

Hi Guys
I have a problem and it seems to be at least a weird bug.
I have a REST service method which is returning a POJO.
A simplified version:


class WEBAPIResult<E> implements Serializable {
    private E result;
    private boolean success;
    
    public void setSuccess(boolean success){
        this.success = success;
    }
    
    public void setResult(E result){
        this.result = result;
    }
}

The webservice method is the following:


WEBAPIResult<User> getCurrentUserData{
    User userResult;
    WEBAPIResult<User> webResult = new WEBAPIResult<>();
    ..............
    // the trasanction frame and other codefragments is omitted.
    // em is EntityManager
    userResult = em.find(User.class, userID, "webView");
    webResult.setResult(userResult);
    ........
    return webResult;
}

So that code is failing and the log says that there is null session and LAZY attributes in Pojo which cannot fetched. And I need to fetch them.
The problem is that the em.Find is already fetch all attributes which are in view. Even when I simply return the Entity and not the POJO it will be returned just fine.
The wierd stuff is the following:
IF i do before the return:


Gson.toJSon(userResult); // the result is discarded!

THEN the error is gone, but i’ll get a a full entity returned with all the fields not respecting any security and view configuration.
How can I avoid this bug?
BTW I using 6.5.3
Best Regards!

Hi Sándor,

Thank you for reporting the problem. In fact, partially loaded entities inside POJO results are simply not supported. I’ve created a YouTrack issue, so we’ll try to fix it in the future.

As a workaround, you can use a non-persistent entity instead of POJO. For example:

@MetaClass(name = "sample$MyResultEntity")
public class MyResultEntity extends AbstractNotPersistentEntity {
    private static final long serialVersionUID = 8112201060237849411L;

    @MetaProperty
    protected User user;

    @MetaProperty
    protected Boolean success;

    public void setUser(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public Boolean getSuccess() {
        return success;
    }
}

A method returning such result can look like this:

public MyResultEntity getMyResultEntity() {
    MyResultEntity result = new MyResultEntity();
    try (Transaction tx = persistence.createTransaction()) {
        
        View view = viewRepository.getView(User.class, "new-view");
        view.setLoadPartialEntities(true);

        User user = persistence.getEntityManager().find(User.class, uss.currentOrSubstitutedUserId(), view);
        result.setUser(user);
        result.setSuccess(true);
        tx.commit();
    }
    return result;
}

Also, keep in mind that when used on the middle tier, views do not affect local attributes of entities, i.e. local attributes are always loaded. That’s why I specify view.setLoadPartialEntities(true) in the code above.

1 Like

:ticket: See the following issue in our bug tracker:

https://youtrack.cuba-platform.com/issue/PL-9256