I get a 500 error message from Tomcat when I return a list of objects from my service level in Spring. If I just make the entities “on the fly” in memory, I won’t get an error and they will be back in order, so do something specifically with transactions.
I have the following method in my controller ...
@RequestMapping(value = "{examid}", method = RequestMethod.GET) @ResponseBody public List<Exam> getExam(@PathVariable String examid, Model model) { return examService.getAllExams(); }
When this method is called, tomcat displays a 500 error and has no stack trace at all. I even wrapped it in a catch attempt and nothing appears in this stacktrace.
This service just calls dao ...
@Service("examService") public class ExamServiceImpl implements ExamService{ @Autowired private ExamDao examDao; @Override @Transactional(readOnly = true) public List<Exam> getAllExams() { return examDao.getAllExams(); }
And that dao just returns a simple HQL script ...
@Repository("examDao") public class ExamDaoImpl implements ExamDao { @Autowired private SessionFactory sessionFactory; @Override public List<Exam> getAllExams() { return sessionFactory.getCurrentSession().createQuery("from Exam") .list(); }
Initially, I thought that this is due to the fact that objects are loaded lazy, my entities are lower, as you can see, they are very simple
@Entity @Table(name = "exams") public class Exam implements Serializable { private static final long serialVersionUID = -5109075534794721930L; @Id @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy = "uuid") @Column(name = "examid", unique = true) private String examId; @OneToMany(mappedBy = "exam") private Set<Question> questions; public String getExamId() { return examId; } public void setExamId(String examId) { this.examId = examId; } @JsonManagedReference public Set<Question> getQuestions() { return questions; } public void setQuestions(Set<Question> questions) { this.questions = questions; } }
Question Object
@Entity @Table(name = "questions") public class Question implements Serializable { private static final long serialVersionUID = 8804841647267857850L; private String questionId; private Exam exam; private Set<Answer> answers; @JsonManagedReference @OneToMany(mappedBy = "question") public Set<Answer> getAnswers() { return answers; } public void setAnswers(Set<Answer> answers) { this.answers = answers; } @JsonBackReference @ManyToOne @JoinColumn(name = "examid", nullable = false) public Exam getExam() { return exam; } public void setExam(Exam exam) { this.exam = exam; } @Id @GeneratedValue(generator = "system-uuid") @GenericGenerator(name = "system-uuid", strategy = "uuid") @Column(name = "questionid", unique = true) public String getQuestionId() { return questionId; } public void setQuestionId(final String questionId) { this.questionId = questionId; } }
Response object
@Entity @Table(name = "answers") public class Answer implements Serializable { private static final long serialVersionUID = -3922870865886851018L; @Id @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy = "uuid") @Column(name = "answerid", unique = true) private String answerId; @ManyToOne() @JoinColumn(name = "questionid", nullable = false) private Question question; @JsonBackReference public Question getQuestion() { return question; } public void setQuestion(Question question) { this.question = question; } public String getAnswerId() { return answerId; } public void setAnswerId(final String answerId) { this.answerId = answerId; } }
I am using Jackson 2.2.0 - now the following code works fine, so definitely the problem is either with the joins (which were originally downloaded but deleted for debugging). Just returning the following code from the controller works fine ...
Exam exam = new Exam(); Question presidentQuestion = new Question(); presidentQuestion.setExam(exam); Question skyQuestion = new Question(); skyQuestion.setExam(exam); Set<Question> questions = new HashSet<>(); questions.add(skyQuestion); questions.add(presidentQuestion); exam.setQuestions(questions); Answer answer = new Answer(); answer.setQuestion(skyQuestion); Answer answer1 = new Answer(); answer1.setQuestion(skyQuestion); Answer answer2 = new Answer(); answer2.setQuestion(presidentQuestion); Set<Answer> answers1 = new HashSet<>(); answers1.add(answer2); Set<Answer> answers = new HashSet<>(); answers.add(answer); answers.add(answer1); presidentQuestion.setAnswers(answers1); skyQuestion.setAnswers(answers); return Arrays.asList(exam);
There is nothing in Tomcat logs - how can I force some kind of stack? Hibernate version = 4.1.10. Final, Spring version 3.1.4.