Saturday, 6 November 2021

MySQL on Kubernetes

 


How to Deploy MySQL on Kubernetes


I found the nice article and learning here 
https://pycon2019.container.training/#169
https://container.training/kube-selfpaced.yml.html#129


Prepare the environment

Following this tutorial, you need to have Minikube installed on your Ubuntu Linux.

You can verify whether the Minikube has been successfully up and running by the following command:

$ minikube status

Output:

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Create Secret for MySQL

Kubernetes uses Secret to store and manage sensitive information such as passwords, ssh keys and OAuth tokens. In this tutorial, we use base64 encoded to store 'MYSQL_ROOT_PASSWORD'. For example:

$ echo -n 'admin' | base64

Output:

YWRtaW4=

Create a mysql-secret.yaml file for MySQL that will be mapped as an environment variable as follows:

apiVersion: v1
kind: Secret
metadata:
  name: mysql-pass
type: Opaque
data:
  password: YWRtaW4=

Apply the manifest:

$ kubectl create -f mysql-secret.yaml

secret/mysql-pass created

Verify that the Secret has just been created successfully:

$ kubectl get secrets

NAME                  TYPE                                  DATA   AGE
default-token-l7t7b   kubernetes.io/service-account-token   3      4h24m
mysql-pass            Opaque                                1      1m

Deploy MySQL

Create the mysql-pod.yaml file to deploy MySQL pod on Kubernetes cluster:

apiVersion: v1
kind: Pod
metadata:
  name: k8s-mysql
  labels:
    name: lbl-k8s-mysql
spec:
  containers:
  - name: mysql
    image: mysql:latest
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-pass
          key: password
    ports:
    - name: mysql
      containerPort: 3306
      protocol: TCP
    volumeMounts:
    - name: k8s-mysql-storage
      mountPath: /var/lib/mysql
  volumes:
  - name: k8s-mysql-storage
    emptyDir: {}

Apply the manifest file:

$ kubectl create -f mysql-pod.yaml

pod/k8s-mysql created

Verify that the pod is running:

$ kubectl get pod

NAME        READY   STATUS    RESTARTS   AGE
k8s-mysql   1/1     Running   0          30s

Now, we can connect to the k8s-mysql pod:

$ kubectl exec k8s-mysql -it -- bash

root@k8s-mysql:/# echo $MYSQL_ROOT_PASSWORD
admin
root@k8s-mysql:/# mysql --user=root --password=$MYSQL_ROOT_PASSWORD
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

Kubernetes use Service to expose pods to other pods or external systems. We will use the following manifest file mysql-service.yaml to make the k8s-mysql pod be reachable:

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  labels:
    name: lbl-k8s-mysql
spec:
  ports:
  - port: 3306
  selector:
    name: lbl-k8s-mysql
  type: ClusterIP

Apply the manifest to create the service:

$ kubectl create -f mysql-service.yaml

service/mysql-service created

Verify that the service has been successfully created:

$ kubectl get svc

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes      ClusterIP   10.96.0.1               443/TCP    5h4m
mysql-service   ClusterIP   10.110.22.182           3306/TCP   30s

Friday, 10 September 2021

 

This post is copied form https://www.ibm.com/cloud/blog/8-kubernetes-tips-and-tricks

1. Set default namespaces

You can divide a Kubernetes cluster into multiple environments by using namespaces (e.g., Dev1, Dev2, QA1, QA2, etc.), and each environment can be managed by a different user. One of the inconveniences of writing kubectl commands is that every time you write a command, you need the --namespace option at the end. People often forget this and end up creating objects (pods, services, deployments) in the wrong namespace. 

With this trick, you can set the namespace preference before running kubectl commands. Run the following command before executing the kubectl commands, and it will save the namespace for all subsequent kubectl commands for your current context:

kubectl config set-context $(kubectl config current-context) --namespace=mynamespace

Some of the most common and useful commands with namespace are listed below:

  • kubectl get namespaces
  • kubectl create namespace mynamespace
  • kubectl get pods --all-namespaces (List all pods with status from all namespaces.)
  • kubectl get po -o wide -n <namspace1> -n <namespace2> -n <namespace3> (This command will identify the pods in each namespace)
  • kubectl describe namespace <namespace>
  • kubectl config view --minify | grep namespace (This command will ensure that you set the namespace correctly for your current context.) 

