Wildfly: чтение свойств из каталога конфигурации
Я пытаюсь прочитать информацию о развертывании из файла свойств в моей папке конфигурации wildfly. Я пробовал это:
@Singleton
@Startup
public class DeploymentConfiguration {
protected Properties props;
@PostConstruct
public void readConfig() {
props = new Properties();
try {
props.load(getClass().getClassLoader().getResourceAsStream("my.properties"));
} catch (IOException e) {
// ... whatever
}
}
Но, видимо, это не работает, поскольку папка конфигурации больше не находится в пути к классам. Теперь я не могу найти простой способ сделать это. Моим любимым было бы что-то вроде этого:
@InjectProperties("my.properties")
protected Properties props;
Единственное решение, которое я нашел в Интернете, включает в себя создание моего собственного модуля OSGi, но я считаю, что должен быть более простой способ сделать это (один без OSGi!). Может ли кто-нибудь показать мне, как?
Ответы
Ответ 1
Если вы хотите явно прочитать файл из каталога конфигурации (например, $WILDFLY_HOME/standalone/configuration
или domain/configuration
), есть системное свойство с контуром в нем. Просто сделайте System.getProperty("jboss.server.config.dir");
и добавьте к нему имя файла, чтобы получить файл.
Вы бы не прочитали его как ресурс, поэтому...
String fileName = System.getProperty("jboss.server.config.dir") + "/my.properties";
try(FileInputStream fis = new FileInputStream(fileName)) {
properties.load(fis);
}
Затем файл будет загружен для вас.
Кроме того, поскольку WildFly больше не поставляется с поддержкой OSGi, я не знаю, как помочь вам создать модуль OSGi.
Ответ 2
Вот полный пример, используя только CDI, взятый из этого сайта.
-
Создайте и заполните файл свойств внутри папки конфигурации WildFly
$ echo 'docs.dir=/var/documents' >> .standalone/configuration/application.properties
-
Добавить системное свойство в конфигурационный файл WildFly.
$ ./bin/jboss-cli.sh --connect
[[email protected]:9990 /] /system-property=application.properties:add(value=${jboss.server.config.dir}/application.properties)
Это добавит следующее в ваш конфигурационный файл сервера (standalone.xml или domain.xml):
<system-properties>
<property name="application.properties" value="${jboss.server.config.dir}/application.properties"/>
</system-properties>
-
Создайте сеанс singleton bean, который загружает и сохраняет свойства приложения в целом
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
@Singleton
public class PropertyFileResolver {
private Logger logger = Logger.getLogger(PropertyFileResolver.class);
private String properties = new HashMap<>();
@PostConstruct
private void init() throws IOException {
//matches the property name as defined in the system-properties element in WildFly
String propertyFile = System.getProperty("application.properties");
File file = new File(propertyFile);
Properties properties = new Properties();
try {
properties.load(new FileInputStream(file));
} catch (IOException e) {
logger.error("Unable to load properties file", e);
}
HashMap hashMap = new HashMap<>(properties);
this.properties.putAll(hashMap);
}
public String getProperty(String key) {
return properties.get(key);
}
}
-
Создайте квалификатор CDI. Мы будем использовать эту аннотацию для переменных Java, которые мы хотим ввести.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
public @interface ApplicationProperty {
// no default meaning a value is mandatory
@Nonbinding
String name();
}
-
Создайте метод производителя; это генерирует объект, который нужно вставить
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
public class ApplicaitonPropertyProducer {
@Inject
private PropertyFileResolver fileResolver;
@Produces
@ApplicationProperty(name = "")
public String getPropertyAsString(InjectionPoint injectionPoint) {
String propertyName = injectionPoint.getAnnotated().getAnnotation(ApplicationProperty.class).name();
String value = fileResolver.getProperty(propertyName);
if (value == null || propertyName.trim().length() == 0) {
throw new IllegalArgumentException("No property found with name " + value);
}
return value;
}
@Produces
@ApplicationProperty(name="")
public Integer getPropertyAsInteger(InjectionPoint injectionPoint) {
String value = getPropertyAsString(injectionPoint);
return value == null ? null : Integer.valueOf(value);
}
}
-
Наконец, добавьте свойство в один из ваших CDI beans
import javax.ejb.Stateless;
import javax.inject.Inject;
@Stateless
public class MySimpleEJB {
@Inject
@ApplicationProperty(name = "docs.dir")
private String myProperty;
public String getProperty() {
return myProperty;
}
}
Ответ 3
Простейшая вещь, которую вы можете сделать, - запустить standalone.sh
с опцией -P
, ссылающейся на ваш файл свойств (вам нужен URL file:/path/to/my.properties
или поместить файл в $WILDFLY_HOME/bin
).
Затем все свойства из файла будут загружены как системные.
Чтобы внедрить свойства конфигурации в свои классы приложений, просмотрите конфигурацию DeltaSpike, которая поддерживает различные источники свойств, такие как свойства системы, переменные среды, JNDI и скрывает конкретный источник от вашего приложения.
В качестве альтернативы, чтобы избежать установки системных свойств (которые будут глобальными в смысле видимости для всех приложений, развернутых в вашем экземпляре WildFly), вы также можете определить собственный источник свойств для DeltaSpike, читающий файл свойств из любого заданного местоположения, и эти свойства будут локальными для вашего приложения.
Ответ 4
Похоже, проблема, которую вы пытаетесь решить, заключается в управлении разными (но, вероятно, подобными) конфигурационными файлами для запуска вашего приложения в разных средах (например, Production, QA или даже разных клиентах). Если это так, посмотрите Jfig http://jfig.sourceforge.net/. Это избавит вас от необходимости хранить файлы свойств вне вашего пути к классам (но вы все равно можете).
Требуется иерархический подход к файлам конфигурации. Девяносто процентов значений конфигурации, которые не изменяются, могут поддерживаться в базовом файле. Остальные десять процентов (или меньше) могут поддерживаться в их собственном файле конфигурации. Во время выполнения файлы накладываются друг на друга, чтобы обеспечить гибкую управляемую конфигурацию. Например, в среде разработки myhost.config.xml объединяется с dev.config.xml и base.config.xml, чтобы сформировать мою уникальную конфигурацию.
Каждый конфигурационный файл может быть сохранен в управлении версиями, поскольку у них есть уникальные имена. При изменении базовых значений необходимо изменить только базовые файлы, и легко увидеть разницу между версиями. Другим важным преимуществом является то, что изменения в базовом файле конфигурации будут исчерпывающе протестированы перед развертыванием.
Ответ 5
InputStream in = null;
File confDir = new File(System.getProperty("jboss.server.config.dir"));
File fileProp = new File(confDir, "my.properties");
try{
//teste fileProp.exists etc.
in = new FileInputStream(fileProp);
Properties properties = new Properties();
properties.load(in);
//You should throws or handle FileNotFoundException and IOException
}finally{
try{
in.close();
}catch(Exception ignored){
}
}
Ответ 6
Чтобы избежать такого рода проблем, проблема заключается в том, чтобы установить jboss.server.config.dir
в аргументах VM следующим образом:
-Djboss.server.config.dir="[jboss_repository]/server/[default-all-standard-standalone]/conf" –server