Spring Boot ApplicationContext

The primary job of the ApplicationContext is to manage beans.
let’s create a configuration class to define our AccountService class as a Spring bean:

@Configuration
public class AccountConfig {

  @Bean
  public AccountService accountService() {
    return new AccountService(accountRepository());
  }

  @Bean
  public AccountRepository accountRepository() {
    return new AccountRepository();
  }
}

Java configuration typically uses @Bean-annotated methods within a @Configuration class. The @Bean annotation on a method indicates that the method creates a Spring bean. Moreover, a class annotated with @Configuration indicates that it contains Spring bean configurations.

AnnotationConfigApplicationContext

ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class);
AccountService accountService = context.getBean(AccountService.class);

AnnotationConfigWebApplicationContext

is a web-based variant of AnnotationConfigApplicationContext.

We may use this class when we configure Spring’s ContextLoaderListener servlet listener or a Spring MVC DispatcherServlet in a web.xml file.

Moreover, from Spring 3.0 onward, we can also configure this application context container programmatically. All we need to do is implement the WebApplicationInitializer interface:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    context.register(AccountConfig.class);
    context.setServletContext(container);

    // servlet configuration
  }
}

@Autowire  ApplicationContext

You can Autowire the ApplicationContext, either as a field

@Autowired
private ApplicationContext context;

or a method

@Autowired
public void context(ApplicationContext context) { this.context = context; }

Finally use

context.getBean(SomeClass.class)

References
https://www.baeldung.com/spring-application-context
https://stackoverflow.com/questions/34088780/how-to-get-bean-using-application-context-in-spring-boot

Dependency Injection in Spring Boot

Dependency Injection in Spring can be done through constructors, setters or fields.

Constructor-Based Dependency Injection

@Configuration
public class AppConfig {

    @Bean
    public Item item1() {
        return new ItemImpl1();
    }

    @Bean
    public Store store() {
        return new Store(item1());
    }
}

The @Configuration annotation indicates that the class is a source of bean definitions. We can also add it to multiple configuration classes.

We use the @Bean annotation on a method to define a bean. If we don’t specify a custom name, then the bean name will default to the method name.

For a bean with the default singleton scope, Spring first checks if a cached instance of the bean already exists, and only creates a new one if it doesn’t. If we’re using the prototype scope, the container returns a new bean instance for each method call.

Setter-Based Dependency Injection

@Bean
public Store store() {
    Store store = new Store();
    store.setItem(item1());
    return store;
}

Field-Based Dependency Injection

public class Store {
    @Autowired
    private Item item; 
}

While constructing the Store object, if there’s no constructor or setter method to inject the Item bean, the container will use reflection to inject Item into Store.

Autowiring Dependencies

Wiring allows the Spring container to automatically resolve dependencies between collaborating beans by inspecting the beans that have been defined.

There are four modes of autowiring a bean using an XML configuration:

no: the default value – this means no autowiring is used for the bean and we have to explicitly name the dependencies.
byName: autowiring is done based on the name of the property, therefore Spring will look for a bean with the same name as the property that needs to be set.
byType: similar to the byName autowiring, only based on the type of the property. This means Spring will look for a bean with the same type of the property to set. If there’s more than one bean of that type, the framework throws an exception.
constructor: autowiring is done based on constructor arguments, meaning Spring will look for beans with the same type as the constructor arguments.

For example, let’s autowire the item1 bean defined above by type into the store bean:

@Bean(autowire = Autowire.BY_TYPE)
public class Store {
    
    private Item item;

    public setItem(Item item){
        this.item = item;    
    }
}

We can also inject beans using the @Autowired annotation for autowiring by type:

public class Store {
    
    @Autowired
    private Item item;
}

If there’s more than one bean of the same type, we can use the @Qualifier annotation to reference a bean by name:

public class Store {
    
    @Autowired
    @Qualifier("item1")
    private Item item;
}

References
https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring

Create Indexes in Spring Data MongoDB

Using @Indexed
This annotation marks the field as indexed in MongoDB:

@QueryEntity
@Document
public class User {
    @Indexed
    private String name;
    
    ... 
}

but as of Spring Data MongoDB 3.0, automatic index creation is turned off by default.

We can, however, change that behavior by explicitly overriding autoIndexCreation() method in our MongoConfig:

public class MongoConfig extends AbstractMongoClientConfiguration {

    // rest of the config goes here

    @Override
    protected boolean autoIndexCreation() {
        return true;
    }
}

We can create other types of index using these attributes :

@Indexed
@TextIndexed
@HashIndexed
@GeoSpatialIndexed
@WildcardIndexed
@GeoIndexed

Create an Index Programmatically

mongoOps.indexOps(User.class).
  ensureIndex(new Index().on("name", Direction.ASC));

Compound Indexes

MongoDB supports compound indexes, where a single index structure holds references to multiple fields.

@QueryEntity
@Document
@CompoundIndexes({
    @CompoundIndex(name = "email_age", def = "{'email.id' : 1, 'age': 1}")
})
public class User {
    //
}

References
https://www.baeldung.com/spring-data-mongodb-index-annotations-converter
https://careydevelopment.us/blog/spring-boot-and-mongotemplate-how-to-handle-a-full-text-search
https://spring.io/blog/2014/07/17/text-search-your-documents-with-spring-data-mongodb
https://mongodb.github.io/mongo-java-driver/3.4/driver/tutorials/indexes/
https://www.mongodb.com/docs/manual/indexes/