2. Helpful aliases to save time

Kubernetes commands can be quite lengthy, so setting up some aliases for running kubectl is very helpful. You will no longer need to spell out the full command over and over again, making your life a lot easier when you want to execute multiple Kubernetes commands in one session.

We have listed aliases for some frequently used commands below. Run these before executing kubectl commands to save yourself some time. Example: You just need to type k instead of typing kubectl:

  • alias k='kubectl'
  • alias kc='k config view --minify | grep name'
  • alias kdp='kubectl describe pod'
  • alias krh='kubectl run --help | more'
  • alias ugh='kubectl get --help | more'
  • alias c='clear'
  • alias kd='kubectl describe pod'
  • alias ke='kubectl explain'
  • alias kf='kubectl create -f'
  • alias kg='kubectl get pods --show-labels'
  • alias kr='kubectl replace -f'
  • alias kh='kubectl --help | more'
  • alias krh='kubectl run --help | more'
  • alias ks='kubectl get namespaces'
  • alias l='ls -lrt'
  • alias ll='vi ls -rt | tail -1'
  • alias kga='k get pod --all-namespaces'
  • alias kgaa='kubectl get all --show-labels'

3. YAML editing with vi

There are many different editors available to write YAML files, but there are many times where you may need to quickly tweak a generated YAML and while working on a terminal. This is a great place to use our trusty vi, the text editor originally created for the Unix operating system.

The vi editor is well documented and has support from a vibrant open source community. One of the problems with the vi editor while creating YAML files, however, is the space issue. We need a way to indent with tabs and align with spaces. Using tabs vs. spaces for whitespace has always created syntax issues while writing YAML files (e.g., getting the 2-space YAML as the default when hitting carriage return).

The solution? Create a ~/.vimrc file with these lines before creating YAML files with the vi editor to make editing easier:

  • set smarttab
  • set expandtab
  • set shiftwidth=4
  • set tabstop=4
  • set number

4. Create YAML from kubectl commands 

We can create complex YAML files from the command line using kubectl commands.

Most people would agree that working with YAML files is no fun, and Kubernetes YAML files can be very verbose and hard to create from scratch. It is much easier to create the YAML file from kubectl commands instead of from a blank page using an editor.

The following commands will create a YAML file with name yamlfile. Once you create the YAML file from these kubectl commands, you can modify it based on your requirements and use it instead of writing from scratch:

  • kubectl run busybox --image=busybox --dry-run=client -o yaml --restart=Never > yamlfile.yaml
  • kubectl create job my-job --dry-run=client -o yaml --image=busybox -- date  > yamlfile.yaml
  • kubectl get -o yaml deploy/nginx > 1.yaml (Ensure that you have a deployment named as nginx)
  • kubectl run busybox --image=busybox --dry-run=client -o yaml --restart=Never -- /bin/sh -c "while true; do echo hello; echo hello again;done" > yamlfile.yaml
  • kubectl run wordpress --image=wordpress –-expose –-port=8989 --restart=Never -o yaml
  • kubectl run test --image=busybox --restart=Never --dry-run=client -o yaml -- bin/sh -c 'echo test;sleep 100' > yamlfile.yaml  (Notice that --bin comes at the end. This will create yaml file.)

Another good idea for creating the YAML file is obtaining the file directly from the internet using the wget command. 

5. Switching between Kubernetes namespaces

In Tip 1, we learned some useful commands to use Kubernetes namespaces and save them so that you don't have to add to every command. Let's expand the tip to make it easier to switch between namespaces and kubectl contexts.

There are several tools that can help, but we like kubectx and kubens for managing contexts and namespaces, respectively. You can find details of kubectx and kubens here.

Here is how to download the Linux binaries for kubectx and kubens utility:

  • wget https://github.com/ahmetb/kubectx/releases/download/v0.9.0/kubectx_v0.9.0_linux_x86_64.tar.gz
  • wget https://github.com/ahmetb/kubectx/releases/download/v0.9.0/kubens_v0.9.0_linux_x86_64.tar.gz

Then you extract them with the following commands:

  • tar -xvf kubectx_v0.9.0_linux_x86_64.tar.gz
  • tar -xvf kubens_v0.9.0_linux_x86_64.tar.gz

