0

I'm currently working on a web application using Angular 7 for front-end, spring-boot for back-end (in which I'm developing a restful web service). I'm using @Autowired annotation to inject my services into each other and my rest controller. The problem is that in some of my services, there are some attributes that get shared when the injection is done. How do I prevent that?

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class ServiceA {
   private boolean test;
   public ServiceA (){
     test = true;
   }
   public changeValues(){
     test = false;
   }
}

@Service
public class ServiceB {
   @Autowired
   private ServiceA serivceA;
   public void method1() {
     serviceA.changeValues();
   }
}

@Service
public class ServiceC {
   @Autowired
   private ServiceA serivceA;
   public void method2(){
      if(serviceA.getTest()){
        doSomethingNeeded();
      }
   } 
}

public class Application{
  @Autowired
  private ServiceB b;
  @Autowired
  private ServiceC c;

  public static void main(String[] args) {
    b.method1();
    c.method2();
  }
}

In this case the method doSomethingNeeded() in ServiceC won't be able to be executed because the ressource 'test' of ServiceA is shared between both ServiceB and ServiceC. How do I prevent That?

P.S. In my case, the dependency injections are way too complex for applying any modifications to the services, that's why I need a way to configure spring-ioc dependency injection in a way to create instances of private attributes to each client session.

Mark Benningfield
  • 2,800
  • 9
  • 31
  • 31
  • If i understand you correctly, you want to use ServiceA in two different services, but each to have its own "state" of your "test" variable. In this case you might consider setting ServiceA as prototype (`@Scope("prototype")`). If you can't set it as prototype and you want it to be singleton, then it depends on use-case – Tom May 14 '19 at 16:25

2 Answers2

0

Spring Beans are by default Singletons and the should not contain state.

Single Page Applications (like you create with Angular) should anyway hold the state on the client side and pass the information with every request.

The main reason is when your backend is stateless it's easy to scale and is more reliable because if a backend service is restarted you don't loose anything.

Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82
0

You just need change the scope of ServiceA to prototype by adding @Scope(scopeName = "prototype"):

@Scope(scopeName = "prototype")
@Service
public class ServiceA {

}

Then when ServiceB and ServiceC are instantiated , separated ServiceA will be created and inject into them.

P.S. Please note that a new instance of prototype bean will only be created during ServiceB and ServiceC are instantiated. It does not mean that a new instance of prototype bean will always be created whenever you access them. You need to use one of these technique if you want such behaviour.

Ken Chan
  • 84,777
  • 26
  • 143
  • 172