Шаблон Singleton с ini4j

Исходная проблема: программа считывала входные данные старого файла конфигурации (.ini).

Новая проблема: после попытки одноэлементного шаблона с потоком / ini я больше не могу писать в файл. Это бросает исключение java.io.FileNotFoundException.

Могу ли я изменить свой класс конфигурации, чтобы он работал?

Заранее спасибо.

Класс конфигурации:

import org.ini4j.Wini;
import java.io.*;

//http://www.javenue.info/post/40

public class Configuration {
    private static Configuration _instance = null;

    private Wini ini = null;
    FileInputStream stream;

    private Configuration() {
        ini= new Wini();
        try {
            stream = new FileInputStream(Constants.PATH);
            ini.load(stream);
        }
        catch (Exception e) {
            System.out.println("FILE NOT FOUND!");
        }
    }

    public synchronized static Configuration getInstance() {
        if (_instance == null)
            _instance = new Configuration();
        return _instance;
    }

    public String getConfig(String xSectionName, String xFieldValue){

        String readValue = null;

        if (ini.get(xSectionName, xFieldValue) != null) {
            readValue = ini.get(xSectionName, xFieldValue);
        } else {
            // TODO: What should happen
        }
        return readValue;
    }

    public void setConfig(String xSectionName, String xFieldValue, String xValue){

        System.out.println("Section: " + xSectionName);
        System.out.println("Field:   " + xFieldValue);
        System.out.println("Value:   " + xValue + "\n\n");

        try {
            ini.put(xSectionName, xFieldValue, xValue);
            ini.store();
        } catch (Exception e1) {
            System.out.println(xValue + " could not be stored.");
            e1.printStackTrace();
        }
    }
}

Раздел: дрифт

Поле: mu

Значение: 5

5 не удалось сохранить.

Решение новой проблемы: см. Ответ ниже.

Разрешение на исходный выпуск:

Я динамически загружал класс с библиотекой Java-Runtime-Compiler. После некоторого исследования я прочитал, что ClassLoader может иметь только один экземпляр определенного класса. Итак, решение состоит в том, чтобы создать новый экземпляр ClassLoader в методе .loadFromJava (), и проблема с бумом решена.

Вот немного кода.

Динамический класс реализует Callable и возвращает объект, поэтому можно получить все, что он там создал.

import net.openhft.compiler.CompilerUtils;

...

ClassLoader classloader = new ClassLoader() {
        };

Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(classloader, className, javaCode);

Callable<Object[]> caller = (Callable<Object[]>) aClass.newInstance();

Object[] obj = (Object[]) caller.call();

...

Я только что просмотрел исходный код.
Проблема в том, что

import org.ini4j.Wini;
import java.io.*;

//http://www.javenue.info/post/40

public class Configuration {
    private static Configuration _instance = null;

    private Wini ini = null;
    FileInputStream stream;

    private Configuration() {
        ini= new Wini();
        try {
            stream = new FileInputStream(Constants.PATH);
            ini.load(stream);
        }
        catch (Exception e) {
            System.out.println("FILE NOT FOUND!");
        }
    }

    public synchronized static Configuration getInstance() {
        if (_instance == null)
            _instance = new Configuration();
        return _instance;
    }

    public String getConfig(String xSectionName, String xFieldValue){

        String readValue = null;

        if (ini.get(xSectionName, xFieldValue) != null) {
            readValue = ini.get(xSectionName, xFieldValue);
        } else {
            // TODO: What should happen
        }
        return readValue;
    }

    public void setConfig(String xSectionName, String xFieldValue, String xValue){

        System.out.println("Section: " + xSectionName);
        System.out.println("Field:   " + xFieldValue);
        System.out.println("Value:   " + xValue + "\n\n");

        try {
            ini.put(xSectionName, xFieldValue, xValue);
            ini.store();
        } catch (Exception e1) {
            System.out.println(xValue + " could not be stored.");
            e1.printStackTrace();
        }
    }
}
в классе
import net.openhft.compiler.CompilerUtils;

...

ClassLoader classloader = new ClassLoader() {
        };

Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(classloader, className, javaCode);

Callable<Object[]> caller = (Callable<Object[]>) aClass.newInstance();

Object[] obj = (Object[]) caller.call();

...
следует избегать загрузки ini-файла, если вы хотите использовать тот же экземпляр _3_ для вызова метода _4_.
Почему? Поскольку метод _5_ ожидает наличия существующего файлового поля в экземпляре текущего _6_, но не может его найти, поскольку вы загрузили ini из потока, а не из файла.


person Edv Beq    schedule 25.12.2016    source источник
comment
Для синглтона вы можете сделать проще и без явной синхронизации с реализацией синглтона Билла Пью.   -  person davidxxx    schedule 25.12.2016
comment
@davidxxx он печатает ... не может быть сохранен.   -  person davidxxx    schedule 25.12.2016
comment
Хорошо, а вы можете опубликовать трассировку стека, связанную с этим исключением?   -  person Edv Beq    schedule 25.12.2016
comment
Я думаю, проблема в потоке - когда он пытается писать, у него больше нет доступа. Я надеюсь, что есть способ преодолеть это.   -  person davidxxx    schedule 25.12.2016
comment
Я видел. Спасибо. Пишу вам полный ответ.   -  person Edv Beq    schedule 25.12.2016
comment
Большое спасибо. Это решило проблему записи и значительно упростило поиск и устранение исходной проблемы. Я добавил пояснение в описание, если вам интересно. Еще раз спасибо - и счастливых праздников.   -  person davidxxx    schedule 25.12.2016