Finally, you move them to your PATH:

  • sudo mv kubectx /usr/local/bin
  • sudo mv kubens /usr/local/bin

Once installed, you can simply use kubens to list the namespaces and switch between them:

Once installed, you can simply use kubens to list the namespaces and switch between them:

When working with multiple clusters, kubectx makes switching between contexts a breeze:

When working with multiple clusters, kubectx makes switching between contexts a breeze:

6. Shell auto-completion

Did you know that kubectl provides auto-completion for BASH and ZSH? This is an optional configuration.

Let’s say you understand the concepts of Kubernetes and have some experience with kubectl, but perhaps you aren’t so good at memorizing commands. First you install bash-completion, and then you enable kubectl autocompletion. You can find all the details in the “Install and Set Up kubectl“ documentation page for your environment.

Below are the config options with the autocompletion feature:

Below are the config options with the autocompletion feature:

Now, just tab away!

7. Viewing resource utilization

The top command is probably one of the most popular tools to monitor processes and system resources. It provides a simple character-based interface and quick access to crucial information.

You can see resource utilization per node:

You can see resource utilization per node:

Resource utilization per pod:

Resource utilization per pod:

And the handy watch command can help you display the command in a desirable interval without having to run it over and over again. The following example makes it run every five seconds (the default is two seconds): 

watch kubectl top node -n 5

Note: The watch command needs to be downloaded for your environment.

Your Kubernetes cluster also needs to be running heapster in order for the top command work, otherwise you'll get the following error: “Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)”

Learn how to enable the heapster add-on.

8. Extend kubectl and create your own commands using raw outputs

The kubectl command provides a summarized view of the resources stored by the apiserver. There are many more fields stored by the apiserver that are not shown. You can use the kubectl get command with the raw resource output to create your own visualization and commands. 

You can print the raw resources in JSON with the following command:

kubectl get deployments -o json

You can also call the resource directly using the api call:

kubectl get --raw=/apis/apps/v1/deployments

You can even combine the output with tools like jq to provide different visualizations, filter the output, or feed the output to other tools for advance automation. 

For example, it can be hard to find issues on clusters with multiple namespaces and deployments, but the example below uses the raw API to scan all deployments in the cluster and filter only the deployments with failing replicas:

kubectl get --raw=/apis/apps/v1/deployments | jq '.items[] | {name: .metadata.name, replicas: .status.replicas, available: (.status.availableReplicas // 0), unavailable: (.status.unavailableReplicas // 0)} | select (.unavailable > 0)'

The following is a quick explanation of the command above:

  • First, we call the Kubernetes API to return all deployments. The default output is in JSON. It is hard to visualize the structure of the JSON document, but you can pipe to jq to get a better idea like in the example below:
    kubectl get --raw=/apis/apps/v1/deployments | jq .
  • Notice that the response document has an array of items for each deployment. We want to inspect the status field of this array all the way in the end. The command below shows how to print just the data you need and a default value of 0 when the field is not available:
    kubectl get --raw=/apis/apps/v1/deployments | jq '.items[] | {name: .metadata.name, replicas: .status.replicas, available: (.status.availableReplicas // 0), unavailable: (.status.unavailableReplicas // 0)}'
  • The final piece of the puzzle is using the select function to only display deployments with unavailable replicas:
    kubectl get --raw=/apis/apps/v1/deployments | jq '.items[] | {name: .metadata.name, replicas: .status.replicas, available: (.status.availableReplicas // 0), unavailable: (.status.unavailableReplicas // 0)} | select (.unavailable > 0)'

Saturday, 14 August 2021

 


Spring Boot Annotation


Annotation Basics

Let’s start with some basic terminologies used during the explanation of annotations.

What is The IoC container?

In a nutshell, a container that injects dependencies while creating the bean. IoC stands for ‘Inversion Of Control’. Instead of creating objects by us, the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes with the help of the IoC container. Hence, this process is known as ‘Inversion of control’. Sometimes we also call it Spring Container in short.

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. ApplicationContext is a sub-interface of BeanFactory.

What is an Application Context in Spring Framework?

