Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Singleton, NullPointerException 
:(
    Опции темы
LLIbIcpEP
Дата 9.2.2011, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Доброго времени суток.
Есть синглтон:
Код

public class DataRepositoryProducer {
    private static final LoggerFilter log = LoggerFilter.getLoggerFilter(DataRepositoryProducer.class);
    
    /**
     * Constructor.
     */
    private DataRepositoryProducer() {
        factory = Persistence.createEntityManagerFactory("pu-update");
        log.info("Created EntityManagerFactory");
    }
    
    /**
     * Holder.
     */
    private static class DataRepositoryProducerHolder {
        private static final DataRepositoryProducer instance = new DataRepositoryProducer();
    }
    
    /**
     * @return {@link DataRepositoryProducer}
     */
    public static DataRepositoryProducer getInstance() {
        return DataRepositoryProducerHolder.instance;
    }

    /**
     * Factory.
     */
    private EntityManagerFactory factory;
    
    /**
     * Singleton {@link EntityManagerFactory} getter.
     * @return {@link EntityManagerFactory}
     */
    private EntityManagerFactory getEntityManagerFactory() {
        return factory;
    }

    /**
     * Get {@link EntityManager}.
     * @return {@link EntityManager}
     */
    private EntityManager getEntityManager() {
        return getEntityManagerFactory().createEntityManager();
    }

        // дальше паблик-методы, работающие с EntityManager...
}

Дальше этот синглтон использую хочу использовать так:
Код

@Entity
public abstract class Unit implements Cloneable {
    private static final LoggerFilter log = LoggerFilter.getLoggerFilter(Unit.class);
    private static final DataRepositoryProducer drp = DataRepositoryProducer.getInstance();
        // Ну и все остальное...
}

Может я чего-то не понимаю, но в юнит-тестах получаю NullPointerException smile 
drp почему-то null. Никаких static { } конструкций не юзаю. Логгер (не синглтон, моя обертка к log4j для отложенной обработки строк) работает нормально, хотя объявляется и инициализируется там-же и так-же.
log.info("Created EntityManagerFactory"); - отрабатывает.
Как так?
PM MAIL   Вверх
Kircul
Дата 9.2.2011, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



LLIbIcpEP, стектрэйс в студию.
PM   Вверх
LLIbIcpEP
Дата 9.2.2011, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Код

java.lang.NullPointerException
    at my.model.Unit.save(Unit.java:165)
    at my.admin.model.Config.<init>(Config.java:55)
    at my.admin.bean.DataFactory.createConfigs(DataFactory.java:63)
    at my.admin.bean.DataFactory.createData(DataFactory.java:43)
    at my.test.GatewayTest.testInitEntityManagerFactory(GatewayTest.java:78)

Config унаследован от Unit. Метод save() в Unit:
Код

    /**
     * Save this unit to DB.
     * @return {@link Unit}
     */
    @SuppressWarnings("unchecked")
    public <T extends Unit> T save() {
        return (T) drp.saveUnit(this);
    }

Вылетаем при попытке drp.saveUnit(this), drp - null.

Это сообщение отредактировал(а) LLIbIcpEP - 9.2.2011, 13:20
PM MAIL   Вверх
LSD
Дата 9.2.2011, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Код

@Entity
public abstract class Unit implements Cloneable {
    private static final LoggerFilter log = LoggerFilter.getLoggerFilter(Unit.class);
    private static final DataRepositoryProducer drp = DataRepositoryProducer.getInstance();
        // Ну и все остальное...
}

Есть подозрение что LoggerFilter.getLoggerFilter(Unit.class) вызывает метод save(), а значит он будет вызван до того как будет проинициализирован drp.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
LLIbIcpEP
Дата 9.2.2011, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Да нет, это разные компоненты, функционально не связанные. LoggerFilter - простая обертка для log4j, в которую передаю String format и аргументы, а конкатенация строк и toString() аргументов происходит только если соответствует уровень логов в конфиге. Я в курсе, что slf4j умеет такое из коробки, но вот...

Код

public class LoggerFilter {
    private Logger log;
    
    @SuppressWarnings("unchecked")
    private LoggerFilter(Class clazz) {
        log = Logger.getLogger(clazz);
    }
    
    @SuppressWarnings("unchecked")
    public static LoggerFilter getLoggerFilter(Class clazz) {
        return new LoggerFilter(clazz);
    }
        // и т.д...
    
    public boolean isTraceEnabled() {
        return log.isEnabledFor(Level.TRACE);
    }
...
    public void trace(String format, Object... args) {
        if (isTraceEnabled()) {
            log.trace(String.format(format, args));
        }
    }
    
    public void trace(String format, Throwable t, Object... args) {
        if (isTraceEnabled()) {
            log.trace(String.format(format, args), t);
        }
    }
    
    public void trace(Throwable t) {
        if (isTraceEnabled()) {
            log.trace(t);
        }
    }
...
}

Метод save() вызывается в не пустых конструкторах сущностей, если это важно.

Это сообщение отредактировал(а) LLIbIcpEP - 9.2.2011, 14:14
PM MAIL   Вверх
LLIbIcpEP
Дата 9.2.2011, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Насколько правильно будет определять drp только в тех методах, где он юзается? Это ведь синглтон, по производительности ударить не должно?
PM MAIL   Вверх
LSD
Дата 9.2.2011, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Честно говоря, я вообще не понимаю зачем тут такие сложности. Зачем внутри DataRepositoryProducer объявлять класс DataRepositoryProducerHolder все назначение которого держать ссылку на внешний класс? Тут явно не в том порядке инициализируются поля, отсюда и null.

Добавлено через 2 минуты и 56 секунд
Если все таки решишь разобраться, что там и как - добавь в каждый класс:
Код

    static {
        System.out.println("Init class " + <put_class_name_here>.class);
    }



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
LLIbIcpEP
Дата 9.2.2011, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Это просто такая реализация синглтона.
user posted image
Смена реализации на классический вариант не помогает.
user posted image

У этой реализации недостаток - нельзя обработать исключения в конструкторе синглтона. Но мне это не надо. Зато есть выгода - нет лишних ифов и synchronized-блоков при поддержке многопоточности и отложенной инициализации, плюс к перфомансу.

Добавлено через 9 минут и 26 секунд
PS:
Код

    private static final DataRepositoryProducer drp = DataRepositoryProducer.getInstance();
    static {
        System.out.println("Init class " + Unit.class + " " + drp);
    }

Код

Init class class my.model.Unit null


Это сообщение отредактировал(а) LLIbIcpEP - 9.2.2011, 18:22
PM MAIL   Вверх
LLIbIcpEP
Дата 9.2.2011, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Это вообще смешно)
Код

    private static final DataRepositoryProducer drp;
    static {
        drp = DataRepositoryProducer.getInstance();
        System.out.println("Init class " + Unit.class + " " + drp);
    }

