9 Replies Latest reply on Sep 24, 2010 7:35 AM by misqu23

    Another problem with serialization, ManyToMany and StackOverflow

    misqu23

      Hi

       

      During serialization I get StackOverflowError. My user entity holds references to the set of groups it belongs, and on the other hand group entity holds the set of the users which are belongs to it. During serialization of the user entity errai wants to serialize also groups, but when it serialize the group it starts to serialize the user and so on. In the result we get StackOverflowError. Below there is a simple test case with the corresponding User.class and Group.class implementation.

       

      First the exception :

      at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEnc
      
      java.lang.StackOverflowError
           at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
           at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
           at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
           at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
           at java.lang.Class.newInstance0(Class.java:355)
           at java.lang.Class.newInstance(Class.java:308)
           at org.mvel2.optimizers.OptimizerFactory.getAccessorCompiler(OptimizerFactory.java:78)
           at org.mvel2.optimizers.dynamic.DynamicOptimizer.<init>(DynamicOptimizer.java:33)
           at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
           at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
           at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
           at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
           at java.lang.Class.newInstance0(Class.java:355)
           at java.lang.Class.newInstance(Class.java:308)
           at org.mvel2.optimizers.OptimizerFactory.getDefaultAccessorCompiler(OptimizerFactory.java:69)
           at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:126)
           at org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:41)
           at org.mvel2.MVEL.executeExpression(MVEL.java:1039)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:118)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeCollection(JSONEncoder.java:153)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:54)
           at org.jboss.errai.bus.server.io.JSONEncoder.encodeObject(JSONEncoder.java:119)
           at org.jboss.errai.bus.server.io.JSONEncoder._encode(JSONEncoder.java:73)
      

       

      Test case :

       

           @Test
           public void testEncodeDecode() {
                
                User user = new User();
                user.setLogin("admin");
                user.setPassword("admin");
      
                
                Group group = new Group();
                group.setParent(null);
                group.setName("Test group");
                group.setDescription("Test group description");
                
                Set<User> users = new HashSet<User>(); 
                users.add(user);
                
                group.setUsers(users);
                group.setParent(null);
                group.setSuperGroup(true);
                
                Set<Group> groups = new HashSet<Group>(); 
                groups.add(group);
                
                user.setGroups(groups);
                
                JSONEncoder.encode(user);
                System.out.println(JSONEncoder.encode(user));
           }
      

       

      User.class and Group.class :

       

       

      import java.io.Serializable;
      import java.util.Set;
      
      import javax.persistence.CascadeType;
      import javax.persistence.Entity;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.JoinTable;
      import javax.persistence.ManyToMany;
      import javax.validation.Valid;
      import javax.validation.constraints.NotNull;
      
      import org.jboss.errai.bus.server.annotations.ExposeEntity;
      
      @Entity
      @ExposeEntity
      public class User implements Serializable {
      
           private static final long serialVersionUID = 5861196132584179497L;
      
           @Id
           private Long id;
           
           private boolean active = true; 
                
           private String login;
           
           private String password;
      
           @ManyToMany(cascade={CascadeType.REFRESH})
           @JoinTable(name="USERS_GROUPS",
                     joinColumns=@JoinColumn(name="USER_ID"),
                     inverseJoinColumns=@JoinColumn(name="GROUP_ID"))
           @NotNull
           @Valid
           private Set<Group> groups;
      
           public User() {
                super();
           }
      
           public Long getId() {
                return id;
           }
      
           public void setId(Long id) {
                this.id = id;
           }
      
           public boolean isActive() {
                return active;
           }
      
           public void setActive(boolean active) {
                this.active = active;
           }
      
           public String getLogin() {
                return login;
           }
      
           public void setLogin(String login) {
                this.login = login;
           }
      
           public String getPassword() {
                return password;
           }
      
           public void setPassword(String password) {
                this.password = password;
           }
      
           public Set<Group> getGroups() {
                return groups;
           }
      
           public void setGroups(Set<Group> groups) {
                this.groups = groups;
           }      
      }
      
      import java.io.Serializable;
      import java.util.Set;
      
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.ManyToMany;
      import javax.persistence.ManyToOne;
      import javax.persistence.OneToMany;
      
      import org.jboss.errai.bus.server.annotations.ExposeEntity;
      
      @Entity
      @ExposeEntity
      public class Group implements Serializable {
           
           private static final long serialVersionUID = 1723678191345674847L;
      
           @Id
           private Long id;
           
           private String name;
           
           private String description;
      
           @OneToMany(mappedBy="parent", fetch = FetchType.LAZY, 
                     cascade={CascadeType.REFRESH,CascadeType.REMOVE})
           private Set<Group> groups;
           
           @ManyToOne
           @JoinColumn(name="PARENT_ID", nullable=true)
           private Group parent;
      
           @ManyToMany(mappedBy="groups",fetch=FetchType.LAZY,
                     cascade={CascadeType.REFRESH})
           private Set<User> users;
           
           /**
            * Is super group?
            */
           @Column(name="SUPER_GROUP", nullable=false)
           private boolean superGroup = false;
           
           public Group() {
                super();
           }
      
           public Long getId() {
                return id;
           }
      
           public void setId(Long id) {
                this.id = id;
           }
      
           public String getName() {
                return name;
           }
      
           public void setName(String name) {
                this.name = name;
           }
      
           public String getDescription() {
                return description;
           }
      
           public void setDescription(String description) {
                this.description = description;
           }
      
           public Set<Group> getGroups() {
                return groups;
           }
      
           public void setGroups(Set<Group> groups) {
                this.groups = groups;
           }
      
           public Group getParent() {
                return parent;
           }
      
           public void setParent(Group parent) {
                this.parent = parent;
           }
      
           public Set<User> getUsers() {
                return users;
           }
      
           public void setUsers(Set<User> users) {
                this.users = users;
           }
      
           public boolean isSuperGroup() {
                return superGroup;
           }
      
           public void setSuperGroup(boolean superGroup) {
                this.superGroup = superGroup;
           }
      
      }
      

       

       

      Of course standard GWT RPC serialization was working fine with those classes. Is it possible to serialize those classes ?

       

      Thanks in advance.

      Marcin

        • 1. Re: Another problem with serialization, ManyToMany and StackOverflow
          cbrock

          Ouch, I'll look into this ASAP.

          • 2. Re: Another problem with serialization, ManyToMany and StackOverflow
            misqu23

            Thanks for the quick response.

             

            I'm looking forward for the solution.

            • 3. Re: Another problem with serialization, ManyToMany and StackOverflow
              cbrock

              The solution has been pushed.  However, as of Friday we have moved to GitHub.  You can find the fix here: http://github.com/errai/errai

               

              The fix was not an easy one. =)

              • 4. Re: Another problem with serialization, ManyToMany and StackOverflow
                misqu23

                Hi

                 

                I checked and it seems to work perfectly. Thanks for the quick response. I suspected that it will not be easy to fix it, but even that you have fix it very quick.

                Thanks once again.

                 

                Errai is now on GitHub can you post an url to the errai-weld sources on the GitHub, I couldn't find it.

                • 5. Re: Another problem with serialization, ManyToMany and StackOverflow
                  heiko.braun
                  • 6. Re: Another problem with serialization, ManyToMany and StackOverflow
                    misqu23

                    I have already found that repository.

                     

                    Unfortunately during building with -Pjboss6 switch I get following exception :

                     

                    [INFO] ------------------------------------------------------------------------
                    [INFO] Building Errai::CDI::Examples::Server
                    [INFO]    task-segment: [clean, install]
                    [INFO] ------------------------------------------------------------------------
                    [INFO] [clean:clean {execution: default-clean}]
                    [INFO] Deleting file set: /home/misiek/dev/errai/errai-cdi/examples/server/target (included: [**], excluded: [])
                    [INFO] [resources:resources {execution: default-resources}]
                    [INFO] Using 'UTF-8' encoding to copy filtered resources.
                    [INFO] Copying 2 resources
                    [INFO] Copying 1 resource
                    Downloading: https://repository.jboss.org/nexus/content/groups/public//org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.pom
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:pom:1.0.1-FINAL' in repository jboss-public-repository-group (https://repository.jboss.org/nexus/content/groups/public/)
                    Downloading: https://repository.jboss.org/nexus/content/repositories/deprecated//org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.pom
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:pom:1.0.1-FINAL' in repository jboss-deprecated (https://repository.jboss.org/nexus/content/repositories/deprecated/)
                    Downloading: http://repo1.maven.org/maven2/org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.pom
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:pom:1.0.1-FINAL' in repository central (http://repo1.maven.org/maven2)
                    Downloading: https://repository.jboss.org/nexus/content/groups/public//org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.jar
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:jar:1.0.1-FINAL' in repository jboss-public-repository-group (https://repository.jboss.org/nexus/content/groups/public/)
                    Downloading: https://repository.jboss.org/nexus/content/repositories/deprecated//org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.jar
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:jar:1.0.1-FINAL' in repository jboss-deprecated (https://repository.jboss.org/nexus/content/repositories/deprecated/)
                    Downloading: http://repo1.maven.org/maven2/org/jboss/weld/weld-se/1.0.1-FINAL/weld-se-1.0.1-FINAL.jar
                    [INFO] Unable to find resource 'org.jboss.weld:weld-se:jar:1.0.1-FINAL' in repository central (http://repo1.maven.org/maven2)
                    [INFO] ------------------------------------------------------------------------
                    [ERROR] BUILD ERROR
                    [INFO] ------------------------------------------------------------------------
                    [INFO] Failed to resolve artifact.
                     
                    Missing:
                    ----------
                    1) org.jboss.weld:weld-se:jar:1.0.1-FINAL
                     
                      Try downloading the file manually from the project website.
                     
                      Then, install it using the command: 
                          mvn install:install-file -DgroupId=org.jboss.weld -DartifactId=weld-se -Dversion=1.0.1-FINAL -Dpackaging=jar -Dfile=/path/to/file
                     
                      Alternatively, if you host your own repository you can deploy the file there: 
                          mvn deploy:deploy-file -DgroupId=org.jboss.weld -DartifactId=weld-se -Dversion=1.0.1-FINAL -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
                     
                      Path to dependency: 
                           1) org.jboss.errai:errai-cdi-examples-server:jar:1.1-SNAPSHOT
                           2) org.jboss.weld:weld-se:jar:1.0.1-FINAL
                     
                    ----------
                    1 required artifact is missing.
                     
                    for artifact: 
                      org.jboss.errai:errai-cdi-examples-server:jar:1.1-SNAPSHOT
                     
                    from the specified remote repositories:
                      central (http://repo1.maven.org/maven2),
                      jboss-deprecated (https://repository.jboss.org/nexus/content/repositories/deprecated/),
                      jboss-public-repository-group (https://repository.jboss.org/nexus/content/groups/public/)
                     
                     
                     
                    
                    
                    • 7. Re: Another problem with serialization, ManyToMany and StackOverflow
                      heiko.braun

                      IIRC, you can safely exclude weld-se. It's not need anymore since 1.0.1-FINAL.

                      let me know if that works.

                      • 8. Re: Another problem with serialization, ManyToMany and StackOverflow
                        heiko.braun

                        If not get back to a previous version (i.e. CR1). I've been changing a lot in errai-cdi lately and will do in the next week.

                        So it might get a little rocky if you stick to the most recent version.

                        • 9. Re: Another problem with serialization, ManyToMany and StackOverflow
                          misqu23

                          Hi

                           

                          Ok. Right now my compiled cdi-integration works well. So I will wait for the next version. it's not a problem. When I excluded weld-se I got another errors. But as I wrote before, I will wait for the next version.