When you create a project in Spring or Spring Boot, a container or wrapper gets created to manage your beans. This is nothing but Application Context. However Spring supports two containers : Bean Factory and Application Context. In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality including easier integration with Spring’s AOP features; message resource handling (for use in internationalization), event publication; and application-layer specific contexts such as the WebApplicationContext for use in web applications. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this topic in descriptions of Spring’s IoC container. Spring Framework recommends to use Application Context to get the full features of the framework. Moreover, Dependency injection and auto-wiring of beans is done in Application Context.

The interface org.springframework.context.ApplicationContext represents the Spring IoC container and it manages the process of instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code.

What is Spring Bean or Components?

During Application startup, Spring instantiates objects and adds them to the Application Context. These objects in the Application Context are called ‘Spring Beans’ or ‘Spring Components’. As they are managed by Spring, therefore we also call them Spring-managed Bean or Spring-managed Component.

What is Component Scanning?

The process of discovering classes that can contribute to the Application Context, is called Component Scanning. During Component Scanning, if Spring finds a class annotated with a particular annotation, It will consider this class as a candidate for Spring Bean/Component and adds it to the Application Context. Spring explicitly provides a way to identify Spring bean candidates via the @ComponentScan annotation.

When to use Component Scanning in a Spring Boot Application?

By default, the @ComponentScan annotation will scan for components in the current package and all its sub-packages. If it is a Spring Boot application, then all the packages under the package containing the Main class (a class annotated with @SpringBootApplication) will be covered by an implicit component scan. So if your package doesn’t come under the hierarchy of the package containing the Main class, then there is a need for explicit component scanning.

Annotations to create a Bean

Let’s start discussing our article ‘Spring Boot Annotations with Examples’ with the annotations to create a Bean. Needless to say, we can’t work on Spring Boot/Spring without creating a Bean. Now you can imagine how important is that !

@Configuration 

We apply this annotation on classes. When we apply this to a class, that class will act as a configuration by itself. Generally the class annotated with @Configuration has bean definitions as an alternative to <bean/> tag of an XML configuration. It also represents a configuration using Java class. Moreover the class will have methods to instantiate and configure the dependencies. For example :

@Configuration
public class AppConfig { 
    @Bean
    public RestTemplate getRestTemplate() {
       RestTemplate restTemplate = new RestTemplate();
       return restTemplate();
    } 
}

♥ The benefit of creating an object via this method is that you will have only one instance of it. You don’t need to create the object multiple times when required. Now you can call it anywhere in your code.

@Bean

We use @Bean at method level. If you remember the xml configuration of a Spring, It is a direct analog of the XML <bean/> element. It creates Spring beans and generally used with @Configuration. As aforementioned, a class with @Configuration (we can call it as a Configuration class) will have methods to instantiate objects and configure dependencies. Such methods will have @Bean annotation. By default, the bean name will be the same as the method name. It instantiates and returns the actual bean. The annotated method produces a bean managed by the Spring IoC container.

@Configuration
public class AppConfig {
     @Bean 
     public Employee employee() {
         return new Employee();
     }
    @Bean
    public Address address() {
        return new Address();
     }
}

For comparison sake, the configuration above is exactly equivalent to the following Spring XML:

<beans>
    <bean name="employee" class="com.dev.Employee"/>
    <bean name="address" class="com.dev.Address"/>
</beans>

The annotation supports most of the attributes offered by <bean/>, such as: init-method, destroy-method, autowiring, lazy-init, dependency-check, depends-on and scope.

@Component 

This is a generic stereotype annotation which indicates that the class is a Spring-managed bean/component. @Component is a class level annotation. Other stereotypes are a specialization of @Component. During the component scanning, Spring Framework automatically discovers the classes annotated with @Component, It registers them into the Application Context as a Spring Bean. Applying @Component annotation on a class means that we are marking the class to work as Spring-managed bean/component. For example, look at the code below:

@Component
class MyBean { }

On writing a class like above, Spring will create a bean instance with name ‘myBean’. Please keep in mind that, By default, the bean instances of this class have the same name as the class name with a lowercase initial. However, we can explicitly specify a different name using the optional argument of this annotation like below.

@Component("myTestBean")
class MyBean { }

@Controller 

@Controller tells Spring Framework that the class annotated with @Controller will work as a controller in the Spring MVC project.

@RestController

@RestController tells Spring Framework that the class annotated with @RestController will work as a controller in a Spring REST project.

@Service

