Kategorie: Design Patterns

  • Inversion of Control – Part III – Dependency Injection in Java Spring II (Example)

    I will continue with using the AlertService from part 2 of the series, to show how to utilise Dependency Injection in Spring with a more common situation. Let us start with the MessageServices and bring them under control of the BeanFactory in Spring by annotating them as a Component.

    @Component
    public class EmailMessageService implements MessageService {
        ...
    }
    
    @Component
    public class SlackMessageService implements MessageService {
        ...
    }
    

    One of these Components is the DiscFullAlertService bean. We will inject the dependency to a MessageService Bean via constructor injection.

    package com.vividbreeze.designpattern.spring.di;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    
    @Component
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
        @Autowired
        public DiscFullAlertService(MessageService messageService) {
            super (messageService);
        }
    
        @Override
        public void processAlert(String receiver) {
            messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }
    

    Let us now run the application

    @ComponentScan
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(FireAlert.class);
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert(receiver);
        }
    }
    

    It looks like we might run into problems here, as we want to inject a MessageService (the abstract super-class), but there are two beans that implement the MessageService: EmailMessageService and SlackMessageService. You might find the following message in the console:

    ... nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.vividbreeze.designpattern.spring.di.MessageService' available: expected single matching bean but found 2: emailMessageService,slackMessageService
    

     

    Configurations

    So the BeanFactory is confused which implementation to inject into the DiscFullAlertService. One solution would be to configure the BeanFactory so that it knows which implementation to choose. In this configuration, you are able to instantiate and register a Bean with the BeanFactory, so it later can be injected.

    package com.vividbreeze.designpattern.spring.di;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class AlertConfiguration {
    
        @Bean
        public MessageService messageService() {
            return new EmailMessageService();
        }
    }
    

    The class is annotated as a class that contains the configuration (@Configuration). The configuration is implemented in form of beans (or optionally an XML-file). The bean-name is the name of the method that is annotated with @Bean (messageService, not getMessageService). This method returns the instance of the bean that is then registered with the BeanFactory. After the initialisation, a ComponentScan is performed. So when it reaches

    @Autowired
    public DiscFullAlertService(MessageService messageService) {
        super (messageService);
    }
    

    it the BeanFactory already has a registered Bean „messageService“ and injects it in the messageService attribute of DiscFullAlertService. Notice that in our main-method, we pass the Configuration class when we initialise the ApplicationContext and we don’t perform a ComponentScan here.

    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(AlertConfiguration.class);
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert(receiver);
        }
    }

    The reason why I included the ComponentScan in the Configuration class will become more obvious when we work with a different Configuration for unit-tests. As mentioned in the previous blog-post where we might not be able to send e-mails or Slack-messages from our local computers. Thus we can use a MockMessageService that just logs the message to the console.

    @Component
    public class MockMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(MockMessageService.class);
    
        @Override
        public void sendMessage(String subject, String message, String receiver) {
            LOG.debug("MockMessageService - subject: " + subject + ", receiver: " + receiver + ", message: " + message);
        }
    }
    

    The instance of this class will also be annotated as a component so we can access it later via context.getBean(). The configuration will then look like this

    @Configuration
    @ComponentScan
    public class AlertTestConfiguration {
    
        //@Bean
        public MessageService messageService() {
            return new MockMessageService();
        }
    }
    

    The unit test can now look like this

    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
    
        ApplicationContext context = new AnnotationConfigApplicationContext(AlertTestConfiguration.class);
    
        @Test
        public void sendAlertMessage() {
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert("vividbreeze");
        }
    }
    

    Debugging

    The dependencies are resolved during run-time. If you have many beans with lots of dependencies your application might become more prone to errors. You can see which beans are initialised under which name during start-up (when the ApplicationContext is instantiated and initialised). This log message might be a bit confusing. You can also list all beans that are registered with the BeanFactory using the following snippet

    ApplicationContext context =
            new AnnotationConfigApplicationContext(FireAlert.class);
    
    String[] beanNames = context.getBeanDefinitionNames();
    for (String beanname: beanNames) {
        LOG.debug(">>> " + beanname + " - " + context.getBean(beanname).toString());
    }

    Remarks

    This example should give an overview of how to use the Spring Framework in a simple real-life situation. I highly recommend to consult other tutorials and to experiment with small sample applications to gain a better understanding of Dependency Injection in Spring.

     

     

  • Inversion of Control – Part III – Dependency Injection in Java Spring I

    As I explained in the blog post about Inversion of Control, your code can be controlled not only by implementing an IoC Design Pattern within your code, by a framework that controls (part of) your code, but also by an entity, that you don’t have direct control over, such as a Servlet Container that controls your code in a certain behaviour. Java Spring is a framework that takes control over part of your code. One of the key features of Spring is an extensive use of Dependency Injection.

    Components in Spring

    Firstly, Spring manages your beans; in this case, instances of Java classes. You can tell Spring which instances of classes should be controlled by Spring by either using annotations or XML-configuration files. In this introduction, I will solely focus on annotations, to not cause too much confusion. I will focus on XML-configuration in a later blog post.

    Alle components that Spring should take control of, have to be annotated. The most basic annotation is @Component on a class level.

    package com.vividbreeze.spring;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class FormalGreeting {
        public void sayHello() {
            System.out.println("Good day, Madam or Sir. How may I assist you?");
        }
    }
    

    Spring now needs to know that it should take control of this bean. Spring does this by a so-called ComponentScan

    package com.vividbreeze.spring;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan
    public class GreetingExample {
    
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(GreetingExample.class);
    
            context.getBean(FormalGreeting.class).sayHello();
        }
    }
    

    Spring scans all classes in the package com.vividbreeze.spring (and its sub-packages by default) that are annotated with (@Component). These classes (beans) are then instantiated and controlled by the BeanFactory. This BeanFactory can be accessed via the ApplicationContext. The ApplicationContext is bound to the class that is annotated with @ComponentScan. Notice, that the component scan is performed, not until the ApplicationContext is created (new ApplicationConfigApplicationContext(…)).

    You can access a bean under Spring with context.getBean (bean-name). By default, beans are singletons, i.e. only one shared instance of a bean will be managed by Spring. The other option would be non-singleton, i.e. everytime you access a bean with getBean (...) a new instance will be created. The BeanFactory stores beans either by the class-name or a separate bean-name, that you pass as an attribute to the Component annotation.

    @Component ("commonGreeting")
    public class FormalGreeting implements Greeting {
        public void sayHello() {
            System.out.println("Good day, Madam or Sir. How may I assist you?");
        }
    }
    
    @ComponentScan
    public class GreetingExample {
    
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(GreetingExample.class);
    
            ((FormalGreeting)context.getBean("commonGreeting")).sayHello();
        }
    }
    

     

    Dependency Injection in Spring (autowiring)

    This might only seem of a minor benefit so far. The real advantage of Spring is the so-called auto-wiring, where instances of beans are injected into other beans. You can either inject dependencies on an attribute level (as shown above) or on a setter or on the constructor.

    Attribute Level Dependency Injection

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        @Autowired
        private FormalGreeting greeting;
    
        public void process() {
            greeting.sayHello();
        }
    }
    

    When Spring scans the classes annotated with @Component, the BeanFactory will instantiate GreetingProcessor and FormalGreeting. It will then see that GreetingProcessor contains an @Autowired attribute of type FormalGreeting. The BeanFactory finds a bean with the name „FormalGreeting“ and wires it to greeting in the GreetingProcessor Bean.

    So far this is an advantage, as you don’t have to worry about instantiating (and managing) dependencies anymore.

    Setter Dependency Injection

    When you use setter injection during runtime you might notice that the bean was not injected and is null. You can avoid this by annotating the setter with @Required.

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        private FormalGreeting greeting;
    
        @Autowired
        public void setFormalGreeting(FormalGreeting greeting) {
            this.greeting = greeting;
        }
    
        public void process() {
            greeting.sayHello();
        }
    }

    Class Dependency Injection

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        private FormalGreeting greeting;
    
        @Autowired
        public GreetingProcessor (FormalGreeting greeting) {
            this.greeting = greeting;
        }
    
        public void process() {
            greeting.sayHello();
        }
    }

    Circular Dependencies

    We might have dependencies like this: Bean A is instantiated with Bean B, which in turn is instantiated with Bean C. In this case, Spring creates bean C first, then Bean B and injects Bean C into it, then it will create bean A and injects bean B into it.

    There might be some situations where the dependencies are circular, i.e. bean A is instantiated with bean B that, in turn, instantiate with bean A.

    @Component
    public class ComponentA {
    
        private ComponentB componentB;
    
        @Autowired
        private ComponentA (ComponentB componentB) {
            this.componentB = componentB;
        }
    }
    
    @Component
    public class ComponentB {
    
        private ComponentA componentA;
    
        @Autowired
        private ComponentB(ComponentA componentA) {
            this.componentA = componentA;
        }
    }
    
    @ComponentScan
    public class CircularComponentExample {
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(CircularComponentExample.class);
    
            context.getBean(ComponentA.class);
        }
    }
    

    In the console, you will see something like this

    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'componentA': Requested bean is currently in creation: Is there an unresolvable circular reference?
    

    It might seem like a far-fetched example, however, in reality, this happens once in a while especially if you have complex nested dependencies between objects. How can you solve the problem? Simply, try to solve circular dependencies by breaking them up or use attribute or setter-injection, as here the injections are fully resolved when the attribute is used the first time. In the next example, the componentA bean is created upon request when calling context.getBean (ComponentA.class). Alternatively, you can use setter-injection.

    @Component
    public class ComponentA {
    
        @Autowired
        private ComponentB componentB;
    
        private ComponentA () {
            //
        }
    }
    @Component
    public class ComponentB {
    
        @Autowired
        private ComponentA componentA;
    
        private ComponentB() {
        }
    }

    In the console, you can see how Spring is now handling the situation

    08:10:32.536 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'org.springframework.context.event.internalEventListenerFactory' to allow for resolving potential circular references
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'org.springframework.context.event.internalEventListenerFactory'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'circularComponentExample'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'circularComponentExample'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'circularComponentExample' to allow for resolving potential circular references
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'circularComponentExample'
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'componentA'
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'componentA'
    08:10:32.545 [main] DEBUG ...InjectionMetadata - Registered injected element on class [com.vividbreeze.spring.ComponentA]: AutowiredFieldElement for private com.vividbreeze.spring.ComponentB com.vividbreeze.spring.ComponentA.componentB
    08:10:32.545 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'componentA' to allow for resolving potential circular references
    08:10:32.547 [main] DEBUG ...InjectionMetadata - Processing injected element of bean 'componentA': AutowiredFieldElement for private com.vividbreeze.spring.ComponentB com.vividbreeze.spring.ComponentA.componentB
    08:10:32.548 [main] DEBUG org.springframework.core.annotation.AnnotationUtils - Failed to meta-introspect annotation interface ...Autowired: java.lang.NullPointerException
    08:10:32.552 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'componentB'
    08:10:32.552 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'componentB'
    08:10:32.553 [main] DEBUG ...InjectionMetadata - Registered injected element on class [com.vividbreeze.spring.ComponentB]: AutowiredFieldElement for private com.vividbreeze.spring.ComponentA com.vividbreeze.spring.ComponentB.componentA
    08:10:32.553 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'componentB' to allow for resolving potential circular references
    08:10:32.554 [main] DEBUG ...InjectionMetadata - Processing injected element of bean 'componentB': AutowiredFieldElement for private com.vividbreeze.spring.ComponentA com.vividbreeze.spring.ComponentB.componentA
    08:10:32.554 [main] DEBUG org.springframework.core.annotation.AnnotationUtils - Failed to meta-introspect annotation interface ...Autowired: java.lang.NullPointerException
    08:10:32.554 [main] DEBUG ...DefaultListableBeanFactory - Returning eagerly cached instance of singleton bean 'componentA' that is not fully initialized yet - a consequence of a circular reference
    08:10:32.555 [main] DEBUG ...AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'componentB' to bean named 'componentA'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'componentB'
    08:10:32.556 [main] DEBUG ...AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'componentA' to bean named 'componentB'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'componentA'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Returning cached instance of singleton bean 'componentB'
    

    There are other ways to deal with circular dependencies in Spring, such as the @Lazy annotation, where the injected bean creation will be completed when first used (and before as a proxy bean), the @PostConstruct and other.  I recommend, whenever possible, to try to avoid circular dependencies.

     

    Remarks

    You will find many discussion about which form of Dependency Injection to use. Personally, I find that dependencies should be made visible to others that use the class. Hence I avoid attribute injection, although it seems more elegant, especially if you want to inject many dependencies. However, if you have many dependencies in one class, it can be an indication of bad design and concerns might be not separated well enough. Fewer dependencies make a class easier to test and easier to understand. Constructor injection avoids that dependencies are set after the instantiation of a class and hence can be controlled from the outside. If this is changing the dependency during runtime, a setter to inject a dependency makes this clearly visible to others.

    The benefit of using Dependency Injection in Spring is that the IoC container of Spring dissolves, especially complex and nested injection chains. Hence it does a great deal of work from developers.

    This short introduction should give you a good base to learn more about Dependency Injection in Spring. Of course, there is more to DI in Spring. In the next blog post, I will use the Spring Framework with the example from the previous blog post.

  • Inversion of Control – Part II – Dependency Injection

    In the first part, I described what Inversion of Control (IoC) is and how it can be implemented using the classical GoF design patterns. In this post, I will explain another implementation of IoC: Dependency Injection.

    I assume that you are familiar with programming to an interface (or abstract class) rather than classes, as you can easily switch the implementation (aka polymorphism, programming by contract).

    I will start right way with an example: Let us assume we want to send an alert via different mechanisms, such as an E-Mail and a Slack message. The Services that send a message, have a common interface: MessageService; the implementations are EmailMessageService and SlackMessageService. I won’t include that code for sending actual messages, as this would become too complicated. Instead, I will simply log the result to the console.

    package com.vividbreeze.designpattern.di;
    
    public interface MessageService {
        void sendMessage (String subject, String message, String receiver);
    }
    
    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class EmailMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(EmailMessageService.class);
    
        @Override
        public void sendMessage(String receiver, String subject, String message) {
    
            // Code to send an E-Mail message
    
            LOG.debug("E-Mail successfully sent.");
            LOG.debug("Subject: '" + subject + "'");
            LOG.debug("Receiver: '" + receiver + "'");
            LOG.debug("Message:");
            LOG.debug(message);
        }
    }
    
    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class SlackMessageService implements MessageService {
        private static final Logger LOG = LoggerFactory.getLogger(SlackMessageService.class);
    
        @Override
        public void sendMessage(String receiver, String subject, String message) {
    
            // Code to send message to a Slack Channel
    
            LOG.debug("Slack Message successfully sent.");
            LOG.debug("Topic: '" + subject + "'");
            LOG.debug("Receiver or Channel: '" + receiver + "'");
            LOG.debug("Message:");
            LOG.debug(message);
        }
    }

    I further have an abstract class for any kind of service that is responsible for processing the alert, such as sending a message to the correct receiver, e.g. when the disk is full an admin is notified via e-mail; when an exception in the code occurs during working hours, the developers are informed via Slack.

    package com.vividbreeze.designpattern.di;
    
    public abstract class AlertService {
    
        protected MessageService messageService;
    
        public AlertService(MessageService messageService) {
            this.messageService = messageService;
        }
    
        public abstract void processAlert(String receiver);
    }
    

     

    Constructor-Based Dependency Injection

    We can inject the dependency to the MessageService in the constructor. I will continue the example above and subclass the AlertService.

    package com.vividbreeze.designpattern.di;
    
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
    
        public DiscFullAlertService(MessageService messageService) {
            super (messageService);
        }
    
        @Override
        public void processAlert(String receiver) {
           messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }

    The following code shows how to put the pieces together and run the application.

    package com.vividbreeze.designpattern.di;
    
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            new DiscFullAlertService(new EmailMessageService()).processAlert(receiver);
        }
    }
    

    In the example above, the special AlertService or it subclasses do not know which MessageService will send the message (EmailMessageService or SlackMessageService) at runtime. So I will inject an instance of the appropriate Service when instantiating the DiscFullAlertService (in the constructor).

    When I write a test for the DiscFullAlertService, the system running the test, might not be capable of sending Emails or Slack messages (e.g. the development environment). In this case, we have to mock these services without having to change existing code. As we are using Dependency Injection, this has become fairly easy. I can initialise the DiscFullAlertService with a MockMessageService, that does not actually send a message, but only logs it on the console.

    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MockMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(MockMessageService.class);
    
        @Override
        public void sendMessage(String subject, String message, String receiver) {
            LOG.debug("MockMessageService - subject: " + subject + ", receiver: " + receiver + ", message: " + message);
        }
    }
    

    The test will then look like this

    package com.vividbreeze.designpattern.di;
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
        private MessageService mockMessageService;
    
        @BeforeEach
        public void setUp() {
            mockMessageService = new MockMessageService();
        }
    
        @Test
        public void sendAlertMessage() {
            new DiscFullAlertService(mockMessageService).processAlert("test-ops@vividbreeze.com");
        }
    }
    

     

    Setter-Based Dependency Injection

    We can also inject the dependency to the MessageService via a setter, instead of a constructor.

    package com.vividbreeze.designpattern.di;
    
    public abstract class AlertService {
    
        protected MessageService messageService;
    
        public void setMessageService(MessageService messageService) {
            this.messageService = messageService;
        }
    
        public abstract void processAlert(String receiver);
    }
    
    package com.vividbreeze.designpattern.di;
    
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
        @Override
        public void processAlert(String receiver) {
           messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }
    package com.vividbreeze.designpattern.di;
    
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            AlertService alertService = new DiscFullAlertService();
            alertService.setMessageService(new EmailMessageService());
            alertService.processAlert(receiver);
        }
    }
    package com.vividbreeze.designpattern.di;
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
        private MessageService mockMessageService;
    
        @BeforeEach
        public void setUp() {
    
            mockMessageService = new MockMessageService();
        }
    
        @Test
        public void sendAlertMessage() {
    
            AlertService alertService = new DiscFullAlertService();
            alertService.setMessageService(new EmailMessageService());
            alertService.processAlert("test-ops@vividbreeze.com");
        }
    }
    

    Remarks

    So we have seen that dependencies can be easily set by other objects at runtime. You might run into some interesting discussions about Dependency Injection. The arguments I have heard so far is that Dependency Injection increases the number of classes and hence make the code more difficult to understand, especially if you have many dependencies. I concur, as I rather deal with many simple classes that are easier to understand, than a few complex classes. In addition, you have the flexibility of changing implementation, which becomes especially useful when testing implementations. Dependency Injection might have an effect on performance, but I consider it negligible.

    In the subsequent blog post, I will explain how the Java Spring Framework can support you in using Dependency Injection.

  • Inversion of Control – Part I

    Why am I talking about Inversion of Control? I will use Spring (Boot) later on to build services. Spring is based on Dependency Injection. Dependency Injection is one possible implementation of Inversion of Control. Hence, it is reasonable to understand the basics of Inversion of Control (IoC) and how it can be implemented. Before I get to the Sprint implementation, I will explain the concept, the Design Patterns that use IoC and will write about Dependency Injection in Spring in a subsequent blog post.

    What is Inversion of Control?

    When you write an application (code) you are fully in control of the flow.

    public static void main(String args[]) {
    
        while (true) {
            Scanner scan = new Scanner(System.in);
            String text = scan.nextLine();
            System.out.println(text);
        }
    }
    

    However, quite often the control is handed over to a framework that is in control of your code.

    Take for example Java Servlets, that I explained in an earlier blog post. In your implementation of the HttpServlet class, you implement a method such as doGet() which handles HTTP GET requests. This method is called whenever a request is made to an URL you specify in your web.xml. Here the servlet container takes control of your class. This allows the elegant implementation of different Servlets that are all controlled the same way.

    public class HelloServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;
    
      public void init() throws ServletException {
        System.out.println("init()");
        super.init();
      }
    
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
        System.out.println("doGet()");
      }
    }

    Another example is Event Handling, e.g. in JavaScript. You can bind JavaScript code to an event on an element, e.g. object.addEventListener("click", myScript); Once you click on the element, the JavaScript Engine of your Browser will call myScript.

    document.getElementById("submitButton").addEventListener("click", submitForm);
    
    function submitForm() {
       var name = document.getElementById("name");
       // read elements and call service()-method
    }

    Basically, IoC separates what code is executed from when it is executed. Both parts know as little as possible about each other – there only connection is an interface or abstract class provided by the controlling code. Furthermore, IoC reduces code duplication and encourages the use of Interfaces instead of implementations.

    Implementations of Inversion of Control

    Some of the well-known Design Patterns by the GoF (Gang of Four –  E. Gamma, R. Helm, R. Johnson and J. Vlissides) implement the Inversion of Control, such as the Observer, Strategy, Factory or the Template design pattern. Other examples are the Service Locator or Dependency Injection. In the next part, we will take a further look at Dependency Injection. In the last part, we will see how Dependency Injection is used with the Spring Framework.