Ответы (1)


Поэтому вам следует загрузить ini-файл с помощью конструктора Wini. Конструктор принимает в качестве параметра File и дополнительно устанавливает поле внутри экземпляра для загрузки содержимого ini.

Посмотри на это :

Так что замените:

public Wini(File input) throws IOException, InvalidFileFormatException{
        this();
        setFile(input);
        load();
}

этим :

 private Configuration() {
        ini = new Wini();
        try {
            stream = new FileInputStream(Constants.PATH);
            ini.load(stream);
        }
        catch (Exception e) {
            System.out.println("FILE NOT FOUND!");
        }
    }

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

private Configuration()  {
    try {
        ini= new Wini(new File(Constants.PATH));
    }
    catch (Exception e) {
        LOGGER.error("Exception during init of Configuration",e);
    }
}

void load(InputStream input) выполняется во время выполнения?

public class Configuration {

    private static Logger LOGGER = Logger.getLogger(Configuration.class)//

    private static class HolderLazySingleton {
        private static Configuration instance = new Configuration();
    }

    private Wini ini = null;

    private Configuration() {    
        try {
            ini = new Wini(new File(Constants.PATH));    
        } catch (Exception e) {
            LOGGER.error("Exception during init of Configuration",e);
        }
    }

    public static Configuration getInstance() {
        return HolderLazySingleton.instance;
    }

    public String getConfig(String xSectionName, String xFieldValue) {

        String readValue = null;

        if (ini.get(xSectionName, xFieldValue) != null) {
            readValue = ini.get(xSectionName, xFieldValue);
        } else {
            // TODO: What should happen
        }
        return readValue;
    }

    public void setConfig(String xSectionName, String xFieldValue, String xValue) {

        System.out.println("Section: " + xSectionName);
        System.out.println("Field:   " + xFieldValue);
        System.out.println("Value:   " + xValue + "\n\n");

        try {
            ini.put(xSectionName, xFieldValue, xValue);
            ini.store();
        } catch (Exception e1) {
            LOGGER.error(xValue + " could not be stored.", e1);         
        }
    }
}
person davidxxx    schedule 25.12.2016
comment
Отличные новости. Я видел решение исходной проблемы: интересно. Добро пожаловать. С праздником тебя тоже :) - person Edv Beq; 26.12.2016
comment
java.io.FileNotFoundException в org.ini4j.Ini.store (Ini.java:126) в application.prototypes.Configuration.setConfig (Configuration.java:72) в application.prototypes.UserInputs.lambda $ 0 (UserInputs.java:92 ) в com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent (CompositeEventHandler.java:86) в com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent (EventHandlerManager.java:238.java.java.event.event. dispatchBubblingEvent (EventHandlerManager.java:191) в com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent (CompositeEventDispatcher.java:59) в com.sun.javafx.event.BasicEventDispatcher58 (в com.sun.javafx.event.BasicEventDispatcher58) (BasicEventDispatcher). .javafx.event.EventDispatchChainImpl.dispatchEvent (EventDispatchChainImpl.java:114) в com.sun.javafx.event.BasicEventDispatcher.dispatchEvent (BasicEventDispatcher.java:56) в com.sun.javafispatcher (EventChainDispatcher. DispatchChainImpl.java:114) по адресу com.sun.javafx.event.BasicEventDispatcher.dispatchEvent (BasicEventDispatcher.java:56) в com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent (EventDispatch.javaxhainImpl.dispatchEvent (EventDispatch.javashain) в com.Dispatch.javax11: // .event.EventUtil.fireEventImpl (EventUtil.java:74) в com.sun.javafx.event.EventUtil.fireEvent (EventUtil.java:54) в javafx.event.Event.fireEvent (Event.java:198) в javafx. scene.Scene $ KeyHandler.process (Scene.java:3964) в javafx.scene.Scene $ KeyHandler.access $ 1800 (Scene.java:3910) в javafx.scene.Scene.impl_processKeyEvent (Scene.java:2040) в javafx. scene.Scene $ ScenePeerListener.keyEvent (Scene.java:2501) в com.sun.javafx.tk.quantum.GlassViewEventHandler $ KeyEventNotification.run (GlassViewEventHandler.java:216) $ в com.sun.javafx.tk.Glassquant KeyEventNotification.run (GlassViewEventHandler.java:148) в java.security.AccessController.doPrivileged (собственный метод) в com.sun.javafx.tk.quantum. GlassViewEventHandler.lambda $ handleKeyEvent $ 353 (GlassViewEventHandler.java:247) по адресу com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock (QuantumToolkit.java:389) по адресу com.sunEvent.java: .java: 246) на com.sun.glass.ui.View.handleKeyEvent (View.java:546) на com.sun.glass.ui.View.notifyKey (View.java:966) на com.sun.glass. ui.win.WinApplication._runLoop (собственный метод) на com.sun.glass.ui.win. WinApplication.lambda $ null $ 148 (WinApplication.java:191) в java.lang.Thread.run (неизвестный источник) - person davidxxx; 26.12.2016