@Service tells Spring Framework that the class annotated with @Service is a part of service layer and it will include business logics of the application.

@Repository

@Repository tells Spring Framework that the class annotated with @Repository is a part of data access layer and it will include logics of accessing data from the database in the application.

@Bean vs @Component

@Component is a class level annotation whereas @Bean is a method level annotation and name of the method serves as the bean name. @Bean annotation has to be used within the class and that class should be annotated with @Component. However, @Component needs not to be used with the @Configuration. @Component auto detects and configures the beans using classpath scanning, whereas @Bean explicitly declares a single bean, rather than letting Spring do it automatically.

 

Configuration Annotations

Next annotations in our article ‘Spring Boot Annotations with Examples’ are for Configurations. Since Spring Framework is healthy in configurations, we can’t avoid learning annotations on configurations. No doubt, they save us from complex coding effort.

@ComponentScan

Spring container detects Spring managed components with the help of @ComponentScan. Once you use this annotation, you tell the Spring container where to look for Spring components. When a Spring application starts, Spring container needs the information to locate and register all the Spring components with the application context. However It can auto scan all classes annotated with the stereotype annotations such as @Component, @Controller, @Service, and @Repository from pre-defined project packages.

The @ComponentScan annotation is used with the @Configuration annotation to ask Spring the packages to scan for annotated components. @ComponentScan is also used to specify base packages and base package classes using basePackages or  basePackageClasses attributes of @ComponentScan. For example :

import com.springframework.javatechonline.example.package2.Bean1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.springframework.javatechonline.example.package1",
                                                    "com.springframework.javatechonline.example.package3",
                                                    "com.springframework.javatechonline.example.package4"},
                                basePackageClasses = Bean1.class
                               )
public class SpringApplicationComponentScanExample {
               ....
}

Here the @ComponentScan annotation uses the basePackages attribute to specify three packages including their subpackages that will be scanned by the Spring container. Moreover the annotation also uses the basePackageClasses attribute to declare the Bean1 class, whose package Spring Boot will scan.

Moreover, In a Spring Boot project, we typically apply the @SpringBootApplication annotation on the main application class. Internally, @SpringBootApplication is a combination of the @Configuration, @ComponentScan, and @EnableAutoConfiguration annotations. Further, with this default setting, Spring Boot will auto scan for components in the current package (containing the SpringBoot main class) and its sub packages.

@Import 

Suppose we have multiple Java configuration classes annotated by @Configuration. @Import imports one or more Java configuration classes. Moreover It has the capability to group multiple configuration classes. We use this annotation where one @Configuration class logically imports the bean definitions defined by another. For example:

@Configuration
@Import({ DataSourceConfig.class, TransactionConfig.class })
public class AppConfig extends ConfigurationSupport {
    // @Bean methods here that can reference @Bean methods in DataSourceConfig or TransactionConfig
} 

@PropertySource 

If you create a Spring Boot Starter project using an IDE such as STS, application.properties comes under resources folder by default. In contrast, You can provide the name & location of the properties file (containing the key/value pair) as per your convenience by using @PropertySource. Moreover, this annotation provides a convenient and declarative mechanism for adding a PropertySource to Spring’s Environment. For example,

@Configuration
@PropertySource("classpath:/com/dev/javatechonline/app.properties")
public class MyClass {
}

@PropertySources (For Multiple Property Locations)

Of course, If we have multiple property locations in our project, we can also use the @PropertySources annotation and specify an array of @PropertySource.

@Configuration 
@PropertySources({ 
              @PropertySource("classpath:/com/dev/javatechonline/app1.properties"), 
              @PropertySource("classpath:/com/dev/javatechonline/app2.properties") 
})
public class MyClass { }

However, we can also write the same code in another way as below. The @PropertySource annotation is repeatable according to Java 8 conventions. Therefore, if we’re using Java 8 or higher, we can use this annotation to define multiple property locations. For example:

@Configuration 
@PropertySource("classpath:/com/dev/javatechonline/app1.properties")
@PropertySource("classpath:/com/dev/javatechonline/app2.properties") 
public class MyClass { }

♥ Note : If there is any conflict in names such as the same name of the properties, the last source read will always take precedence.

@Value

We can use this annotation to inject values into fields of Spring managed beans. We can apply it at field or constructor or method parameter level. For example, let’s first define a property file, then inject values of properties using @Value.

