Εμφάνιση αναρτήσεων με ετικέτα @Conditional. Εμφάνιση όλων των αναρτήσεων
Εμφάνιση αναρτήσεων με ετικέτα @Conditional. Εμφάνιση όλων των αναρτήσεων

Πέμπτη 21 Οκτωβρίου 2021

Spring Certification: Spring Boot Auto Configuration

How does Spring Boot know what to configure?
  • These classes contain ConditionalOn.. classes that scan classpath resources and register beans, according to starters and dependencies that user introduced in POMs
  • Spring Boot checks for the presence of a META-INF/spring.factories file within your published jar. The file should list your configuration classes under the EnableAutoConfiguration key, as shown in the following example:
    • org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.code.in.packets.autoconf.SomeAutoConfiguration1,\
      com.code.in.packets.autoconf.SomeAutoConfiguration2
  • See all ConditionalOn classes
  • Using @Profile("some-profile") on a @Bean, and then load this profile

  • Using @Conditional("<some-class>") on a @Bean




What does @EnableAutoConfiguration do?

  • Applied in Application/Main class of Spring application
  • In Spring Boot application, already included in @SpringBootApplication annotation
  • Responsible for kick-starting autoconfiguration process, by
    • @AutoConfigurationPackage
      • Importing AutoConfigurationPackages.Registrar, that registers a bean which provides Bean list for Spring boot to use internally, in spring-boot-autoconfigure package
    • @Import(EnableAutoConfigurationImportSelector.class)
      • Imports AutoConfigurationImportSelector that aggregates all spring.factories
  • Can exclude some autoconfiguration class, like: @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) in our @Configuration class



What does @SpringBootApplication do?

  • Applied only in root package class, and contains below annotations:
  • @EnableAutoConfiguration: enables Spring Boot’s auto-configuration mechanism
  • @ComponentScan: enable @Component scan on the package where the application is located
  • @Configuration: allow to register extra beans in the context or import additional configuration classes

Does Spring Boot do component scanning? Where does it look by default?
  • Yes, @ComponentScan or @SpringBootApplication enables component scanning.
  • By default, it scans for components in whole package (and subpackages) of the class with @SpringBootApplication
  • If no component scanning is set, it only scans the package of the main class
  • @ComponentScan is also used to specify base packages and base package classes using thebasePackageClasses or basePackages attributes


How are DataSource and JdbcTemplate auto-configured?
  • DataSource 
    •  with DataSourceAutoConfiguration class from spring-boot-autoconfigure package.
    • that retrieves properties spring.datasource.url, spring.datasource.username, spring.datasource.password from application.properties or yml file.
  • JdbcTemplate
    • with JdbcTemplateAutoConfiguration, that contains:
    • @ConditionalOnClass(value={javax.sql.DataSource.class,org.springframework.jdbc.core.JdbcTemplate.class})
      • If DataSource class exists in classpath, only then configure JdbcTemplate
    • @ConditionalOnSingleCandidate(value=javax.sql.DataSource.class)
      • We need only one candidate
    • @AutoConfigureAfter(value=DataSourceAutoConfiguration.class) 
      • First configure DataSource, and only then JdbcTemplate 

What is spring.factories file for?
  • spring.factories contains auto-configuration classes needed for the AutoConfiguration mechanism of Spring
  • @EnableAutoConfiguration eventually gathers all spring.factories files of all project modules/packages and aggregates them into one.
  • A spring.factories contains an EnableAutoConfiguration key with values as the list of auto-configuration classes, and resides under META/INF directory
  • spring.factories should be used when we want to set default components globally for our app. Thus the need for @Autowire-ing a dependency disappears. But of course, this default behavior can later be overwritten with some @Bean/@Configuration


How do you customize Spring Boot auto configuration?
  • To create our own auto-configuration: 
    • add a spring.factories in META-INF, with content:
    • org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.myapp.package1.autoconfigure.MyDataSourceAutoConfiguration, com.myapp.package2.autoconfigure.MyJpaAutoConfiguration
    • Implement above classes as @Configurations accordingly to specific needs
    • Disable loading of auto-configuration class for DataSource loading:  @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) 


What are the examples of @Conditional annotations? How are they used?

Conditional classes are used from within AutoConfiguration classes to load conditionally classpath resources :
  • ConditionalOnBean - Spring Bean must be registered
  • ConditionalOnMissingBean - Spring Bean must not be registered
  • ConditionalOnClass - Class must exist in classpath
  • ConditionalOnMissingClass - Class must not exist in classpath
  • ConditionalOnExpression - spEL expression must result to true
  • ConditionalOnJava - Java JDK in certain version must exist
  • ConditionalOnJndi - JNDI location should exist
  • ConditionalOnProperty - property must exist
  • ConditionalOnResource - resource must exist

Τετάρτη 20 Οκτωβρίου 2021

Spring Certification: Spring Boot Basics

What is Spring Boot?
  • Extension of Spring Framework
  • Build fast production-ready applications, by:
  • providing auto-configurated dependencies
  • starter POMs (easy dependency management)
  • devTools (live code reload)
  • Fit for building apps in microservice architecture


What are the advantages of using Spring Boot?

  • Starter POMs: provide commonly used dependencies with correct versions and transitive dependencies
  • Embedded servlet containers (tomcat, jetty..), no need for WAR, packaging and deploying manually
  • Automatic Configuration: out of the box dependencies, but also configurable
  • Facilitates testing - provides default setup for unit IT tests
  • Solves boilerplate code in Spring projects (no XML)
  • Easily set  development and production profiles
  • Non-functional requirements: Security, Metrics, Externalized configuration and more


