Successfully reported this slideshow.
Your SlideShare is downloading. ×

Greach 2019 - Creating Micronaut Configurations

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 30 Ad

Greach 2019 - Creating Micronaut Configurations

Download to read offline

Micronaut provides out-of-the-box integrations with a lot of tools and third-party libraries: Consul, Eureka, Hibernate, Kafka, Mongo, Micrometer, Zipkin, Hystrix, Swagger,... But sometimes this is not enough and you need to integrate with a new one.

In this talk, we will discuss the different options that we have to create a new configuration for Micronaut: bean factories, conditional beans, configuration properties,... and you will learn how to make the most out of it.

Micronaut provides out-of-the-box integrations with a lot of tools and third-party libraries: Consul, Eureka, Hibernate, Kafka, Mongo, Micrometer, Zipkin, Hystrix, Swagger,... But sometimes this is not enough and you need to integrate with a new one.

In this talk, we will discuss the different options that we have to create a new configuration for Micronaut: bean factories, conditional beans, configuration properties,... and you will learn how to make the most out of it.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to Greach 2019 - Creating Micronaut Configurations (20)

Advertisement

More from Iván López Martín (20)

Recently uploaded (20)

Advertisement

Greach 2019 - Creating Micronaut Configurations

  1. 1. Creating Micronaut Configurations Iván Lopez - @ilopmar
  2. 2. About me... ➢ Iván Lopez Martín - @ilopmar ➢ Java/Groovy developer Grails & Micronaut teams at OCI ➢ @MadridGUG coordinator https://madridgug.com ➢ Greach ex-organizer https://greachconf.com ➢ Speaker: Devoxx, GeeCon, Codemotion, ConFoo, JavaCro, RigaDevDays, SpringOne 2GX,...
  3. 3. What is a configuration?
  4. 4. Micronaut Features (configurations) annotation-api aws-api-gateway aws-api-gateway-graal cassandra config-consul discovery-consul discovery-eureka file-watch flyway graal-native-image groovy grpc hibernate-gorm hibernate-jpa http-client http-server java jdbc-dbcp jdbc-hikari jdbc-tomcat jib jrebel junit kafka kafka-streams kotlin liquibase management micrometer micrometer-atlas micrometer-graphite micrometer-prometheus micrometer-statsd mongo-gorm mongo-reactive neo4j-bolt neo4j-gorm netflix-archaius netflix-hystrix netflix-ribbon picocli postgres-reactive rabbitmq redis-lettuce security-jwt security-session spek spock springloaded swagger-groovy swagger-java swagger-kotlin tracing-jaeger tracing-zipkin
  5. 5. Creating app with CLI $ mn create-app greach --features=discovery-consul, management, graal-native-image, tracing-zipkin
  6. 6. It is “just” creating beans...
  7. 7. ...although it’s not
  8. 8. Creating a configuration - Bean Factories - Conditional Beans - Bean Replacement - Bean Configuration - Configuration Properties - Configuration Builder - Each Property - Each Bean - More options
  9. 9. Bean Factories public class FooLibrary { // Do stuff } @Singleton public class FooLibrary { // Do stuff } @Factory public class FooFactory { @Bean public FooLibrary createFoo() { return new FooLibrary(); } }
  10. 10. Conditional Beans @Requires(beans = DataSource.class) @Requires(property = "datasource.url") @Singleton public class JdbcBookService implements BookService { DataSource dataSource; public JdbcBookService(DataSource dataSource) { this.dataSource = dataSource; } }
  11. 11. Conditional Beans (II) @Requires(classes = DataSource.class) @Requires(missing = JdbcRowSet.class) @Requires(beans = DataSource.class) @Requires(missingBeans = DataSource.class) @Requires(env = Environment.TEST) @Requires(notEnv = Environment.TEST) @Requires(configuration = "some.config") @Requires(missingConfigurations = "other.config") @Requires(sdk = Requires.Sdk.JAVA, value = "1.8") @Requires(entities = javax.persistence.Entity.class) @Requires(property = "data-source.url") @Requires(missingProperty = "data-source.url") @Requires(property="foo", value="John", defaultValue="John") @Requires(condition = FlywayCondition.class) public class Foo { }
  12. 12. Bean Replacement @Singleton @Requires(beans = DataSource.class) @Requires(property = "datasource.url") public class JdbcBookService implements BookService { DataSource dataSource; public JdbcBookService(DataSource dataSource) { this.dataSource = dataSource; } }
  13. 13. Bean Replacement @Singleton @Requires(beans = DataSource.class) @Requires(property = "datasource.url") public class JdbcBookService implements BookService { DataSource dataSource; public JdbcBookService(DataSource dataSource) { this.dataSource = dataSource; } } @Singleton @Replaces(JdbcBookService.class) @Requires(property = "spec.name", value = "foo") public class MockBookService implements BookService { Map<String, Book> bookMap = new LinkedHashMap<>(); @Override public Book findBook(String title) { return bookMap.get(title); } }
  14. 14. Bean Configuration // package-info.java @Configuration @Requires(property = "flyway.enabled", notEquals = "false") package io.micronaut.configuration.dbmigration.flyway; @Configuration @Requires(classes = {Channel.class, Connection.class, ConnectionFactory.class}) package io.micronaut.configuration.rabbitmq;
  15. 15. Configuration injection @Singleton public class ApiService { @Value("${api.key}") protected String apiKey; @Value("${api.secret}") protected String apiSecret; @Value("${api.results:10}") protected int results; @Value("${api.url:`https://api.foo.com`}") protected URL url; }
  16. 16. Configuration injection (II) @Controller("/api/${api.version:v1}") public class ApiController { // ... } @Client("${api.server-url:`http://localhost:8080`}") public interface ApiClient { // ... }
  17. 17. Configuration injection (III) # application.yml datasources: default: name: 'mydb' jpa: default: properties: hibernate: hbm2ddl: auto: 'update' show_sql: true @Property(name = "jpa.default.properties") Map<String, Object> jpaProperties;
  18. 18. Configuration Properties @ConfigurationProperties('my.engine') class EngineConfig { @NotBlank String manufacturer = "Ford" @Min(1L) int cylinders CrankShaft crankShaft = new CrankShaft() @ConfigurationProperties('crank-shaft') static class CrankShaft { Optional<Double> rodLength = Optional.empty() } } # application.yml my: engine: manufacturer: Toyota cylinders: 4 crank-shaft: rod-length: 4
  19. 19. Configuration Builder @ConfigurationProperties('my.engine') class EngineConfig { @ConfigurationBuilder(prefixes = "with") EngineImpl.Builder builder = EngineImpl.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "crank-shaft") CrankShaft.Builder crankShaft = CrankShaft.builder() SparkPlug.Builder sparkPlug = SparkPlug.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "spark-plug") void setSparkPlug(SparkPlug.Builder sparkPlug) { this.sparkPlug = sparkPlug } }
  20. 20. Configuration Builder @ConfigurationProperties('my.engine') class EngineConfig { @ConfigurationBuilder(prefixes = "with") EngineImpl.Builder builder = EngineImpl.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "crank-shaft") CrankShaft.Builder crankShaft = CrankShaft.builder() SparkPlug.Builder sparkPlug = SparkPlug.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "spark-plug") void setSparkPlug(SparkPlug.Builder sparkPlug) { this.sparkPlug = sparkPlug } } class EngineImpl implements Engine { //... static Builder builder() { return new Builder() } static final class Builder { private String manufacturer = "Ford" private int cylinders Builder withManufacturer(String manufacturer) { this.manufacturer = manufacturer this } Builder withCylinders(int cylinders) { this.cylinders = cylinders this } EngineImpl build(CrankShaft.Builder crankShaft, SparkPlug.Builder sparkPlug) { new EngineImpl(manufacturer, cylinders, crankShaft.build(), sparkPlug.build()) } } }
  21. 21. Configuration Builder @ConfigurationProperties('my.engine') class EngineConfig { @ConfigurationBuilder(prefixes = "with") EngineImpl.Builder builder = EngineImpl.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "crank-shaft") CrankShaft.Builder crankShaft = CrankShaft.builder() SparkPlug.Builder sparkPlug = SparkPlug.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "spark-plug") void setSparkPlug(SparkPlug.Builder sparkPlug) { this.sparkPlug = sparkPlug } }
  22. 22. Configuration Builder # application.yml my: engine: cylinders: 4 manufacturer: 'Subaru' crank-shaft: rod-length': 4 spark-plug: name: '6619 LFR6AIX' type: 'Iridium' companyName: 'NGK' @ConfigurationProperties('my.engine') class EngineConfig { @ConfigurationBuilder(prefixes = "with") EngineImpl.Builder builder = EngineImpl.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "crank-shaft") CrankShaft.Builder crankShaft = CrankShaft.builder() SparkPlug.Builder sparkPlug = SparkPlug.builder() @ConfigurationBuilder(prefixes = "with", configurationPrefix = "spark-plug") void setSparkPlug(SparkPlug.Builder sparkPlug) { this.sparkPlug = sparkPlug } }
  23. 23. @EachProperty @EachProperty("flyway.datasources") public class FlywayConfigurationProperties { private final DataSource dataSource; private final String nameQualifier; public FlywayConfigurationProperties(@Nullable @Parameter DataSource dataSource, @Parameter String name) { this.dataSource = dataSource; this.nameQualifier = name; } ... } # application.yml flyway: datasources: default: async: true locations: classpath:databasemigrations books: locations: classpath:bookmigrations enabled: false
  24. 24. @EachProperty @EachProperty("flyway.datasources") public class FlywayConfigurationProperties { private final DataSource dataSource; private final String nameQualifier; public FlywayConfigurationProperties(@Nullable @Parameter DataSource dataSource, @Parameter String name) { this.dataSource = dataSource; this.nameQualifier = name; } ... } # application.yml flyway: datasources: default: async: true locations: classpath:databasemigrations books: locations: classpath:bookmigrations enabled: false
  25. 25. @EachProperty (II) public class FlywayEndpoint { private final ApplicationContext applicationContext; private final Collection<FlywayConfigurationProperties> flywayConfigurationProperties; public FlywayEndpoint(ApplicationContext applicationContext, Collection<FlywayConfigurationProperties> flywayConfigurationProperties) { this.applicationContext = applicationContext; this.flywayConfigurationProperties = flywayConfigurationProperties; } ... } Optional<FlywayConfigurationProperties> optionConfig = applicationContext .findBean(FlywayConfigurationProperties.class, Qualifiers.byName(“books”));
  26. 26. @EachBean @Factory public class FlywayFactory { @Requires(condition = FlywayCondition.class) @EachBean(FlywayConfigurationProperties.class) public Flyway flyway(FlywayConfigurationProperties config) { FluentConfiguration fluentConfiguration = config.fluentConfiguration; fluentConfiguration.dataSource(config.getDataSource()); return fluentConfiguration.load(); } } Flyway flyway = applicationContext .getBean(Flyway.class, Qualifiers.byName(“books”));
  27. 27. More options - Filters - Endpoints - Aspect Oriented Programming (AOP) - Annotation Mapper - Controllers - Fire events - Execute something on startup
  28. 28. Show me the code!
  29. 29. Summary Configurations (features) out-of-the-box Easy to create Extend the Framework Lots of different options The sky is the limit Increase productivity
  30. 30. SLIDE TITLE 27 PT ALL CAPS Thank you! @ilopmar lopez.ivan@gmail.com https://github.com/ilopmar Iván López http://bit.ly/greach-micronaut Questions?

×