server.port=9898
server.ip= 10.10.10.9
emp.department= HR
columnNames=EmpName,EmpSal,EmpId,EmpDept

Now inject the value of server.ip using @Value as below:

@Value("${server.ip}")
private String serverIP;

@Value for default Value

Suppose we have not defined a property in the properties file. In that case we can provide a default value for that property. Here is the example:

@Value("${emp.department:Admin}")
private String empDepartment;

Here, the value Admin will be injected for the property emp.department. However, if we have defined the property in the properties file, the value of property file will override it.

♥ Note : If the same property is defined as a system property and also in the properties file, then the system property would take preference.

@Value for multiple values

Sometimes, we need to inject multiple values of a single property. We can conveniently define them as comma-separated values for the single property in the properties file. Further, we can easily inject them into property that is in the form of an array. For example:

@Value("${columnNames}")
private String[] columnNames;

Spring Boot Specific Annotations

Now it’s time to extend our article ‘Spring Boot Annotations with Examples’ with Spring Boot Specific Annotations. They are discovered by Spring Boot Framework itself. However, most of them internally use annotations provided by Spring Framework and extend them further.

@SpringBootApplication (@Configuration + @ComponentScan + @EnableAutoConfiguration)

Everyone who worked on Spring Boot must have used this annotation. When we create a Spring Boot Starter project, we receive this annotation as a gift. This annotation applies at the main class which has main () method. The Main class serves two purposes in a Spring Boot application: configuration and bootstrapping. In fact @SpringBootApplication is a combination of three annotations with their default values. They are @Configuration, @ComponentScan, and @EnableAutoConfiguration. Therefore, we can also say that @SpringBootApplication is a 3-in-1 annotation.

@EnableAutoConfiguration: enables the auto-configuration feature of Spring Boot.
@ComponentScan: enables @Component scan on the package to discover and register components as beans in Spring’s application Context.
@Configuration: allows to register extra beans in the context or imports additional configuration classes.

We can also use above three annotations in place of @SpringBootApplication if we want any customized behavior of them.

@EnableAutoConfiguration

@EnableAutoConfiguration enables auto-configuration of beans present in the classpath in Spring Boot applications. In a nutshell, this annotation enables Spring Boot to auto-configure the application context. Therefore, it automatically creates and registers beans that are part of the included jar file in the classpath and also the beans defined by us in the application. For example, while creating a Spring Boot starter project when we select Spring Web and Spring Security dependency in our classpath, Spring Boot auto-configures Tomcat, Spring MVC and Spring Security for us.

Moreover, Spring Boot considers the package of the class declaring the @EnableAutoConfiguration as the default package. Therefore, if we apply this annotation in the root package of the application, every sub-packages & classes will be scanned. As a result, we won’t need to explicitly declare the package names using @ComponentScan.

Furthermore, @EnableAutoConfiguration provides us two attributes to manually exclude classes from auto-configurations. If we don’t want some classes to be auto-configured, we can use exclude attribute to disable them. Another attribute is excludeName to declare a fully qualified list of classes to exclude. For example, below are the codes.

Use of ‘exclude’ in @EnableAutoConfiguration 

@Configuration
@EnableAutoConfiguration(exclude={WebSocketMessagingAutoConfiguration.class})
public class MyWebSocketApplication {
        public static void main(String[] args) {
            ...
        }
}

Use of ‘excludeName’ in @EnableAutoConfiguration 

@Configuration
@EnableAutoConfiguration(excludeName = {"org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration"})
public class MyWebSocketApplication {
        public static void main(String[] args) {
            ...
        }
}

@SpringBootConfiguration

This annotation is a part of Spring Boot Framework. However, @SpringBootApplication inherits from it. Therefore, If an application uses @SpringBootApplication, it is already using @SpringBootConfiguration. Moreover, It acts as an alternative to the @Configuration annotation. The primary difference is that @SpringBootConfiguration allows configuration to be automatically discovered. @SpringBootConfiguration indicates that the class provides configuration and also applied at the class level. Particularly, this is useful in case of unit or integration tests. For example, observe the below code:

@SpringBootConfiguration
public class MyApplication {

     public static void main(String[] args) {
          SpringApplication.run(MyApplication.class, args);
     }
     @Bean
     public IEmployeeService employeeService() {
         return new EmployeeServiceImpl();
     }
}

