Saturday, April 6, 2019

Spring interview Questions and Answers

Spring - Injecting a Prototype Bean into a Singleton Bean Problem


If same scoped beans are wired together there's no problem. For example a singleton bean A injected into another singleton bean B. But if the bean A has the narrower scope say prototype scope then there's a problem.
To understand the problem let's see an example. We are going to have two beans MyPrototypeBean, scoped as prototype and MySingletonBean, scoped as singleton. We will inject the prototype bean into the singleton bean. We will also access MySingletonBean via method call context#getBean(MySingletonBean.class) multiple times. We are expecting (per prototype specifications) that a new prototype bean will be created and be injected into MySingletonBean every time.

Example Project


Dependencies and Technologies Used:
  • Spring Context 4.2.3.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.0.4
 Narrower Scope Bean Injection Example Select All  Download 
  • narrower-scoped-bean-injection
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AppConfig.java

    package com.logicbig.example;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Scope;
    
    @Configuration
    public class AppConfig {
    
        @Bean
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        public MyPrototypeBean prototypeBean() {
            return new MyPrototypeBean();
        }
    
        @Bean
        public MySingletonBean singletonBean() {
            return new MySingletonBean();
        }
    
        public static void main(String[] args) throws InterruptedException {
            AnnotationConfigApplicationContext context =
                    new AnnotationConfigApplicationContext(AppConfig.class);
            MySingletonBean bean = context.getBean(MySingletonBean.class);
            bean.showMessage();
            Thread.sleep(1000);
    
            bean = context.getBean(MySingletonBean.class);
            bean.showMessage();
        }
    }



    When to use Spring prototype scope?


    ·         Prototype scope = A new object is created each time it is injected/looked up. It will use new SomeBean() each time.
    ·         Singleton scope = The same object is returned each time it is injected/looked up. Here it will instantiate one instance of SomeBean and then return it each time.

    Prototype bean is created at the time of usage. So when you would like to have statefull beans there is strong need sometimes to have prototypes scope or when you don't wont to cache any values in beans. Prototype bean can be associated with one session or some call.
    Example:

    A data access object (DAO) is not typically configured as a prototype, because a typical DAO does not hold any conversational state; it was just easier for this author to reuse the core of the singleton diagram.
    Java Singleton VS Spring singleton
    The Java singleton is scoped by the Java class loader, the spring singleton is scoped by the container context.
    Which basically means that, in Java, you can be sure a singleton is a truly a singleton only within the context of the class loader which loaded it. Other class loaders should be capable of creating another instance of it (provided the class loaders are not in the same class loader hierarchy), despite of all your efforts in code to try to prevent it.
    In spring, if you could load your singleton class in two different contexts and then again we can break the singleton concept.

    Java considers something a singleton if it cannot create more than one instance of that class within a given class loader, whereas spring would consider something a singleton if it cannot create more than one instance of a class within a given container/context.

    Injecting Spring Prototype bean into Singleton bean


    Have you ever wonder why singleton is the default scope for Spring beans? Why isn’t it prototype?
    It’s not a random choice. It’s because the vast majority of business logic we create can be safely kept in stateless objects. And the best choice for stateless beans is the singleton scope. The prototype scope is better for stateful beans to avoid multithreading issues.
    Yet, sometimes you need to mix both and use a prototype bean in a singleton bean. This particular case is a bit tricky. In this article, I’m going to explain to you different ways of accessing prototypes in singletons
    When to use prototype beans?
    Before we fall into the pitfalls of injecting prototype into singleton beans, stop for a moment to think when you actually need such relation.
    Just because you use dependency injection in your project, it doesn’t mean you should avoid the new keyword like the plague. There is nothing wrong if you instantiate a stateful object on your own.
    Usually, we use the prototype scope for a stateful object when it has dependencies on other Spring beans. Why? Because the framework will autowire these dependencies for us.

    Prototype in singleton bean example

    Now consider the following compoistion of Spring beans.
    singleton-prototype relation diagram
    Let’s start with the right side of the diagram where a prototype bean depends on a singleton. No matter how many instances of MessageBuilders Spring creates, we expect they will always get the reference to the same ContentProcessor object. This part is easy.
    Next, the left side. By contrast, here a singleton bean depends on a prototype. When Spring creates the MessageService bean, it will also create a single instance of MessageBuilder. But just one. That’s all MessageService needs to be created.
    But hang on a minute.
    For this particular graph of objects, Spring creates only one instance for each bean definition. Even though one of them is a prototype. If we had another bean depending on MessageBuilder, it would get another instance of the prototype bean. But in this case, Spring creates only one.
    So what if you want a new instance of the prototype bean on every call to a particular method of the singleton bean? Not only when Spring creates this singleton?
    Don’t worry. There’re multiple solutions.
    You will see all possible options in a moment. But before I share them with you, we need a sample dependency between a prototype and a singleton for demonstration purpose.

    Prototype in singleton dependency demo

    We need a prototype, a singleton which depends on the prototype, and an automated test to verify the number of prototype instances.
    Let’s write each step by step.

    Prototype with instance counter

    First, the prototype.
    We want to know how many objects the Spring framework creates. We’re going to use a simple static counter incremented in the class constructor.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Service
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    class MessageBuilder {
        private static final AtomicInteger instanceCounter = new AtomicInteger(0);
        MessageBuilder() {
            instanceCounter.incrementAndGet();
        }
        static int getInstanceCounter() {
            return instanceCounter.get();
        }
    }
    We need the counter only for testing. The main task of the class is to build some immutable Message object. Our prototype will use the Builder pattern as presented below.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class MessageBuilder {
        //...
        private String content;
        private String receiver;
        MessageBuilder withContent(String content) {
            this.content = content;
            return this;
        }
        MessageBuilder withReceiver(String receiver) {
            this.receiver = receiver;
            return this;
        }
        Message build() {
            return new Message(content, receiver);
        }
    }

    Singleton dependent on prototype bean

    Next, the singleton implementation.
    The MesssageService class is a simple singleton with only one method. It calls all three methods of the prototype.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Service
    class MessageService {
        private final MessageBuilder messageBuilder;
        MessageService(MessageBuilder messageBuilder) {
            this.messageBuilder = messageBuilder;
        }
        Message createMessage(String content, String receiver) {
            return messageBuilder
                    .withContent(content)
                    .withReceiver(receiver)
                    .build();
        }
    }
    As a reminder, since Spring 4.3 you do not have to put the @Autowired annotation on a constructor if there is only one in a class. The framework uses it automatically.

    Checking prototype instance count

    Finally, we write a test that will confirm that on every call to the singleton, Spring creates a new prototype instance. That’s our goal. We call the singleton twice so we expect two objects.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class MessageServiceTest {
        @Autowired
        private MessageService messageService;
        @Test
        public void shouldCreateTwoBuilders() throws Exception {
            //when
            messageService.createMessage("text", "alice");
            messageService.createMessage("msg", "bob");
            //then
            int prototypeCounter = MessageBuilder.getInstanceCounter();
            assertEquals("Wrong number of instances", 2, prototypeCounter);
        }
    }
    Now we’re ready to examine all possible solutions to inject prototype bean into a singleton.

    How to inject prototype bean into singleton bean?

    When you work with a prototype bean in a singleton, you have three options to get a new instance of the prototype:
    1. Spring can autowire a single prototype instance when it creates the singleton. It’s the default framework behavior.
    2. Spring can create a new prototype instance on every call to any method of this prototype.
    3. You can programmatically ask the Spring context to create a new prototype instance at the moment you need a new object.

    Option 1: Injecting on singleton construction

    As I already mentioned, injecting on construction is default behavior of the framework. If a singleton bean depends on a prototype, Spring creates a single prototype instance dedicated for this particular singleton.
    The singleton resuses its single prototype instance through its whole lifecycle.
    Let’s run the test we wrote in the previous paragraph and confirm that Spring creates only one prototype.
    plain test result

    Option 2: Injecting on prototype method call

    Another possibility is to force Spring to create a new prototype instance when every call on prototype’s method.
    To achieve this, you need to modify the prototype bean and set its proxy mode. You can do this by modifying the @Scope annotation as follows:
    1
    2
    3
    4
    5
    6
    @Service
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
           proxyMode = ScopedProxyMode.TARGET_CLASS)
    class MessageBuilder {
      // ...
    }
    By default, Spring doesn’t create a proxy object for a bean and uses the reference to the real bean when injection occurs. However, when you change the proxy mode, Spring creates and injects a special proxy object instead of the real object. The proxy decides on its own when to create the real object.
    proxy diagram
    By setting the proxy mode to ScopedProxyMode.TARGET_CLASS, Spring will create a new instance of the prototype whenever you call its method.
    What is the outcome of our test?
    proxy test result
    We didn’t get one instance, as without the proxy, but as many as six.
    Why that happened?
    In our test, we call the createMessage() method on the MessageService object twice and this, in turn, executes three methods of the proxied MessageBuilder. Two times three gives us six in total and that is what our test proved.
    However, that is not what we wanted and it is even worse. Not only got we more instance than we expected, but also the final result is different than wanted because each instance has a separate state.
    The createMessage() method relies on the state that is stored between sequential calls on the prototype. With the given setup, the state is lost on every call to prototype methods. Therefore, setting a proxy mode is a dead end for our problem.

    Option 3: Creating prototype on demand with ObjectFactory

    The last option is the most flexible because it allows you to create a new prototype instance manually. Thanks to bean definition, Spring knows how to create a prototype. You just need to tell the framework when to do it.
    That’s when ObjectFactory comes in.
    ObjectFactory is a functional interface from Spring framework designed to provide a reference to beans managed by the application context. The interface defines only one method which returns an instance of the selected bean.
    How to use ObjectFactory with prototype beans?
    It’s very simple. You just need to define a dependency on the ObjectFactory for the chosen bean. Spring will generate and inject the appropriate implementation of the interface.
    Let’s update the MessageService singleton to see the factory in action.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Service
    class MessageService {
        private final ObjectFactory<MessageBuilder> messageBuilder;
        MessageService(ObjectFactory<MessageBuilder> messageBuilder) {
            this.messageBuilder = messageBuilder;
        }
        Message createMessage(String content, String receiver) {
            return messageBuilder.getObject()
                    .withContent(content)
                    .withReceiver(receiver)
                    .build();
        }
    }
    Thanks to ObjectFactory you can create a prototype instance exactly when you need it.
    If we run our test again, it will pass. Every call to the createMessage() method gets its own instance of the prototype.

    factory test result

    ObjectFactory in unit test

    One of the reasons to use dependency injection is to simplify unit testing. It’s really simple to replace a real dependency with a stub or a mock.
    Because ObjectFactory is a function interface, you can easily write its stub implementation with the lambda expression.
    1
    2
    3
    4
    5
    6
    @Test
    public void shouldStubFactory() throws Exception {
        ObjectFactory<MessageBuilder> factory = () -> new MessageBuilder()
        MessageService sut = new MessageService(factory);
        //...
    }

    conclusion

    At this point, you should know about all the possible options for creating prototype beans. You learned that injecting a prototype bean into singleton may be a bit tricky. After reading the article, you know which injecting option is best for your requirements.

    How many instances created for singleton bean referring to a session bean/prototype bean
    The singleton scope
    When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
    To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
    The session scope
    With the above bean definition in place, the Spring container will create a brand new instance of the bean , for the lifetime of a single HTTP Session.
    According to Spring framework reference, a different approach needs to be followed in cases where a class which "lives longer"(singleton bean in this case) needs to be injected with another class having a comparatively shorter life-span(session-scoped bean). The approach is different for prototype & singleton scope though.
    In your XML, what we want is that the singletonBean instance should be instantiated only once, and it should be injected with sessionBean. But since sessionBean is session-scoped(which means it should be re-instantiated for every session), the configuration is ambiguous(as the dependencies are set at instantiation time and the session scoped value can change later also).
    So instead of injecting with that class, its injected with a proxy that exposes the exact same public interface as sessionBean. The container injects this proxy object into the singletonBean bean, which is unaware that this sessionBean reference is a proxy. Its specified by writing this tag in the sessionBean:
    <aop:scoped-proxy/>
    XML Configuration:
    <bean name="singletonBean" class="somepkg.SingletonBean">
    <property name="someProperty" ref="sessionBean"/>
    </bean>
    
    <bean name="sessionBean" class="somepkg.SessionBean" scope="session">
    <aop:scoped-proxy/>
    </bean>
    When a singletonBean instance invokes a method on the dependency-injected sessionBean object, it actually is invoking a method on the proxy. The proxy then fetches the real sessionBean object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real sessionBean object.
    Alse please refer this for more info.
    Singleton beans with prototype-bean dependencies
    Lookup Method Injection
    When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scopedbean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
    However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
    <!-- a stateful bean deployed as a prototype (non-singleton) -->
    <bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
      <!-- inject dependencies here as required -->
    </bean>
    
    <!-- commandProcessor uses statefulCommandHelper -->
    <bean id="commandManager" class="fiona.apple.CommandManager">
      <lookup-method name="createCommand" bean="command"/>
    </bean>
    Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The lookup typically involves a prototype bean as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB libraryto generate dynamically a subclass that overrides the method.


    No comments:

    Post a Comment

    All Java 8 / J2EE Interview for Experienced

      1.       Functional Interface, Stream API? Functional interfaces are also called Single Abstract Method interfaces (SAM Interfaces). As ...