Add examples for polymorphic type handling

Example implementations exist for both Java and Scala.
This commit is contained in:
Nemanja Zbiljić 2017-10-15 16:18:58 +02:00
parent 252fda11a7
commit 465ca3bece
13 changed files with 241 additions and 2 deletions

View File

@ -38,8 +38,8 @@ lazy val root = (project in file("."))
)
.aggregate(
testLib, configLib,
simpleLibScala, simpleAppScala, complexAppScala,
simpleLibJava, simpleAppJava, complexAppJava
simpleLibScala, simpleAppScala, complexAppScala, polymorphicAppScala,
simpleLibJava, simpleAppJava, complexAppJava, polymorphicAppJava
)
lazy val configLib = Project("config", file("config"))
@ -60,10 +60,12 @@ lazy val testLib = proj("config-test-lib", file("test-lib"))
lazy val simpleLibScala = proj("config-simple-lib-scala", file("examples/scala/simple-lib")) dependsOn configLib
lazy val simpleAppScala = proj("config-simple-app-scala", file("examples/scala/simple-app")) dependsOn simpleLibScala
lazy val complexAppScala = proj("config-complex-app-scala", file("examples/scala/complex-app")) dependsOn simpleLibScala
lazy val polymorphicAppScala = proj("config-polymorphic-app-scala", file("examples/scala/polymorphic-app")) dependsOn configLib
lazy val simpleLibJava = proj("config-simple-lib-java", file("examples/java/simple-lib")) dependsOn configLib
lazy val simpleAppJava = proj("config-simple-app-java", file("examples/java/simple-app")) dependsOn simpleLibJava
lazy val complexAppJava = proj("config-complex-app-java", file("examples/java/complex-app")) dependsOn simpleLibJava
lazy val polymorphicAppJava = proj("config-polymorphic-app-java", file("examples/java/polymorphic-app")) dependsOn configLib
useGpg := true

View File

@ -0,0 +1,52 @@
import com.typesafe.config.Config;
import com.typesafe.config.ConfigBeanFactory;
import com.typesafe.config.ConfigFactory;
import logging.Appender;
import java.util.List;
class PolymorphicApp {
public static class LoggerConfiguration {
private String level;
private List<Appender> appenders;
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public List<Appender> getAppenders() {
return appenders;
}
public void setAppenders(List<Appender> appenders) {
this.appenders = appenders;
}
}
public static void main(String[] args) {
// This app is "polymorphic" because we have one interface type with
// multiple implementations that are deserialized to correct type based
// on the type defined in configuration.
// Java version showcases two types of defining subtypes and naming
// them: defining one subtype in the main interface, and one in the
// 'META-INF/services' directory.
Config config = ConfigFactory.load("polymorphic");
LoggerConfiguration loggerConfiguration =
ConfigBeanFactory.create(config.getConfig("polymorphic-app.logger"), LoggerConfiguration.class);
String demoMessage = config.getString("polymorphic-app.demo-message");
for (Appender appender : loggerConfiguration.getAppenders()) {
appender.log(demoMessage);
}
}
}

View File

@ -0,0 +1,14 @@
package logging;
import com.typesafe.config.ConfigSubTypes;
import com.typesafe.config.ConfigSubTypes.Type;
import com.typesafe.config.ConfigTypeInfo;
@ConfigTypeInfo
@ConfigSubTypes({
@Type(value = ConsoleAppender.class, name = "console")
})
public interface Appender {
void log(String event);
}

View File

@ -0,0 +1,20 @@
package logging;
public class ConsoleAppender implements Appender {
private String target;
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
@Override
public void log(String event) {
System.out.printf("Logging to '%s' using console logger: %s\n",
target, event);
}
}

View File

@ -0,0 +1,41 @@
package logging;
import com.typesafe.config.ConfigTypeName;
@ConfigTypeName("syslog")
public class SyslogAppender implements Appender {
private String host;
private int port;
private String facility;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getFacility() {
return facility;
}
public void setFacility(String facility) {
this.facility = facility;
}
@Override
public void log(String event) {
System.out.printf("Logging to '%s/%d/%s' using syslog logger: %s\n",
host, port, facility, event);
}
}

View File

@ -0,0 +1 @@
logging.SyslogAppender

View File

@ -0,0 +1,18 @@
polymorphic-app {
logger={
level="INFO"
appenders=[
{
type="console"
target="stderr"
}
{
type="syslog"
host="localhost"
port=514
facility="local0"
}
]
}
demo-message="hello from java"
}

View File

@ -0,0 +1,2 @@
logging.ConsoleAppender
logging.SyslogAppender

View File

@ -0,0 +1,18 @@
polymorphic-app {
logger={
level="INFO"
appenders=[
{
type="console"
target="stderr"
}
{
type="syslog"
host="localhost"
port=514
facility="local0"
}
]
}
demo-message="hello from scala"
}

View File

@ -0,0 +1,30 @@
import com.typesafe.config._
import logging.Appender
import scala.beans.BeanProperty
import scala.collection.JavaConversions._
object PolymorphicApp extends App {
class LoggerConfiguration {
@BeanProperty var level: String = _
@BeanProperty var appenders: java.util.List[Appender] = _
}
// This app is "polymorphic" because we have one interface type with
// multiple implementations that are deserialized to correct type based
// on the type defined in configuration.
// Scala version relies on 'META-INF/services' directory for subtype
// discovery due to the fact that annotations have some Java specific
// elements.
val config = ConfigFactory.load("polymorphic")
val loggerConfiguration =
ConfigBeanFactory.create(config.getConfig("polymorphic-app.logger"), classOf[LoggerConfiguration])
val demoMessage = config.getString("polymorphic-app.demo-message")
loggerConfiguration.getAppenders.toList.foreach(a => a.log(demoMessage))
}

View File

@ -0,0 +1,9 @@
package logging
import com.typesafe.config.ConfigTypeInfo
@ConfigTypeInfo
trait Appender {
def log(event: String)
}

View File

@ -0,0 +1,15 @@
package logging
import com.typesafe.config.ConfigTypeName
import scala.beans.BeanProperty
@ConfigTypeName("console")
class ConsoleAppender extends Appender {
@BeanProperty var target: String = _
override def log(event: String) {
printf("Logging to '%s' using console logger: %s\n", target, event)
}
}

View File

@ -0,0 +1,17 @@
package logging
import com.typesafe.config.ConfigTypeName
import scala.beans.BeanProperty
@ConfigTypeName("syslog")
class SyslogAppender extends Appender {
@BeanProperty var host: String = _
@BeanProperty var port: Int = _
@BeanProperty var facility: String = _
override def log(event: String) {
printf("Logging to '%s/%d/%s' using syslog logger: %s\n", host, port, facility, event)
}
}