0

Iam trying to autowire an enum inside a spring Bean.I have not tried this before and not sure what is missing but when i do that i am getting parameter 0 of constructor in required a bean of type java.lang.string error. Please find below the code i have created.

public interface TokenGenerator{
 String generateToken();
}

@Service
public enum  TokenGeneratorImpl implements TokenGenerator{

INSTANCE;

private string token;

public string  generateToken(){
    if(token == null){
      token="new token";
    }

    return token;
   }
}


@Service
public class ConnectionService {

 @Autowired
 private TokenGenerator generator

 public void getConnection(){
   for(int i =0; i< 1000; i++){
         Thread t = new Thread(() -> generator.generateToken());
          t.start();
      }
   }
 }

There are two issues: 1) Autowiring is not working and I am getting

parameter 0 of constructor in required a bean of type java.lang.string error

2) If i call directly the Enum and generate the token then i found that this code is not thread safe and want to understand how I can make it thread safe

Vinay Pandey
  • 441
  • 3
  • 10
  • 22

2 Answers2

1

By autowiring the TokenGeneratorImpl, you are trying to instantiate an ENUM which is not possible

https://stackoverflow.com/a/36710397/5001937

For 2nd Point https://stackoverflow.com/a/2531998/5001937

Suraj
  • 737
  • 6
  • 21
  • But this resolves the first part only.The scond part why Iam getting multiple threads initializing token again and again if i directly make a call to TokenGeneratorImpl.INSTANCE.generatetoken(); In my understanding enum instance is thread safe – Vinay Pandey Jun 17 '20 at 17:22
  • 1
    For 2nd point https://stackoverflow.com/a/2531998/5001937 – Suraj Jun 17 '20 at 17:59
0

The only way I know to do this is to create a separate bean responsible for registering the enum with the context. It would look something like this

@Component
public class EnumContextInject {

    public final GenericApplicationContext applicationContext;

    public EnumContextInject(GenericApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void inject() {
        applicationContext.registerBean(TokenGeneratorImpl.class, () -> TokenGeneratorImpl.INSTANCE);
    }
}

You would need to make sure anything requiring the instance is created after this is run maybe with @DependsOn

James Mudd
  • 1,816
  • 1
  • 20
  • 25