From 7c66ab41705d5ca38cbb84afbca4337bc4e9007a Mon Sep 17 00:00:00 2001 From: Peter Szanto Date: Wed, 26 Aug 2015 00:49:06 +0200 Subject: [PATCH 1/3] Added support for Java Based Config --- README.md | 11 +- example/java-config/config.yaml | 8 + example/java-config/pom.xml | 160 ++++++++++++++++++ .../dropwizard/spring/GreetingService.java | 12 ++ .../dropwizard/spring/HelloResource.java | 30 ++++ .../dropwizard/spring/MessageBean.java | 17 ++ .../dropwizard/spring/config/Config.java | 17 ++ .../java-config/src/main/resources/banner.txt | 6 + example/{ => xml}/config.yaml | 0 example/{ => xml}/pom.xml | 2 +- .../dropwizard/spring/HelloResource.java | 0 .../{ => xml}/src/main/resources/banner.txt | 0 .../src/main/resources/dropwizard-service.xml | 0 .../ApplicationContextTypeDeserializer.java | 34 ++++ .../spring/SpringConfiguration.java | 44 ++++- .../dropwizard/spring/SpringService.java | 79 +++++++-- 16 files changed, 395 insertions(+), 25 deletions(-) create mode 100644 example/java-config/config.yaml create mode 100644 example/java-config/pom.xml create mode 100644 example/java-config/src/main/java/com/hmsonline/dropwizard/spring/GreetingService.java create mode 100644 example/java-config/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java create mode 100644 example/java-config/src/main/java/com/hmsonline/dropwizard/spring/MessageBean.java create mode 100644 example/java-config/src/main/java/com/hmsonline/dropwizard/spring/config/Config.java create mode 100644 example/java-config/src/main/resources/banner.txt rename example/{ => xml}/config.yaml (100%) rename example/{ => xml}/pom.xml (99%) rename example/{ => xml}/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java (100%) rename example/{ => xml}/src/main/resources/banner.txt (100%) rename example/{ => xml}/src/main/resources/dropwizard-service.xml (100%) create mode 100644 src/main/java/com/hmsonline/dropwizard/spring/ApplicationContextTypeDeserializer.java diff --git a/README.md b/README.md index 25e89a1..13a208a 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,10 @@ dropwizard-spring With **dropwizard-spring** you configure your dropwizard components (resources, healthchecks, jersey providers, managed objects, servlets, filters, etc.) entirely with spring, and tell the spring service which components to enable using a simple YAML configuration. -With **dropwizard-spring** it is not necessary to subclass `com.yammer.dropwizard.Service`, instead you reference the provided -`com.hmsonline.dropwizard.spring.SpringService` class as your service class. +With **dropwizard-spring** it is not necessary to subclass `io.dropwizard.Application`, instead you reference the provided +`com.hmsonline.dropwizard.spring.SpringService` class as your application class. + +With **dropwizard-spring** you can use XML or annotation based (Java Based Config) spring bean definitions ## Maven Configuration @@ -107,6 +109,11 @@ This is required to have maven build a "fat," executable jar file. # The location of one or more beans.xml files configLocations: - conf/dropwizard-beans.xml + + # Package to look for JavaConfig classes annotated with @Configuration + #Set either javaConfigBasePackages or configLocations + javaConfigBasePackages: + - com.hmsonline.dropwizard.spring.config # Servlet Filter # List of FilterConfiguration diff --git a/example/java-config/config.yaml b/example/java-config/config.yaml new file mode 100644 index 0000000..12177c3 --- /dev/null +++ b/example/java-config/config.yaml @@ -0,0 +1,8 @@ +spring: + appContextType: app + + javaConfigBasePackages: + - com.hmsonline.dropwizard.spring.config + + resources: + - helloResource \ No newline at end of file diff --git a/example/java-config/pom.xml b/example/java-config/pom.xml new file mode 100644 index 0000000..5dae578 --- /dev/null +++ b/example/java-config/pom.xml @@ -0,0 +1,160 @@ + + + + 4.0.0 + + 3.0.0 + + + com.hmsonline + dropwizard-spring-javaconfig-example + 0.6.2-SNAPSHOT + jar + + Dropwizard-Spring Java Config Example + + + UTF-8 + UTF-8 + com.hmsonline.dropwizard.spring.SpringService + + + + + com.hmsonline + dropwizard-spring + ${project.version} + + + junit + junit + 4.10 + test + + + + + + + maven-shade-plugin + 1.7 + + true + + + ${mainClass} + + + + META-INF/spring.handlers + + + META-INF/spring.schemas + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + + maven-jar-plugin + 2.4 + + + + true + ${mainClass} + + + + + + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + maven-source-plugin + 2.1.2 + + + attach-sources + + jar + + + + + + maven-javadoc-plugin + 2.8.1 + + + attach-javadocs + + jar + + + + + + maven-deploy-plugin + 2.7 + + + org.apache.maven.wagon + wagon-ssh + 2.2 + + + + + maven-site-plugin + 3.0 + + + + maven-project-info-reports-plugin + 2.4 + + false + false + + + + maven-javadoc-plugin + 2.8.1 + + + + + + + + + diff --git a/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/GreetingService.java b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/GreetingService.java new file mode 100644 index 0000000..0b115fd --- /dev/null +++ b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/GreetingService.java @@ -0,0 +1,12 @@ +package com.hmsonline.dropwizard.spring; + +import org.springframework.stereotype.Service; + +@Service +public class GreetingService { + + public String greet(String name) { + return "Hi " + name; + } + +} diff --git a/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java new file mode 100644 index 0000000..44d3243 --- /dev/null +++ b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java @@ -0,0 +1,30 @@ +// Copyright (c) 2012 Health Market Science, Inc. + +package com.hmsonline.dropwizard.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Component +@Path("/hello") +public class HelloResource { + + @Autowired + private MessageBean messageBean; + + @Autowired + private GreetingService greetingService; + + @GET + @Path("/world") + @Produces(MediaType.APPLICATION_JSON) + public Object hello(){ + return greetingService.greet(messageBean.getMessage()); + } + +} diff --git a/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/MessageBean.java b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/MessageBean.java new file mode 100644 index 0000000..75726cc --- /dev/null +++ b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/MessageBean.java @@ -0,0 +1,17 @@ +package com.hmsonline.dropwizard.spring; + +import org.springframework.stereotype.Component; + +public class MessageBean { + + private String message; + + public MessageBean(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + +} diff --git a/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/config/Config.java b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/config/Config.java new file mode 100644 index 0000000..52d03d4 --- /dev/null +++ b/example/java-config/src/main/java/com/hmsonline/dropwizard/spring/config/Config.java @@ -0,0 +1,17 @@ +package com.hmsonline.dropwizard.spring.config; + +import com.hmsonline.dropwizard.spring.MessageBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.hmsonline.dropwizard.spring") +public class Config { + + @Bean + MessageBean createMessageBean() { + return new MessageBean("Java Config"); + } + +} diff --git a/example/java-config/src/main/resources/banner.txt b/example/java-config/src/main/resources/banner.txt new file mode 100644 index 0000000..1b6bb83 --- /dev/null +++ b/example/java-config/src/main/resources/banner.txt @@ -0,0 +1,6 @@ +================================================================================ + + dropwizard-javaconfig-spring-example + +================================================================================ + diff --git a/example/config.yaml b/example/xml/config.yaml similarity index 100% rename from example/config.yaml rename to example/xml/config.yaml diff --git a/example/pom.xml b/example/xml/pom.xml similarity index 99% rename from example/pom.xml rename to example/xml/pom.xml index a0c84e7..96816eb 100644 --- a/example/pom.xml +++ b/example/xml/pom.xml @@ -9,7 +9,7 @@ com.hmsonline dropwizard-spring-example - 0.2.1-SNAPSHOT + 0.6.2-SNAPSHOT jar Dropwizard-Spring Example diff --git a/example/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java b/example/xml/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java similarity index 100% rename from example/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java rename to example/xml/src/main/java/com/hmsonline/dropwizard/spring/HelloResource.java diff --git a/example/src/main/resources/banner.txt b/example/xml/src/main/resources/banner.txt similarity index 100% rename from example/src/main/resources/banner.txt rename to example/xml/src/main/resources/banner.txt diff --git a/example/src/main/resources/dropwizard-service.xml b/example/xml/src/main/resources/dropwizard-service.xml similarity index 100% rename from example/src/main/resources/dropwizard-service.xml rename to example/xml/src/main/resources/dropwizard-service.xml diff --git a/src/main/java/com/hmsonline/dropwizard/spring/ApplicationContextTypeDeserializer.java b/src/main/java/com/hmsonline/dropwizard/spring/ApplicationContextTypeDeserializer.java new file mode 100644 index 0000000..40c3b7c --- /dev/null +++ b/src/main/java/com/hmsonline/dropwizard/spring/ApplicationContextTypeDeserializer.java @@ -0,0 +1,34 @@ +package com.hmsonline.dropwizard.spring; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; + +import java.io.IOException; +import java.text.MessageFormat; + +public final class ApplicationContextTypeDeserializer extends JsonDeserializer { + + @Override + public SpringConfiguration.ApplicationContextType deserialize(final JsonParser parser, final DeserializationContext context) throws IOException, JsonProcessingException { + final String jsonValue = parser.getText(); + + for (SpringConfiguration.ApplicationContextType applicationContextType : SpringConfiguration.ApplicationContextType.values()) { + if (applicationContextType.getName().equals(jsonValue)) { + return applicationContextType; + } + } + + throw new JsonMappingException( + MessageFormat.format( + "Configuration Error: appContextType must be either \"{0}\" or \"{1}\"", + SpringConfiguration.ApplicationContextType.WEB_APPLICATION_CONTEXT.getName(), + SpringConfiguration.ApplicationContextType.APPLICATION_CONTEXT.getName() + ) + ); + + } + +} diff --git a/src/main/java/com/hmsonline/dropwizard/spring/SpringConfiguration.java b/src/main/java/com/hmsonline/dropwizard/spring/SpringConfiguration.java index 2d9a542..d52ea31 100644 --- a/src/main/java/com/hmsonline/dropwizard/spring/SpringConfiguration.java +++ b/src/main/java/com/hmsonline/dropwizard/spring/SpringConfiguration.java @@ -2,35 +2,61 @@ package com.hmsonline.dropwizard.spring; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.hmsonline.dropwizard.spring.web.FilterConfiguration; import com.hmsonline.dropwizard.spring.web.ServletConfiguration; import io.dropwizard.Configuration; import org.hibernate.validator.constraints.NotEmpty; +import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; public class SpringConfiguration extends Configuration { - public static final String WEB_APPLICATION_CONTEXT = "web"; - public static final String APPLICATION_CONTEXT = "app"; + public enum ApplicationContextType { + WEB_APPLICATION_CONTEXT("web"),APPLICATION_CONTEXT("app"); + + private String name; + + ApplicationContextType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public static final String CLASSPATH_CONFIG = "classpath"; public static final String FILE_CONFIG = "file"; @NotEmpty @JsonProperty - private String appContextType; + @JsonDeserialize(using = ApplicationContextTypeDeserializer.class) + private ApplicationContextType appContextType; @NotEmpty @JsonProperty private String configLocationsType; - @NotEmpty @JsonProperty private List configLocations; + @JsonProperty + private List javaConfigBasePackages; + @NotEmpty @JsonProperty private List resources; @@ -63,7 +89,7 @@ public class SpringConfiguration extends Configuration { @JsonProperty private Map servlets; - public String getAppContextType() { + public ApplicationContextType getAppContextType() { return appContextType; } @@ -126,4 +152,12 @@ public String getConfigLocationsType() { public void setConfigLocationsType(String configLocationsType) { this.configLocationsType = configLocationsType; } + + public List getJavaConfigBasePackages() { + return javaConfigBasePackages; + } + + public void setJavaConfigBasePackages(List javaConfigBasePackages) { + this.javaConfigBasePackages = javaConfigBasePackages; + } } diff --git a/src/main/java/com/hmsonline/dropwizard/spring/SpringService.java b/src/main/java/com/hmsonline/dropwizard/spring/SpringService.java index 42e4366..719399a 100644 --- a/src/main/java/com/hmsonline/dropwizard/spring/SpringService.java +++ b/src/main/java/com/hmsonline/dropwizard/spring/SpringService.java @@ -22,13 +22,17 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.Servlet; +import static com.hmsonline.dropwizard.spring.SpringConfiguration.ApplicationContextType.WEB_APPLICATION_CONTEXT; + public class SpringService extends Application { private static final Logger LOG = LoggerFactory.getLogger(SpringService.class); @@ -242,33 +246,74 @@ private ApplicationContext initSpringParent() { } private ApplicationContext initSpring(SpringConfiguration config, ApplicationContext parent) { + + if (config.getJavaConfigBasePackages() != null && config.getJavaConfigBasePackages().size() > 0) { + return initJavaConfigSpring(config, parent); + } + + if (config.getConfigLocations() != null && config.getConfigLocations().size() > 0) { + return initXmlSpring(parent, config); + + } + + throw new IllegalArgumentException("Configuration Error: You must specify either configLocation or javaConfigBasePackages"); + + } + + private ApplicationContext initXmlSpring(ApplicationContext parent, SpringConfiguration config) { + ApplicationContext appCtx = null; - // Get Application Context Type - String ctxType = config.getAppContextType(); // Get Config Location Type. String cfgLocationType = config.getConfigLocationsType(); - String[] configLocations = config.getConfigLocations().toArray(new String[config.getConfigLocations().size()]); - if (SpringConfiguration.WEB_APPLICATION_CONTEXT.equals(ctxType)) { - // Create Web Application Context. - appCtx = new XmlRestWebApplicationContext(configLocations, cfgLocationType, true, parent); + String[] configLocations = config.getConfigLocations().toArray(new String[config.getConfigLocations().size()]); - } else if (SpringConfiguration.APPLICATION_CONTEXT.equals(ctxType)) { + switch (config.getAppContextType()) { + + case WEB_APPLICATION_CONTEXT: + // Create Web Application Context. + appCtx = new XmlRestWebApplicationContext(configLocations, cfgLocationType, true, parent); + break; + + case APPLICATION_CONTEXT: + // Create Application Context. + if (SpringConfiguration.FILE_CONFIG.equals(cfgLocationType)) { + appCtx = new FileSystemXmlApplicationContext(configLocations, true, parent); + } else if (SpringConfiguration.CLASSPATH_CONFIG.equals(cfgLocationType)) { + appCtx = new ClassPathXmlApplicationContext(configLocations, true, parent); + } else { + throw new IllegalArgumentException(MessageFormat.format("Configuration Error: configLocationsType must be either \"{0}\" or \"{1}\"", SpringConfiguration.FILE_CONFIG, SpringConfiguration.CLASSPATH_CONFIG)); + } - // Create Application Context. - if (SpringConfiguration.FILE_CONFIG.equals(cfgLocationType)) { - appCtx = new FileSystemXmlApplicationContext(configLocations, true, parent); - } else if (SpringConfiguration.CLASSPATH_CONFIG.equals(cfgLocationType)) { - appCtx = new ClassPathXmlApplicationContext(configLocations, true, parent); - } else { - throw new IllegalArgumentException(MessageFormat.format("Configuration Error: configLocationsType must be either \"{0}\" or \"{1}\"", SpringConfiguration.FILE_CONFIG, SpringConfiguration.CLASSPATH_CONFIG)); - } - } else { - throw new IllegalArgumentException(MessageFormat.format("Configuration Error: appContextType must be either \"{0}\" or \"{1}\"", SpringConfiguration.WEB_APPLICATION_CONTEXT, SpringConfiguration.APPLICATION_CONTEXT)); } + + return appCtx; } + private ApplicationContext initJavaConfigSpring(SpringConfiguration config, ApplicationContext parent) { + String[] javaConfigBasePackages = config.getJavaConfigBasePackages().toArray(new String[config.getJavaConfigBasePackages().size()]); + + switch (config.getAppContextType()) { + + case WEB_APPLICATION_CONTEXT: + AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext(); + annotationConfigWebApplicationContext.scan(javaConfigBasePackages); + annotationConfigWebApplicationContext.setParent(parent); + annotationConfigWebApplicationContext.refresh(); + return annotationConfigWebApplicationContext; + + case APPLICATION_CONTEXT: + AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(javaConfigBasePackages); + annotationConfigApplicationContext.setParent(parent); + return annotationConfigApplicationContext; + + } + + throw new RuntimeException("This should never happen"); + + } + private void logNoSuchBeanDefinitionException(NoSuchBeanDefinitionException nsbde) { if (LOG.isWarnEnabled()) { LOG.warn("Skipping missing Spring bean: ", nsbde); From ae87a293e27b19ab4cca27e022ba96df42b1dc10 Mon Sep 17 00:00:00 2001 From: Peter Szanto Date: Wed, 26 Aug 2015 00:53:11 +0200 Subject: [PATCH 2/3] fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 13a208a..b78ef05 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,9 @@ This is required to have maven build a "fat," executable jar file. - conf/dropwizard-beans.xml # Package to look for JavaConfig classes annotated with @Configuration - #Set either javaConfigBasePackages or configLocations + # Set either javaConfigBasePackages or configLocations javaConfigBasePackages: - - com.hmsonline.dropwizard.spring.config + - com.yourpackage.spring.config # Servlet Filter # List of FilterConfiguration From 8cb72f56bdda6a5561bf6c5d7eb95008d4efbb86 Mon Sep 17 00:00:00 2001 From: Peter Szanto Date: Wed, 26 Aug 2015 00:56:05 +0200 Subject: [PATCH 3/3] updating readme.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b78ef05..6b778e7 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ With **dropwizard-spring** it is not necessary to subclass `io.dropwizard.Applic With **dropwizard-spring** you can use XML or annotation based (Java Based Config) spring bean definitions +To see **dropwizard-spring** in action look into the example folder of this project ## Maven Configuration