Сдали проект. Запустили в эксплуатацию. Через 3-4 дня приходит первый алёрт от Заказчика об ошибке, блокирующей работу админки. Перезагрузка или переустановка приложения проблемного модуля восстанавливает работоспособность админки. Приложение работает с использованием Spring 3.0 + Hibernate 4.1 по спецификации JPA 2.0.
Недели 2 переписки с Заказчиком и выяснения обстоятельств проявления ошибки + 2 недели активного поиска причины ошибки. Ошибка плавающая, проявляется с периодичностью 3-5 дней только при сохранении @Entity объектов. В stacktrace рутовая ошибка разная, но чаще всего:
Экспериментальным путем было выявлено, что ошибка проявляется только при одновременной интенсивной работе нескольких редакторов. Важная деталь: другой модуль этого же приложения такой ошибки не проявляет. Похоже на проблему конфигурации или модели данных конкретного модуля?
Манипуляции с исходным кодом админки, DAO и модели в результате привели к интересной ошибке:
Это навело на мысль, что ошибка возникает в условиях одновременного сохранения в БД достаточно большого числа разных потоков. Нашли в документации Spring упоминание специфики использования DAO на базе JPA, и в частности подключения EntityManager к DAO с PersistenceContextType.EXTENDED:
The alternative, PersistenceContextType.EXTENDED, is a completely different affair: This results in a so-called "extended EntityManager", which is not thread-safe and hence must not be used in a concurrently accessed component such as a Spring-managed singleton bean.
Проверили: так и есть, один из предыдущих разработчиков модуля включил в аннотацию @PersistanceContext атрибут PersistenceContextType.EXTENDED. Включение этого атрибута позволило ему упростить код в отношении получения коллекций связанных сущностей по LazyFetch, однако в результате привело к плавающей ошибке!
Недели 2 переписки с Заказчиком и выяснения обстоятельств проявления ошибки + 2 недели активного поиска причины ошибки. Ошибка плавающая, проявляется с периодичностью 3-5 дней только при сохранении @Entity объектов. В stacktrace рутовая ошибка разная, но чаще всего:
Caused by: org.hibernate.HibernateException: Flush during cascade is dangerous
Экспериментальным путем было выявлено, что ошибка проявляется только при одновременной интенсивной работе нескольких редакторов. Важная деталь: другой модуль этого же приложения такой ошибки не проявляет. Похоже на проблему конфигурации или модели данных конкретного модуля?
Манипуляции с исходным кодом админки, DAO и модели в результате привели к интересной ошибке:
java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
Это навело на мысль, что ошибка возникает в условиях одновременного сохранения в БД достаточно большого числа разных потоков. Нашли в документации Spring упоминание специфики использования DAO на базе JPA, и в частности подключения EntityManager к DAO с PersistenceContextType.EXTENDED:
The alternative, PersistenceContextType.EXTENDED, is a completely different affair: This results in a so-called "extended EntityManager", which is not thread-safe and hence must not be used in a concurrently accessed component such as a Spring-managed singleton bean.
Проверили: так и есть, один из предыдущих разработчиков модуля включил в аннотацию @PersistanceContext атрибут PersistenceContextType.EXTENDED. Включение этого атрибута позволило ему упростить код в отношении получения коллекций связанных сущностей по LazyFetch, однако в результате привело к плавающей ошибке!