Сохранить инициализатор Hibernate от сбойной программы - PullRequest
0 голосов
/ 11 мая 2010

У меня есть программа на Java, использующая базовую фабрику сессий Hibernate. У меня возникла проблема с файлом отображения hibernate hbm.xml, и он потерпел крах в моей программе, хотя у меня был вызов getSessionFactory() при попытке перехвата

                try
                {
                    session = SessionFactoryUtil.getSessionFactory().openStatelessSession();    
                    session.beginTransaction();
                    rh = getRunHistoryEntry(session);
                    if(rh == null)
                    {
                        throw new Exception("No run history information found in the database for run id " + runId_ + "!");
                    }
                }
                catch(Exception ex)
                {
                    logger.error("Error initializing hibernate");
                }

Ему все еще удается вырваться из этой попытки / поймать и завершить работу основного потока. Как мне не допустить этого? Основная проблема в том, что у меня есть куча команд очистки, которые НУЖНО выполнить до того, как основной поток завершит работу, и я должен быть в состоянии гарантировать, что даже после сбоя он все еще очищается и несколько изящно завершает работу. Фабрика сессий выглядит так:

public class SessionFactoryUtil {
    private static final SessionFactory sessionFactory;  

    static {  
        try 
        {  
            // Create the SessionFactory from hibernate.cfg.xml  
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } 
        catch (Throwable ex) 
        {  
            // Make sure you log the exception, as it might be swallowed  
            System.err.println("Initial SessionFactory creation failed." + ex);  
            throw new ExceptionInInitializerError(ex);  
        }  
    }  

    public static SessionFactory getSessionFactory() 
    {   try
        {
            return sessionFactory;
        }
        catch(Exception ex)
        {
            return null;
        }
    }  
}

Выдается следующая ошибка, и я исправил ее, но я хотел бы защитить от любой ошибки инициализации спящего режима остановку основного потока.

Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate/TmdIndataLine.hbm.xml
Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.ryanco.db.SessionFactoryUtil.<clinit>(SessionFactoryUtil.java:19)
    at com.ryanco.rta.RtaMain.main(RtaMain.java:148)
Caused by: org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate/TmdIndataLine.hbm.xml
    at org.hibernate.cfg.Configuration.addResource(Configuration.java:616)
    at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1635)
    at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1603)
    at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1582)
    at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1556)
    at org.hibernate.cfg.Configuration.configure(Configuration.java:1476)
    at org.hibernate.cfg.Configuration.configure(Configuration.java:1462)
    at com.ryanco.db.SessionFactoryUtil.<clinit>(SessionFactoryUtil.java:13)
    ... 1 more
Caused by: org.hibernate.InvalidMappingException: Could not parse mapping document from input stream
    at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:555)
    at org.hibernate.cfg.Configuration.addResource(Configuration.java:613)
    ... 8 more
Caused by: org.dom4j.DocumentException: Error on line 114 of document  : The element type "class" must be terminated by the matching end-tag "</class>". Nested exception: The element type "class" must be terminated by the matching end-tag "</class>".
    at org.dom4j.io.SAXReader.read(SAXReader.java:482)
    at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:546)
    ... 9 more

Ответы [ 3 ]

1 голос
/ 12 мая 2010

Статический инициализатор в SessionFactoryUtil имеет try / catch для всех экземпляров Throwable, но ваш основной блок try / catch только перехватывает исключения. Я бы изменил его, чтобы ловить Throwables и посмотреть, решит ли это проблему.

0 голосов
/ 12 мая 2010

Ему все еще удается вырваться из этой попытки / поймать и завершить работу основного потока.

Как уже упоминалось, этот блок в вашем основном методе не поймает ExceptionInInitializerError, брошенный в ваш статический инициализатор:

catch(Exception ex) {
    logger.error("Error initializing hibernate")
}

Если вы хотите поймать и Exception, и Error, вам следует catch (Throwable t) (кстати, я заметил, что вы сказали, что вы изменили это, но я хотел бы увидеть, что именно вы изменили, и ошибку, которую вы получаете .

Но, если честно, если SessionFactory не удалось инициализировать, мне интересно, что вы собираетесь делать в вашем методе main, и на самом деле это обычная практика - позволить программе в этом случае не работать.

Последнее, try/catch в этой части кажется совершенно бесполезным:

public static SessionFactory getSessionFactory() {
    try {
        return sessionFactory;
    } catch(Exception ex) {
        return null;
    }
} 

Вы можете удалить его безопасно.

0 голосов
/ 12 мая 2010

Ну, в зависимости от того, какой тип приложения вы пишете, статические инициализаторы, делающие все, что выходит за пределы JVM, обычно являются плохой идеей.

К проблеме: если я правильно прочитал ваш код, вы сначала перехватите все Throwable s в статическом инициализаторе SessionFactoryUtil, напишите сообщение об ошибке для стандартной ошибки a, а затем сами создадите новый ExceptionInInitializerError , завернув в него пойманную Throwable.

Статические инициализаторы IIRC вызываются первым делом после загрузки класса. Трассировка стека говорит нам, что это происходит, вероятно, от основного метода в классе RtaMain, так как SessionFactoryUtil.getSessionFactory(), кажется, оттуда вызывается, что вызывает загрузку класса.

Чтобы поймать эту ошибку, вам нужно попробовать / поймать окружение вызова getSessionFactory() в главном методе вашего класса RtaUtil, перехватывая Throwable или, по крайней мере, конкретный throwable, который вы бросаете в статический инициализатор самостоятельно, ExceptionInInitializerError.

НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...