Why is it opinionated?
  • Convention over configuration principle is followed, meaning that framework tries to understand what to load, depending on what dependencies the developer has entered
  • Above approach can be edited


What things affect what Spring Boot sets up?
  1. Dependencies are set via starter POMs and/or additional by hand
  2. Spring Boot's autoconfigure module scans what there is on the classpath, and then employs Spring beans to integrate all dependencies (e.g. Spring MVC, Spring Data JPA, etc). This is done with use of @ConditionalOn.. inside AutoConfiguration classes.
  3. Furthermore, developer can set @ConditionalOn.. in his beans


    @ConditionalOn.. classes:

  • ConditionalOnBean - Spring Bean must exist
  • ConditionalOnMissingBean - Spring Bean must not exist
  • ConditionalOnClass - Class must exist
  • ConditionalOnMissingClass - Class must not exist
  • ConditionalOnExpression - spEL expression must result to true
  • ConditionalOnJava - Java JDK in certain version must exist
  • ConditionalOnJndi - JNDI location should exist
  • ConditionalOnProperty - property must exist
  • ConditionalOnResource - resource must exist


What is a Spring Boot starter? Why is it useful?

  • Spring Boot starters are sets of dependency descriptors that define all correct transitive dependencies and versions needed to provide a specific technology to include and use in applications. All official starters follow this pattern: spring-boot-starter-*
  • Developers can focus on business logic, not worrying much about dependency management.
  • Ensures no dependencies are missing and that all have versions that are compatible together.


Spring Boot supports both properties and YML files. Would you recognize and understand them if you saw them?
  • Spring provides option for externalization of configuration by Properties file or YML
  • YML is derived from JSON and is enabled when snakeYAML dependency is present
    • Recognizable from its hierarchical data structure


Can you control logging with Spring Boot? How?
  • Logging library:
    • If spring-boot-starter-web is used, by default Spring uses Commons Logging API, and Apache Logback as reference implementation. To change that, we need to exclude Logback in pom, and include another compatible e.g. Log4J
  • Logging levels:
    • In application properties use logging.level.root=<level> (application-wise).  Use debug=true to enable DEBUG mode globally
    • or com.app.package1=<level> (package-wise)
    • Alternatively, above can apply in a logback-spring.xml file
    • From VM options like: -Dlogging.level.org.springframework=DEBUG

  • Logging output: Use logging.file or logging.path in application properties


Where does Spring Boot look for application.properties file by default?
  1. In /config directory (outside of classpath/jar)
  2. In application directory (outside of classpath/jar)
  3. In /config directory of classpath (in jar)
  4. In classpath root directory (in jar)



How do you define profile specific property files?
  • application-{profile}.yml or application-{profile}.properties
  • If a property is not found in profile-specific file, it loads from the application.properties or application-default.properties (same for yml)



How do you access the properties defined in the property files?
  • In @Configuration class, annotate itself with @PropertySource("app.properties") and then annotate fields with @Value("app.some.property")
  • Alternatively, in Class1 add annotation @ConfigurationProperties(prefix = "app.some"), and then refer to field as "property". Finally, access property value in a second @Configuration class with @EnableConfigurationProperties(Class1.class)
  • @Autowire Spring's Environment, and access property with environment.getProperty("app.some.property")



What properties do you have to define in order to configure external MySQL?
  • spring.datasource.url=jdbc:mysql://<host>:<port>/<databaseName>
  • spring.datasource.username=<username>
  • spring.datasource.password=<password>
  • spring.datasource.driver-class-name=com.mysql.jdbc.Driver


How do you configure default schema and initial data?
  • Configure data.sql and schema.sql in /resources 
  • In properties: spring.datasource.initialization-mode=always
  • If using hibernate, spring.jpa.hibernate.ddl-auto=none
  • Spring loads according to platform set and loads data-{platform}.sql and schema-{platform}.sql. Platform is defined in property spring.datasource.platform=<vendor-platform>, e.g. mysql


What is a fat jar? How is it different from the original jar?
  • An executable jar containing all compiled classes and resources, along with dependencies as nested jars
  • project-1.2.3-SNAPSHOT.jar is the Fat jar, while inside it project-1.2.3-SNAPSHOT.jar.original is the original jar. 
  • To create a Fat jar, spring-boot-maven-plugin is needed to insert original jar in Fat jar. 
  • Fat jar is executable by default with java -jar project-1.2.3-SNAPSHOT.jar, while original is not.


What is the difference between an embedded container and a WAR?
  • Embedded container is used to run a single application's executable jar, and resides in jar itself as a dependency
    • To set up, use maven dependencies spring-boot-starter-web (provides embedded tomcat) and spring-boot-maven-plugin with repackaging goal (to integrate original jar in executable/fat jar)
  • WAR needs to be deployed in an Application Server, where many other war files (applications) can co-exist
    • To set up, use <packaging>war</packaging>, spring-boot-starter-web dependency and spring-boot-starter-tomcat with provided scope

What embedded containers does Spring Boot support?
  • Tomcat 
    • Default with spring-boot-starter-web
  • Jetty
    • First must exclude default Tomcat with <exclusion> tag
    • Set spring-boot-starter-jetty dependency
  • Undetow
    • Same setup logic as Jetty