Initialize MongoDB Repositories using ApplicationContextAware in Spring Boot

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DB.mongoTemplate=applicationContext.getBean(MongoTemplate.class);
        DB.monitoringItemRepository = applicationContext.getBean(MonitoringItemRepository.class);
    }
}
public class DB {
    public static MongoTemplate mongoTemplate=null;
    public static MonitoringItemRepository monitoringItemRepository = null;
}

References
https://zetcode.com/springboot/applicationcontext/

Configure Spring Boot to Connect to MongoDB with Credential

@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
    /*
     * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance.
     */
    public MongoClient mongoClient() {
        //String connectionString = "mongodb://username:password@localhost:27017/?authSource=admin&authMechanism=SCRAM-SHA-1";
        MongoCredential credential = MongoCredential.createScramSha256Credential("username", "admin", "password".toCharArray());
        MongoClient mongoClient = MongoClients.create(
                MongoClientSettings.builder()
                        .applyToClusterSettings(builder ->
                                builder.hosts(Arrays.asList(new ServerAddress("localhost", 27017))))
                        .credential(credential)
                        .build());
        return mongoClient;
    }

    @Override
    protected String getDatabaseName() {
        return "databaseName";
    }

    @Override
    public Collection getMappingBasePackages() {
        return Collections.singleton("net.pupli");
    }
}

References
https://www.baeldung.com/spring-data-mongodb-tutorial
https://www.mongodb.com/docs/drivers/java/sync/current/fundamentals/auth/
https://www.mongodb.com/docs/manual/reference/connection-string/

Install RabbitMQ using Quick Start Script on Ubuntu 20.04

Cloudsmith Quick Start Script

#!/usr/bin/sh

sudo apt-get install curl gnupg apt-transport-https -y

## Team RabbitMQ's main signing key
curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
## Cloudsmith: modern Erlang repository
curl -1sLf https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/gpg.E495BB49CC4BBE5B.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg > /dev/null
## Cloudsmith: RabbitMQ repository
curl -1sLf https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/gpg.9F4587F226208342.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg > /dev/null

## Add apt repositories maintained by Team RabbitMQ
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
## Provides modern Erlang/OTP releases
##
deb [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/ubuntu bionic main
deb-src [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/ubuntu bionic main

## Provides RabbitMQ
##
deb [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/ubuntu bionic main
deb-src [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/ubuntu bionic main
EOF

## Update package indices
sudo apt-get update -y

## Install Erlang packages
sudo apt-get install -y erlang-base \
                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
                        erlang-runtime-tools erlang-snmp erlang-ssl \
                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

## Install rabbitmq-server and its dependencies
sudo apt-get install rabbitmq-server -y --fix-missing

PackageCloud Quick Start Script

#!/usr/bin/sh

sudo apt-get install curl gnupg apt-transport-https -y

## Team RabbitMQ's main signing key
curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
## Launchpad PPA that provides modern Erlang releases
curl -1sLf "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xf77f1eda57ebb1cc" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/net.launchpad.ppa.rabbitmq.erlang.gpg > /dev/null
## PackageCloud RabbitMQ repository
curl -1sLf "https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/io.packagecloud.rabbitmq.gpg > /dev/null

## Add apt repositories maintained by Team RabbitMQ
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
## Provides modern Erlang/OTP releases
##
## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
deb [signed-by=/usr/share/keyrings/net.launchpad.ppa.rabbitmq.erlang.gpg] http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
deb-src [signed-by=/usr/share/keyrings/net.launchpad.ppa.rabbitmq.erlang.gpg] http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main

## Provides RabbitMQ
##
## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
deb [signed-by=/usr/share/keyrings/io.packagecloud.rabbitmq.gpg] https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
deb-src [signed-by=/usr/share/keyrings/io.packagecloud.rabbitmq.gpg] https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
EOF

## Update package indices
sudo apt-get update -y

## Install Erlang packages
sudo apt-get install -y erlang-base \
                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
                        erlang-runtime-tools erlang-snmp erlang-ssl \
                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

## Install rabbitmq-server and its dependencies
sudo apt-get install rabbitmq-server -y --fix-missing

References
https://www.rabbitmq.com/install-debian.html#apt-quick-start-cloudsmith
https://www.rabbitmq.com/install-debian.html#apt-quick-start-packagecloud

Add Expires Headers to .htaccess File in WordPress

Making sure mod_expires is enabled

sudo a2enmod expires
systemctl restart apache2

Add Expires Headers to .htaccess

To add Expires Headers to your site, you need to edit the .htaccess file.

Simply download the .htaccess file from the root of your host (it may be hidden) and add the code below:

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"
</IfModule>
## EXPIRES CACHING ##

References
https://electrictoolbox.com/apache-mod-expires-browser-caching/
https://betterstudio.com/blog/add-expires-headers-htaccess/

Disable Directory Browsing In WordPress

To disable directory browsing in WordPress all you need to do is add a single line of code in your WordPress site’s .htaccess file located in the root directory of your website.
Once connected to your website, you will find a .htaccess file in your site’s root directory. .htaccess is a hidden file, and if you can not find it on your server, you need to make sure that you have enabled your FTP client to show hidden files.
Now at the end of your WordPress generated code in the .htaccess file simply add this line at the bottom:

Options All -Indexes

References
https://bloggingwizard.com/disable-directory-browsing-wordpress/
https://www.wpbeginner.com/wp-tutorials/disable-directory-browsing-wordpress/