Код

Init class class my.model.Unit null


Добавлено через 7 минут и 30 секунд
Ага, все стало на свои места. Сделал в синглтоне:
Код

    /**
     * Holder.
     */
    private static class DataRepositoryProducerHolder {
        private static final DataRepositoryProducer instance;
        static {
            instance = new DataRepositoryProducer();
            System.out.println("Init class " + DataRepositoryProducer.class + " " + instance);
        }
    }

И оставил первое. Выводится следующее:
Код

Init class class my.model.Unit null
Init class class my.admin.bean.DataRepositoryProducer it.treed.quasar.dreamplanet.admin.bean.DataRepositoryProducer@e5ace9

Юнит инициализируется до статик поля в DataRepositoryProducerHolder. Как бороться? У меня уже чисто спортивный интерес)

Это сообщение отредактировал(а) LLIbIcpEP - 9.2.2011, 18:39
PM MAIL   Вверх
_sten_
Дата 9.2.2011, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 184
Регистрация: 29.9.2006

Репутация: нет
Всего: 3



а какая JVM?
--------------------
WARNING: Condition 'to_be || !to_be' is always 'true' !
PM MAIL ICQ   Вверх
techmax
Дата 10.2.2011, 04:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 5.9.2007
Где: Красноярск

Репутация: 2
Всего: 2



Как вариант:
Код

@SuppressWarnings("unchecked")
    public <T extends Unit> T save() {
        return (T) DataRepositoryProducer.getInstance().saveUnit(this);

PM MAIL Skype   Вверх
LLIbIcpEP
Дата 10.2.2011, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Цитата(_sten_ @ 9.2.2011,  23:30)
а какая JVM?

Код

Java: Sun Microsystems Inc. Java(TM) SE Runtime Environment 1.6.0_22
Java VM: Sun Microsystems Inc. Java HotSpot(TM) Server VM 17.1-b03


Добавлено через 1 минуту и 10 секунд
Цитата(techmax @ 10.2.2011,  04:11)
Как вариант:
Код

@SuppressWarnings("unchecked")
    public <T extends Unit> T save() {
        return (T) DataRepositoryProducer.getInstance().saveUnit(this);

Да, вариант, просто не хотелось бы делать громоздкое объявление DataRepositoryProducer в каждом методе, где он нужен...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0914 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.