Конфигурация Typesafe под OSGi

Библиотеки, использующие Typesafe Config, обычно зависят от одной большой конфигурации, объединенной из /reference.conf файлов в пути к классам.

Например, Spray ожидает найти свои разделы конфигурации в экземпляре Typesafe Config ActorSystem, но они недоступны, если пакет, в котором я создаю ActorSystem, не импортирует пакеты Spray. В моем приложении такого импорта нет, потому что у меня есть специальный пакет, единственной целью которого является публикация ActorSystem как сервиса. Другие пакеты используют это, и некоторые из них зависят от Spray, но не от пакета, который просто экспортирует AS.

Это привело меня к общей проблеме, когда Typesafe Config находит /reference.conf файлов в среде OSGi. Я знаю, что BundleDelegatingClassLoader akka-osgi ищет ресурсы в цепочке зависимостей пакетов, поэтому я подумал, почему бы просто не просмотреть все пакеты в системе, чтобы соответствовать идиологии слияния Typesafe Config?

Как правильно работать с Typesafe Config в OSGi? Я представлю свое общее решение в ответе, но я не эксперт OSGi и хотел бы услышать, если это неправильно и почему, и как лучше всего справиться с слиянием.


person Yuri Geinish    schedule 14.01.2015    source источник


Ответы (1)


Это заставляет Typesafe Config include искать данный ресурс во всех установленных пакетах:

// create Typesafe Config

val myConfig = ConfigFactory.parseFile(
  new File("myconfig.conf"),
  ConfigParseOptions.defaults().setClassLoader(new ClassLoader() {
    override def getResources(name: String): util.Enumeration[URL] = {
      val resources = context.getBundles.flatMap { bundle =>
        val found = JavaConversions.enumerationAsScalaIterator(
          Option(bundle.getResources(name)).getOrElse(Collections.emptyEnumeration())
        )
        found
      }
      JavaConversions.asJavaEnumeration(resources.toIterator)
    }
  })
).resolve()

// create ActorSystem

/* This could've been myconfig.getConfig("myconfig").withOnlyPath("akka") but
 * like I said, Spray expects to find "spray.*" section in the ActorSystem's config.
 */
val factory = OsgiActorSystemFactory(context, myconfig.getConfig("myconfig"))
val as = factory.createActorSystem("blah")

В самой конфигурации я использую:

myconfig {

    // this will include reference.conf from every installed bundle in the container
    include classpath("reference.conf")

    // overrides
    akka.loglevel = INFO
    spray.version = "1.3.2"

    // etc ...
    other.stuff.for.my.app = 1
}

Наличие -Dconfig.trace=loads показывает:

karaf@root()> feature:install myfeature
Loading config from a file: C:\Users\YUUshakov\p\myconfig.conf
Loading config from URL bundleresource://925.fwk875016237/reference.conf from class loader mytest.ConfigActivator$$anon$1@1131e4e4
Loading config from URL bundleresource://931.fwk875016237/reference.conf from class loader mytest.ConfigActivator$$anon$1@1131e4e4
Loading config from URL bundleresource://933.fwk875016237/reference.conf from class loader mytest.ConfigActivator$$anon$1@1131e4e4
Loading config from URL bundleresource://934.fwk875016237/reference.conf from class loader mytest.ConfigActivator$$anon$1@1131e4e4
Loading config from URL bundleresource://946.fwk875016237/reference.conf from class loader mytest.ConfigActivator$$anon$1@1131e4e4

И полученный экземпляр конфигурации получил все ссылочные разделы, такие как myconfig.akka, myconfig.spray и т. д.

person Yuri Geinish    schedule 14.01.2015