vaadin / collaboration-engine

The simplest way to build real-time collaboration into web apps
https://vaadin.com/collaboration
Other
3 stars 1 forks source link

Spring enhanced beans cannot be used as topic data #65

Open heruan opened 2 years ago

heruan commented 2 years ago

Describe the bug Spring enhanced beans fails serialization when added to topic data structures.

To Reproduce Steps to reproduce the behavior:

  1. Expose a bean
  2. Add it to a topic (e.g. collaboration list)

Expected behavior The bean is added to the topic.

Versions

Additional context The following code throws the exception below.

public class SomeView extends VerticalLayout {

    public SomeView(@Autowired UserInfo localUser) {
        CollborationEngine.getInstance().openTopicConnection(this, localUser, "topic", conn -> {
            conn.getNamedList("users").add(localUser);
        });
    }
}
com.vaadin.collaborationengine.JsonConversionException: Failed to encode the object to JSON node. Make sure the value contains a supported type.
    at com.vaadin.collaborationengine.JsonUtil.toJsonNode(JsonUtil.java:121) ~[collaboration-engine-5.1.0.beta2.jar:na]
    at com.vaadin.collaborationengine.JsonUtil.createInsertChange(JsonUtil.java:214) ~[collaboration-engine-5.1.0.beta2.jar:na]
    at com.vaadin.collaborationengine.TopicConnection$CollaborationListImplementation.insert(TopicConnection.java:301) ~[collaboration-engine-5.1.0.beta2.jar:na]
    at com.vaadin.collaborationengine.CollaborationList.insertLast(CollaborationList.java:170) ~[collaboration-engine-5.1.0.beta2.jar:na]
...
Caused by: java.lang.IllegalArgumentException: No serializer found for class org.springframework.context.expression.StandardBeanExpressionResolver and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.vaadin.collaborationengine.UserInfo$$EnhancerBySpringCGLIB$$719a1e84["targetSource"]->org.springframework.aop.target.SimpleBeanTargetSource["beanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["beanExpressionResolver"])
    at com.fasterxml.jackson.databind.ObjectMapper.valueToTree(ObjectMapper.java:3394) ~[jackson-databind-2.13.2.1.jar:2.13.2.1]
    at com.vaadin.collaborationengine.JsonUtil.toJsonNode(JsonUtil.java:119) ~[collaboration-engine-5.1.0.beta2.jar:na]
    ... 70 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.context.expression.StandardBeanExpressionResolver and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.vaadin.collaborationengine.UserInfo$$EnhancerBySpringCGLIB$$719a1e84["targetSource"]->org.springframework.aop.target.SimpleBeanTargetSource["beanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["beanExpressionResolver"])
heruan commented 2 years ago

Spring beans cannot be serialized so they can't be used as topic data. One workaround is to use a Spring bean that provides the data you need in topic, e.g.

public class SomeView extends VerticalLayout {

    public SomeView(@Autowired UserInfoProvider localUserProvider) {
        UserInfo localUser = localUserProvider.get();
        CollaborationEngine.getInstance().openTopicConnection(this, localUser, "topic", conn -> {
            conn.getNamedList("users").add(localUser);
        });
    }
}

The exception message might provide more context and possibly suggest this workaround.