@ConfigurationProperties

Spring Framework provides various ways to inject values from the properties file. One of them is by using @Value annotation. Another one is by using @ConfigurationProperties on a configuration bean to inject properties values to a bean. But what is the difference among both ways and what are the benefits of using @ConfigurationProperties, you will understand it at the end. Now Let’s see how to use @ConfigurationProperties annotation to inject properties values from the application.properties or any other properties file of your own choice.

First, let’s define some properties in our application.properties file as follows. Let’s assume that we are defining some properties of our development working environment. Therefore, representing properties name with prefix ‘dev’.

dev.name=Development Application
dev.port=8090
dev.dburl=mongodb://mongodb.example.com:27017/
dev.dbname=employeeDB
dev.dbuser=admin
dev.dbpassword=admin

Now, create a bean class with getter and setter methods and annotate it with @ConfigurationProperties.

@ConfigurationProperties(prefix="dev")
public class MyDevAppProperties {
      private String name;
      private int port;
      private String dburl;
      private String dbname;
      private String dbuser;
      private String dbpassword;

    //getter and setter methods
}

Here, Spring will automatically bind any property defined in our property file that has the prefix ‘dev’ and the same name as one of the fields in the MyDevAppProperties class.

Next, register the @ConfigurationProperties bean in your @Configuration class using the @EnableConfigurationProperties annotation.

@Configuration
@EnableConfigurationProperties(MyDevAppProperties.class)
public class MySpringBootDevApp { }

Finally create a Test Runner to test the values of properties as below.

@Component
public class DevPropertiesTest implements CommandLineRunner {

      @Autowired
      private MyDevAppProperties devProperties;

      @Override
      public void run(String... args) throws Exception {
           System.out.println("App Name = " + devProperties.getName());
           System.out.println("DB Url = " + devProperties.getDburl());
           System.out.println("DB User = " + devProperties.getDbuser());
      }
}

We can also use the @ConfigurationProperties annotation on @Bean-annotated methods.

@EnableConfigurationProperties

In order to use a configuration class in our project, we need to register it as a regular Spring bean. In this situation @EnableConfigurationProperties annotation support us. We use this annotation to register our configuration bean (a @ConfigurationProperties annotated class) in a Spring context. This is a convenient way to quickly register @ConfigurationProperties annotated beans. Moreover, It is strictly coupled with @ConfiguratonProperties. For example, you can refer @ConfigurationProperties from the previous section.

@EnableConfigurationPropertiesScan

@EnableConfigurationPropertiesScan annotation scans the packages based on the parameter value passed into it and discovers all classes annotated with @ConfiguratonProperties under the package. For example, observe the below code:

@SpringBootApplication
@EnableConfigurationPropertiesScan(“com.dev.spring.test.annotation”)
public class MyApplication { }

From the above example, @EnableConfigurationPropertiesScan will scan all the @ConfiguratonProperties annotated classes under the package “com.dev.spring.test.annotation” and register them accordingly.

@EntityScan and @EnableJpaRepositories

Spring Boot annotations like @ComponentScan, @ConfigurationPropertiesScan and even @SpringBootApplication use packages to define scanning locations. Similarly @EnityScan and @EnableJpaRepositories also use packages to define scanning locations. Here, @EntityScan is used for discovering entity classes, whereas @EnableJpaRepositories for JPA repository classes by convention. These annotations are generally used when your discoverable classes are not under the root package or its sub-packages of your main application. Remember that, @EnableAutoConfiguration(as part of @SpringBootApplication) scans all the classes under the root package or its sub-packages of your main application. Therefore, If the repository classes or other entity classes are not placed under the main application package or its sub package, then the relevant package(s) should be declared in the main application configuration class with @EntityScan and @EnableJpaRepositories annotation accordingly. For example, observe the below code:

@EntityScan(basePackages = "com.dev.springboot.examples.entity")

@EnableJpaRepositories(basePackages = "com.dev.springboot.examples.jpa.repositories")

Links to Other Annotations

As stated in the introduction section of our article ‘Spring Boot Annotations With Examples’, we will discuss all annotations we generally use in a Spring Boot web Application, Below are the links to continue with ‘Spring boot Annotations with Examples’: