Объект домена, возвращенный из RestController, вызывает ошибку AJAX; Пользовательский объект модели работает

У меня есть проблема в моем SpringMVC RestController, которая записывает результаты JSON:

1) Когда я возвращаю объект домена, как показано ниже, ActivityT, я получаю внутреннюю ошибку сервера AJAX 500 на стороне клиента.

@RequestMapping("/participant/activityForEvent") 
public ActivitiesT getActivityForGuiEventId() throws Exception {
    ActivitiesT activitiesT = participantService.getActivity();
    return activitiesT;
}

Объект домена ActivityT, сгенерированный Hiberate:

@Entity
@Table(name = "activities_t", schema = "public")
public class ActivitiesT implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private int id;
    //... etc...
}

2) Но когда я возвращаю пользовательский POJO, метод AJAX работает. Это почти то же самое.

@RequestMapping("/participant/activityForEvent") 
public ActivitiesT getActivityForGuiEventId() throws Exception {
    ActivitiesT activitiesT = participantService.getActivity();
    // Create a custom Activity POJO and return it
    return new Activity(activitiesT.id, activitiesT.title);
}

Пользовательский POJO активности:

public class Activity implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public int id;
    public String title;
     //etc.

СООБЩЕНИЕ ОБ ОШИБКЕ

HTTP Status 500 - Could not write JSON: could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - 

нет сеанса (через цепочку ссылок: com.myapp")

Некоторые вещи, которые следует отметить:

  • Оба объекта реализуют Serializable, это нормально
  • Проблема не в DAO, я вижу, что DAO всегда возвращает правильные данные для обоих, мы можем игнорировать часть DAO.
  • Контроллер имеет аннотацию @RestController, поэтому он всегда выводит JSON; Мне не нужен ResponseBody или старые теги

Любые мысли о том, где проблема может лежать? Проблема сводится к следующему:

  • Я не могу вернуть JSON из методов RestController для сгенерированных Hibernate @Entity POJO,
  • Но я могу вернуть JSON из методов RestController в свои собственные POJO.

person gene b.    schedule 18.12.2017    source источник
comment
Не могли бы вы предоставить исключение, которое выдается (500 Internal Server Error)?   -  person lzagkaretos    schedule 18.12.2017
comment
Никаких исключений на стороне сервера не выдается, Контроллер завершает работу ОК. Я вижу только 500 Internal Server Error в Firebug, когда я добираюсь до AJAX JS на стороне клиента.   -  person gene b.    schedule 18.12.2017
comment
500 Internal Server Error указывает на то, что что-то происходит на стороне сервера. Я видел такие проблемы при сериализации больших объектов, ActivitiesT - это простой или сложный объект (просто угадывая), где какое-то исключение было вызвано после того, как контроллер вернул значение.   -  person lzagkaretos    schedule 18.12.2017
comment
Я получил сообщение об ошибке, вот оно: HTTP Status 500 - Could not write JSON: could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.myapp")   -  person gene b.    schedule 18.12.2017
comment
Возможно, в Entity живет какая-то ленивая инициализация, и когда Джексон пытается получить доступ к этим свойствам, спискам, транзакция недоступна. Вы можете это проверить?   -  person lzagkaretos    schedule 18.12.2017
comment
Да, похоже, здесь есть поток: stackoverflow.com/questions/26957554/ Объяснение таково: это происходит, когда вы возвращаете объект через @Responsebody (или, в вашем случае, тело ответа через @RestController), и объект сериализуется но имеет дочерние элементы в коллекции LAZY, на которые не было ссылок. К тому времени, когда вы находитесь в своем контроллере, больше не активна транзакция, которая облегчит их получение.   -  person gene b.    schedule 18.12.2017
comment
Да, я считаю, что это проблема. :) Удачи   -  person lzagkaretos    schedule 18.12.2017


Ответы (1)


Когда Джексон подготавливает ответ, он рекурсивно пытается преобразовать классы модели в JSON. Например, если у вас есть отношение «Отдел» и «Сотрудник» с отношением «один ко многим», тогда Джексон выполняет метод getEmployees() в Department.java для подготовки ответа. Но getEmployees() метод требует, чтобы hibernate выполнил другой запрос для извлечения записей о сотрудниках из БД из-за ленивой загрузки. Но сессия уже закрыта. Следовательно, вы получаете эту ошибку. Чтобы избежать этого, всегда используйте DTO вместо реальных классов модели. И то же самое, что вы упомянули, - объект домена, возвращенный из RestController, вызывает ошибку AJAX; Пользовательский объект модели работает.

person Dhiraj Ray    schedule 19.12.2017
comment
Да, теперь мы используем простые POJO для всех методов, возвращающих JSON. спасибо - person gene b.; 19.12.2017