From 05197ab17e2190c810b220e1f43440c9bcba4ea1 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 27 Sep 2013 16:15:54 -0400 Subject: [PATCH] Add Java version of the examples --- examples/java/complex-app/build.sbt | 0 .../complex-app/src/main/java/ComplexApp.java | 78 +++++++++++++++++++ .../src/main/resources/complex1.conf | 8 ++ .../src/main/resources/complex2.conf | 13 ++++ examples/java/simple-app/build.sbt | 0 .../simple-app/src/main/java/SimpleApp.java | 27 +++++++ .../src/main/resources/application.conf | 8 ++ examples/java/simple-lib/build.sbt | 0 .../main/java/simplelib/SimpleLibContext.java | 34 ++++++++ .../src/main/resources/reference.conf | 5 ++ .../simple-app/src/main/scala/SimpleApp.scala | 4 +- .../src/main/scala/simplelib/SimpleLib.scala | 5 ++ project/Build.scala | 24 ++++-- 13 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 examples/java/complex-app/build.sbt create mode 100644 examples/java/complex-app/src/main/java/ComplexApp.java create mode 100644 examples/java/complex-app/src/main/resources/complex1.conf create mode 100644 examples/java/complex-app/src/main/resources/complex2.conf create mode 100644 examples/java/simple-app/build.sbt create mode 100644 examples/java/simple-app/src/main/java/SimpleApp.java create mode 100644 examples/java/simple-app/src/main/resources/application.conf create mode 100644 examples/java/simple-lib/build.sbt create mode 100644 examples/java/simple-lib/src/main/java/simplelib/SimpleLibContext.java create mode 100644 examples/java/simple-lib/src/main/resources/reference.conf diff --git a/examples/java/complex-app/build.sbt b/examples/java/complex-app/build.sbt new file mode 100644 index 00000000..e69de29b diff --git a/examples/java/complex-app/src/main/java/ComplexApp.java b/examples/java/complex-app/src/main/java/ComplexApp.java new file mode 100644 index 00000000..447b0908 --- /dev/null +++ b/examples/java/complex-app/src/main/java/ComplexApp.java @@ -0,0 +1,78 @@ +import com.typesafe.config.*; +import simplelib.*; + +class ComplexApp { + + // Simple-lib is a library in this same examples/ directory. + // This method demos usage of that library with the config + // provided. + private static void demoConfigInSimpleLib(Config config) { + SimpleLibContext context = new SimpleLibContext(config); + context.printSetting("simple-lib.foo"); + context.printSetting("simple-lib.hello"); + context.printSetting("simple-lib.whatever"); + } + + public static void main(String[] args) { + // This app is "complex" because we load multiple separate app + // configs into a single JVM and we have a separately-configurable + // context for simple lib. + + // system property overrides work, but the properties must be set + // before the config lib is used (config lib will not notice changes + // once it loads the properties) + System.setProperty("simple-lib.whatever", "This value comes from a system property"); + + // ///////// + + // "config1" is just an example of using a file other than + // application.conf + Config config1 = ConfigFactory.load("complex1"); + + // use the config ourselves + System.out.println("config1, complex-app.something=" + + config1.getString("complex-app.something")); + + // use the config for a library + demoConfigInSimpleLib(config1); + + // //////// + + // "config2" shows how to configure a library with a custom settings + // subtree + Config config2 = ConfigFactory.load("complex2"); + + // use the config ourselves + System.out.println("config2, complex-app.something=" + + config2.getString("complex-app.something")); + + // pull out complex-app.simple-lib-context and move it to + // the toplevel, creating a new config suitable for our + // SimpleLibContext. + // The defaultOverrides() have to be put back on top of the stack so + // they still override any simple-lib settings. + // We fall back to config2 again to be sure we get simple-lib's + // reference.conf plus any other settings we've set. You could + // also just fall back to ConfigFactory.referenceConfig() if + // you don't want complex2.conf settings outside of + // complex-app.simple-lib-context to be used. + Config simpleLibConfig2 = ConfigFactory.defaultOverrides() + .withFallback(config2.getConfig("complex-app.simple-lib-context")) + .withFallback(config2); + + demoConfigInSimpleLib(simpleLibConfig2); + + // //////// + + // Here's an illustration that simple-lib will get upset if we pass it + // a bad config. In this case, we'll fail to merge the reference + // config in to complex-app.simple-lib-context, so simple-lib will + // point out that some settings are missing. + try { + demoConfigInSimpleLib(config2.getConfig("complex-app.simple-lib-context")); + } catch (ConfigException.ValidationFailed e) { + System.out.println("when we passed a bad config to simple-lib, it said: " + + e.getMessage()); + } + } +} diff --git a/examples/java/complex-app/src/main/resources/complex1.conf b/examples/java/complex-app/src/main/resources/complex1.conf new file mode 100644 index 00000000..19fb190c --- /dev/null +++ b/examples/java/complex-app/src/main/resources/complex1.conf @@ -0,0 +1,8 @@ +# these are our own config values defined by the app +complex-app { + something="This value comes from complex-app's complex1.conf" +} + +# Here we override some values used by a library +simple-lib.foo="This value comes from complex-app's complex1.conf" +simple-lib.whatever = "This value comes from complex-app's complex1.conf" \ No newline at end of file diff --git a/examples/java/complex-app/src/main/resources/complex2.conf b/examples/java/complex-app/src/main/resources/complex2.conf new file mode 100644 index 00000000..53758b13 --- /dev/null +++ b/examples/java/complex-app/src/main/resources/complex2.conf @@ -0,0 +1,13 @@ +complex-app { + something="This value comes from complex-app's complex2.conf" + + # here we want a simple-lib-context unique to our app + # which can be custom-configured. In code, we have to + # pull out this subtree and pass it to simple-lib. + simple-lib-context = { + simple-lib { + foo="This value comes from complex-app's complex2.conf in its custom simple-lib-context" + whatever = "This value comes from complex-app's complex2.conf in its custom simple-lib-context" + } + } +} diff --git a/examples/java/simple-app/build.sbt b/examples/java/simple-app/build.sbt new file mode 100644 index 00000000..e69de29b diff --git a/examples/java/simple-app/src/main/java/SimpleApp.java b/examples/java/simple-app/src/main/java/SimpleApp.java new file mode 100644 index 00000000..bc4a148e --- /dev/null +++ b/examples/java/simple-app/src/main/java/SimpleApp.java @@ -0,0 +1,27 @@ +import com.typesafe.config.*; +import simplelib.*; + +class SimpleApp { + public static void main(String[] args) { + // example of how system properties override; note this + // must be set before the config lib is used + System.setProperty("simple-lib.whatever", "This value comes from a system property"); + + // Load our own config values from the default location, + // application.conf + Config conf = ConfigFactory.load(); + System.out.println("The answer is: " + conf.getString("simple-app.answer")); + + // In this simple app, we're allowing SimpleLibContext() to + // use the default config in application.conf ; this is exactly + // the same as passing in ConfigFactory.load() here, so we could + // also write "new SimpleLibContext(conf)" and it would be the same. + // (simple-lib is a library in this same examples/ directory). + // The point is that SimpleLibContext defaults to ConfigFactory.load() + // but also allows us to pass in our own Config. + SimpleLibContext context = new SimpleLibContext(); + context.printSetting("simple-lib.foo"); + context.printSetting("simple-lib.hello"); + context.printSetting("simple-lib.whatever"); + } +} diff --git a/examples/java/simple-app/src/main/resources/application.conf b/examples/java/simple-app/src/main/resources/application.conf new file mode 100644 index 00000000..c8957d5b --- /dev/null +++ b/examples/java/simple-app/src/main/resources/application.conf @@ -0,0 +1,8 @@ +# these are our own config values defined by the app +simple-app { + answer=42 +} + +# Here we override some values used by a library +simple-lib.foo="This value comes from simple-app's application.conf" +simple-lib.whatever = "This value comes from simple-app's application.conf" diff --git a/examples/java/simple-lib/build.sbt b/examples/java/simple-lib/build.sbt new file mode 100644 index 00000000..e69de29b diff --git a/examples/java/simple-lib/src/main/java/simplelib/SimpleLibContext.java b/examples/java/simple-lib/src/main/java/simplelib/SimpleLibContext.java new file mode 100644 index 00000000..690fb16f --- /dev/null +++ b/examples/java/simple-lib/src/main/java/simplelib/SimpleLibContext.java @@ -0,0 +1,34 @@ +package simplelib; + +import com.typesafe.config.*; + +// Whenever you write a library, allow people to supply a Config but +// also default to ConfigFactory.load if they don't supply one. +// Libraries generally have some kind of Context or other object +// where it's convenient to place the configuration. + +public class SimpleLibContext { + private Config config; + + // we have a constructor allowing the app to provide a custom Config + public SimpleLibContext(Config config) { + this.config = config; + // This verifies that the Config is sane and has our + // reference config. Importantly, we specify the "simple-lib" + // path so we only validate settings that belong to this + // library. Otherwise, we might throw mistaken errors about + // settings we know nothing about. + config.checkValid(ConfigFactory.defaultReference(), "simple-lib"); + } + + // This uses the standard default Config, if none is provided, + // which simplifies apps willing to use the defaults + public SimpleLibContext() { + this(ConfigFactory.load()); + } + + // this is the amazing functionality provided by simple-lib + public void printSetting(String path) { + System.out.println("The setting '" + path + "' is: " + config.getString(path)); + } +} diff --git a/examples/java/simple-lib/src/main/resources/reference.conf b/examples/java/simple-lib/src/main/resources/reference.conf new file mode 100644 index 00000000..7a1ab9e8 --- /dev/null +++ b/examples/java/simple-lib/src/main/resources/reference.conf @@ -0,0 +1,5 @@ +simple-lib { + foo = "This value comes from simple-lib's reference.conf" + hello = "This value comes from simple-lib's reference.conf" + whatever = "This value comes from simple-lib's reference.conf" +} diff --git a/examples/scala/simple-app/src/main/scala/SimpleApp.scala b/examples/scala/simple-app/src/main/scala/SimpleApp.scala index c9b27a72..9e0c02a0 100644 --- a/examples/scala/simple-app/src/main/scala/SimpleApp.scala +++ b/examples/scala/simple-app/src/main/scala/SimpleApp.scala @@ -14,7 +14,9 @@ object SimpleApp extends App { // use the default config in application.conf ; this is exactly // the same as passing in ConfigFactory.load() here, so we could // also write "new SimpleLibContext(conf)" and it would be the same. - // (simple-lib is a library in this same examples/ directory) + // (simple-lib is a library in this same examples/ directory). + // The point is that SimpleLibContext defaults to ConfigFactory.load() + // but also allows us to pass in our own Config. val context = new SimpleLibContext() context.printSetting("simple-lib.foo") context.printSetting("simple-lib.hello") diff --git a/examples/scala/simple-lib/src/main/scala/simplelib/SimpleLib.scala b/examples/scala/simple-lib/src/main/scala/simplelib/SimpleLib.scala index 926eed91..06b03c0a 100644 --- a/examples/scala/simple-lib/src/main/scala/simplelib/SimpleLib.scala +++ b/examples/scala/simple-lib/src/main/scala/simplelib/SimpleLib.scala @@ -2,6 +2,11 @@ package simplelib import com.typesafe.config._ +// Whenever you write a library, allow people to supply a Config but +// also default to ConfigFactory.load if they don't supply one. +// Libraries generally have some kind of Context or other object +// where it's convenient to place the configuration. + // we have a constructor allowing the app to provide a custom Config class SimpleLibContext(config: Config) { diff --git a/project/Build.scala b/project/Build.scala index a9260c26..c02e7246 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -26,7 +26,9 @@ object ConfigBuild extends Build { lazy val root = Project(id = "root", base = file("."), - settings = Project.defaultSettings ++ unpublished) aggregate(testLib, configLib, simpleLibScala, simpleAppScala, complexAppScala) + settings = Project.defaultSettings ++ unpublished) aggregate(testLib, configLib, + simpleLibScala, simpleAppScala, complexAppScala, + simpleLibJava, simpleAppJava, complexAppJava) lazy val configLib = Project(id = "config", base = file("config"), @@ -40,21 +42,33 @@ object ConfigBuild extends Build { artifact in (Compile, packageBin) ~= { _.copy(`type` = "bundle") } )) dependsOn(testLib % "test->test") - lazy val testLib = Project(id = "test-lib", + lazy val testLib = Project(id = "config-test-lib", base = file("test-lib"), settings = Project.defaultSettings ++ unpublished) - lazy val simpleLibScala = Project(id = "simple-lib", + lazy val simpleLibScala = Project(id = "config-simple-lib-scala", base = file("examples/scala/simple-lib"), settings = Project.defaultSettings ++ unpublished) dependsOn(configLib) - lazy val simpleAppScala = Project(id = "simple-app", + lazy val simpleAppScala = Project(id = "config-simple-app-scala", base = file("examples/scala/simple-app"), settings = Project.defaultSettings ++ unpublished) dependsOn(simpleLibScala) - lazy val complexAppScala = Project(id = "complex-app", + lazy val complexAppScala = Project(id = "config-complex-app-scala", base = file("examples/scala/complex-app"), settings = Project.defaultSettings ++ unpublished) dependsOn(simpleLibScala) + + lazy val simpleLibJava = Project(id = "config-simple-lib-java", + base = file("examples/java/simple-lib"), + settings = Project.defaultSettings ++ unpublished) dependsOn(configLib) + + lazy val simpleAppJava = Project(id = "config-simple-app-java", + base = file("examples/java/simple-app"), + settings = Project.defaultSettings ++ unpublished) dependsOn(simpleLibJava) + + lazy val complexAppJava = Project(id = "config-complex-app-java", + base = file("examples/java/complex-app"), + settings = Project.defaultSettings ++ unpublished) dependsOn(simpleLibJava) } // from https://raw.github.com/paulp/scala-improving/master/project/PublishToSonatype.scala