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

    Another problem with serialization, ManyToMany and StackOverflow

    Marcin Misiewicz Newbie

      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

        • 2. Re: Another problem with serialization, ManyToMany and StackOverflow
          Marcin Misiewicz Newbie

          Thanks for the quick response.

           

          I'm looking forward for the solution.

          • 3. Re: Another problem with serialization, ManyToMany and StackOverflow
            Mike Brock Master

            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
              Marcin Misiewicz Newbie

              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.

              • 6. Re: Another problem with serialization, ManyToMany and StackOverflow
                Marcin Misiewicz Newbie

                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 Master

                  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 Master

                    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
                      Marcin Misiewicz Newbie

                      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.