6 Replies Latest reply on Feb 28, 2008 9:20 PM by boki

    Lazy Initialization issue?

    boki

      I seem to be running into a lazy initialization issue while trying to prepare data for editing.
      I have a stateful session bean with conversational scope.  Entities have several levels of relationships.
      I will use a snippet similar to the one from the Seam book, Chapter 5. to explain the issue.


      Each teacher has many students, each student has one final grade given by that teacher, and each final grade has a numeric value.


      @Begin(join=true)
      public void prepareGrades(Long teacherId)     
      {     
        Teacher teacher = entityManager.find(Teacher.class, teacherId);       
        List<Student> students = new ArrayList(teacher.getAllStudents());
        for (Student student : students) {
           FinalGrade grade = student.getFinalGrade();
           gradesList.add(grade.getNumericGrade());
         }
         myBean.setGradesList(gradesList);
      }
      


      When debugging, I can drill down into each

      student

      and see that the handler is of type
      org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer


      Inside that handler, I see  the correct values for FinalGrade object. However,
      student.getFinalGrade()

      returns nulls for those values.


      Why is this happening and what is the recommended way of avoiding issues like this?
      Thanks!

        • 1. Re: Lazy Initialization issue?
          keithnaas

          Excellent question.  Would you be able to share the Teacher, Student, and FinalGrade classes?

          • 2. Re: Lazy Initialization issue?
            jimk1723

            And how you're getting your entity manager? Is it a default, extended or Seam-managed persistence context, e.g.


            @PersistenceContext
            EntityManager entityManager;
            



            @PersistenceContext(type=EXTENDED)
            EntityManager entityManager;
            



            @In
            EntityManger entityManager
            




            • 3. Re: Lazy Initialization issue?
              boki

              I get the entity manager using


              @PersistenceContext(type=EXTENDED)
              EntityManager entityManager;
              


              As for source, classes are generated from the database using seam-gen. I assume it is hard to point me into any direction without the source? If so, I'll do some cleanup and post the code as soon as I can.

              • 4. Re: Lazy Initialization issue?
                boki

                Actually, while cleaning up the code for new post here, I realized I could change the FetchType on getGradeValue to eager, but that has not fixed it either.


                //imports go here
                /**
                 * Student generated by hbm2java
                 */
                @Entity
                @Table(name = "student", catalog = "test")
                public class Student implements java.io.Serializable {
                     private static final long serialVersionUID = 1601881459097872908L;
                     private Integer studentId;
                     private Grade grade;
                     private Teacher teacher;
                     private String studentName;
                
                     public Student() {
                     }
                
                     public Student(Grade grade, Teacher teacher, String studentName) {
                          this.grade = grade;
                          this.teacher = teacher;
                          this.studentName = studentName;
                     }
                
                     @Id
                     @GeneratedValue(strategy = IDENTITY)
                     @Column(name = "student_id", unique = true, nullable = false)
                     public Integer getStudentId() {
                          return this.studentId;
                     }
                
                     public void setStudentId(Integer studentId) {
                          this.studentId = studentId;
                     }
                     @ManyToOne(fetch = FetchType.LAZY)
                     @JoinColumn(name = "grade_id", nullable = false)
                     @NotNull
                     public Grade getGrade() {
                          return this.grade;
                     }
                
                     public void setGrade(Grade grade) {
                          this.grade = grade;
                     }
                     @ManyToOne(fetch = FetchType.LAZY)
                     @JoinColumn(name = "teacher_id", nullable = false)
                     @NotNull
                     public Teacher getTeacher() {
                          return this.teacher;
                     }
                
                     public void setTeacher(Teacher teacher) {
                          this.teacher = teacher;
                     }
                
                     @Column(name = "student_name", nullable = false, length = 45)
                     @NotNull
                     @Length(max = 45)
                     public String getStudentName() {
                          return this.studentName;
                     }
                
                     public void setStudentName(String studentName) {
                          this.studentName = studentName;
                     }
                }
                




                 //imports go here
                /**
                 * Teacher generated by hbm2java
                 */
                @Entity
                @Table(name = "teacher", catalog = "test")
                public class Teacher implements java.io.Serializable {
                     private static final long serialVersionUID = -5621323306701394395L;
                     private Integer teacherId;
                     private String teacherName;
                     private Set<Student> students = new HashSet<Student>(0);
                
                     public Teacher() {
                     }
                
                     public Teacher(String teacherName) {
                          this.teacherName = teacherName;
                     }
                     public Teacher(String teacherName, Set<Student> students) {
                          this.teacherName = teacherName;
                          this.students = students;
                     }
                
                     @Id
                     @GeneratedValue(strategy = IDENTITY)
                     @Column(name = "teacher_id", unique = true, nullable = false)
                     public Integer getTeacherId() {
                          return this.teacherId;
                     }
                
                     public void setTeacherId(Integer teacherId) {
                          this.teacherId = teacherId;
                     }
                
                     @Column(name = "teacher_name", nullable = false, length = 45)
                     @NotNull
                     @Length(max = 45)
                     public String getTeacherName() {
                          return this.teacherName;
                     }
                
                     public void setTeacherName(String teacherName) {
                          this.teacherName = teacherName;
                     }
                     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "teacher")
                     public Set<Student> getStudents() {
                          return this.students;
                     }
                
                     public void setStudents(Set<Student> students) {
                          this.students = students;
                     }
                
                }



                //imports here
                /**
                 * Grade generated by hbm2java
                 */
                @Entity
                @Table(name = "grade", catalog = "test")
                public class Grade implements java.io.Serializable {
                     private static final long serialVersionUID = 1082275105130293538L;
                     private Integer gradeId;
                     private String gradeValue;
                     private String description;
                     private Set<Student> students = new HashSet<Student>(0);
                
                     public Grade() {
                     }
                
                     public Grade(String gradeValue, String description) {
                          this.gradeValue = gradeValue;
                          this.description = description;
                     }
                     public Grade(String gradeValue, String description, Set<Student> students) {
                          this.gradeValue = gradeValue;
                          this.description = description;
                          this.students = students;
                     }
                
                     @Id
                     @GeneratedValue(strategy = IDENTITY)
                     @Column(name = "grade_id", unique = true, nullable = false)
                     public Integer getGradeId() {
                          return this.gradeId;
                     }
                
                     public void setGradeId(Integer gradeId) {
                          this.gradeId = gradeId;
                     }
                
                     @Column(name = "grade_value", nullable = false, length = 45)
                     @NotNull
                     @Length(max = 45)
                     public String getGradeValue() {
                          return this.gradeValue;
                     }
                
                     public void setGradeValue(String gradeValue) {
                          this.gradeValue = gradeValue;
                     }
                
                     @Column(name = "description", nullable = false, length = 45)
                     @NotNull
                     @Length(max = 45)
                     public String getDescription() {
                          return this.description;
                     }
                
                     public void setDescription(String description) {
                          this.description = description;
                     }
                     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "grade")
                     public Set<Student> getStudents() {
                          return this.students;
                     }
                
                     public void setStudents(Set<Student> students) {
                          this.students = students;
                     }
                }



                //imports
                @Stateful
                @Scope(ScopeType.CONVERSATION)
                @Name("myManager")
                public class ManagerBean implements Manager {
                    @PersistenceContext(type=EXTENDED)
                    EntityManager entityManager;
                    private Teacher teacher;
                    private List<String> gradesList;
                    
                     @Begin(join=true)
                    public void prepareTeacherData(Integer teacherId)
                    {
                         Teacher t = entityManager.find(Teacher.class, teacherId);
                         this.setTeacher(t);
                         Set<Student> set = teacher.getStudents();
                         List<Student> students = new ArrayList<Student>(set);
                         for (int i = 0; i < students.size(); i++) {
                              Student student = students.get(i);
                               Grade grade = student.getGrade();
                               String aGrade = grade.getGradeValue();
                               gradesList.add(aGrade);
                          }
                         this.setGradesList(gradesList);
                    }
                     public Teacher getTeacher() {
                          return teacher;
                     }
                     public void setTeacher(Teacher teacher) {
                          this.teacher = teacher;
                     }
                     public List<String> getGradesList() {
                          return gradesList;
                     }
                     public void setGradesList(List<String> gradesList) {
                          this.gradesList = gradesList;
                     }
                     @Remove
                     public void destroy() {}
                     public void cancel() {}
                }



                In the bean I tried to do everything step by step, assigning values to variables each time, however, the result is

                java.lang.NullPointerException

                at
                ManagerBean.prepareTeacherData(ManagerBean.java:42)


                In debug mode, I see all assignments inside the bean method done correctly, but when I try to add the grade value to the list, that's when I get the exception. So, either I am doing something really dumb and not seeing it, or perhaps I am missing some key concepts, but I can't seem to figure it out. Any help is appreciated.

                • 5. Re: Lazy Initialization issue?
                  srini.ragu

                  private List<String> gradesList;


                  intialize gradeList inline with new ArrayList or have a @Create on a method which initializes gradeList.

                  • 6. Re: Lazy Initialization issue?
                    boki

                    Yes, I just realized it... was about to post it. Sometimes two eyes looking at something just are not enough. Thanks!