Tarun
Tarun

Reputation: 13

how to inject a dependency in a java enum?

I am trying to inject a bean into an enum but i keep getting null pointer exception when call to someMethod is made.

The answer mentioned in this Inject bean into enum worked for me. I want to know why my code didn't work

@Component
public class DataProvider {

public int method1() {
//somecode
}

}

public enum Genres {

DRAMA(1,”Drama”);
ADVENTURE(2,”Adventure”);
HORROR(3,”Horror”);

private int id;
private String name;

@Inject DataProvider dataprovider;

public int someMethod() {
return dataprovider.method1();
}

}

Upvotes: 1

Views: 10677

Answers (3)

pirho
pirho

Reputation: 12215

To have any injection to work you would need to have your enum also managed. You could try to inject your enum but how and what would you inject? It presents constant values and in addition it has private no args constructor.

So the way you might have it working would be some JNDI lookup - that initializes dataProvider - inside your someMethod() or using some static context accessor.

And: for for Spring it is not @Inject but @Resource or @Autowired

Upvotes: 0

PumpkinX
PumpkinX

Reputation: 67

  • Generally, it is not a good practice to have dependency injection in enums as they are designed to be constants/static (Reference)

But, I agree with you, many times, we need to associate some real time behavior to be encapsulated along with Enum values.

I would suggest, create a new class and encapsulate Enum within that.

class GenresService{
 // 1st option: Declare Genres enum reference at class level and 
 // initialize using class constructor/injection.

 // Genres g;

 @Inject DataProvider dataprovider;

 //2nd option: pass Genres value to method at real time.
 public int someMethod(Genres g) {
    return dataprovider.method1();
 }
}

Upvotes: 1

LppEdd
LppEdd

Reputation: 21144

What the answer you linked does is loop the enum values and use a setter to inject the DataProvider dependency

public void postConstruct() {
   for (ReportType rt : EnumSet.allOf(ReportType.class)) {
      rt.setDataPrepareService(dataPrepareService);
   }
}

It works because the ReportTypeServiceInjector class is an inner, static class, and so it can be seen and instantiated by Spring.

It's a crazy design anyway. Avoid it.
Ultimately, keep the enum simple and extract the DataProvider usage.

Your original code didn't work because Spring cannot @Autowire/@Inject dependencies in enums.

Upvotes: 2

Related Questions