Mike's Blog

Getting Spring Certified 3 | Reviewing the Study guide

By: Micheal Arsenault

Posted: December 26, 2020| Modified: January 5, 2021

Reading Time: 7 minutes

Tags: certification Java Spring

resources:




What is the preferred way to close an application context? Does Spring Boot do this for you?


NON-WEB CONTEXT

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class Boot {

    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

        // add a shutdown hook for the above context...
        ctx.registerShutdownHook();

        // app runs here...

        // main method exits, hook is called prior to the app shutting down...
    }
}

It’s important to note here the ‘Boot’ class here has nothing to do with Spring Boot. This will link the application to the JVM and upon JVM shutdown the ApplicationContext to close.


Additionally, there is a close() function that will close the application context and destroy al of it’s beans as well. Additionally this will remove a JVM linked shutdown hook if one is registered.

If you’re using Spring to create a web based application it will link itself with the container in order to shutdown properly; otherwise you’ll need to register a shutdown hook yourself.


Spring-Boot shutdown Hook

Spring boot’s SpringApplication itself registers a shutdown hook with the JVM. There’s also the capability for an application to create a bean that implements the ExitCodeGenerator Interface. In the below example from Spring’s Boot documentation you can see

@SpringBootApplication
public class ExitCodeApplication {

    @Bean
    public ExitCodeGenerator exitCodeGenerator() {
        return () -> 42;
    }

    public static void main(String[] args) {
        System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
    }

}

WEB Hooks


Spring integrates the ApplicationContext lifecycle with the web application itself so no manual steps are needed for the web application context.

This section applies only to non-web applications. Spring’s web-based ApplicationContext implementations already have code in place to gracefully shut down the Spring IoC container when the relevant web application is shut down.

Spring Core Documentation link icon




Next part of the study guide has multiple sections:

Can you describe:

* Dependency injection using Java configuration?
* Dependency injection using annotations (@Autowired)?
* Component scanning, Stereotypes?–Scopes for Spring beans? 
* What is the default scope?

I want to take a second and mention how I don’t like the question above. It mentions using “Java configuration” and then mentions “using annotations”; this to me is a bit confusing as annotations are Java code. Regardless, I keep this in my head as thinking of the distinction of using Java class(es) as a central place to create Spring beans. I also will be splitting up some of the above questions based upon how large these posts become.


Dependency injection using Java configuration?

      Java configuration would look like below. You can see that we’re explicitly instantiating the beans inside of the methods.

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer
    propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
    @Bean
    @Profile("test")
    UserRepo userRepoTest() {
        return new HashMapUserRepo();
    }

    @Bean
    @Profile("test")
    Greeter greeterTest(@Value("${greeting.test}") String greeting) {
        return new GreeterImpl(greeting);
    }

    @Bean
    @Profile("prod")
    Greeter greeterProd(@Value("${greeting.prod}") String greeting) {
        return new GreeterImpl(greeting);
    }

    @Bean
    @Profile("prod")
    UserRepo prodRepo() {
        return new HashMapUserRepo();
    }
}

While the above code is calling methods like normal, it’s important to understand that by using the @Configuration annotation you’re explicitly telling Spring to intercept method calls using Spring’s AOP methods. This means beans are still created in a prototype like fashion regardless of the actual usage of the method being called. So if you call any method you’ll only really be given the same object each time. Additionally, if you don’t use the @Configuration annotation on a class then you’ll have different effects when creating @Bean methods especially on intr-bean calls.


Full @Configuration vs “lite” @Bean mode?

When @Bean methods are declared within classes that are not annotated with @Configuration, they are referred to as being processed in a “lite” mode. Bean methods declared in a @Component or even in a plain old class are considered to be “lite”, with a different primary purpose of the containing class and a @Bean method being a sort of bonus there. For example, service components may expose management views to the container through an additional @Bean method on each applicable component class. In such scenarios, @Bean methods are a general-purpose factory method mechanism.

Unlike full @Configuration, lite @Bean methods cannot declare inter-bean dependencies. Instead, they operate on their containing component’s internal state and, optionally, on arguments that they may declare. Such a @Bean method should therefore not invoke other @Bean methods. Each such method is literally only a factory method for a particular bean reference, without any special runtime semantics. The positive side-effect here is that no CGLIB subclassing has to be applied at runtime, so there are no limitations in terms of class design (that is, the containing class may be final and so forth).

In common scenarios, @Bean methods are to be declared within @Configuration classes, ensuring that “full” mode is always used and that cross-method references therefore get redirected to the container’s lifecycle management. This prevents the same @Bean method from accidentally being invoked through a regular Java call, which helps to reduce subtle bugs that can be hard to track down when operating in “lite” mode.

Spring Core Documentation: Full @Configuration vs “lite” @Bean mode? link icon


I’ve also included the below example from the documentation where they have a simple configuration class:


@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        return new BeanOne(beanTwo());
    }

    @Bean
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

      It’s also important to think of Java annotation like XML configuration when it comes to integrating multiple disparate sources into a unified area. This means that you can have one Java configuration that will pull in XML files, as well as other @Configuration annotated classes

@Configuration
public class ServiceConfig {

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

@Configuration
public class RepositoryConfig {

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

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}
  • Injecting Dependencies on Imported @Bean Definitions
  • You can see here that we’re pulling in configuration metadata from other classes, but this could just as easily have been XML documents
  • Really one of the major points to understand, is that with this you’re able to create a central repository where you instantiate and setup objects to be used throughout your application.

Alright, this has gone on long enough and I’ll begin with this next: Dependency injection using annotations (@Autowired)