Injecting spring bean (service layer class) into ResourceBundle

158 views Asked by At

I created a class using ResourceBundle interface as shown below. This class is dependent on another class. The implementation class for ResourceBundle (QuestionnaireSource as shown below) always has null as dependencies. No matter if I use setter or constructor injection. Could someone please help me with this issue. I am I missing some configuration here.

    @Component
public class QuestionnaireSource extends ResourceBundle {

    private final QuestionnaireCache questionnaireCache;

    private static final Object lockObject = new Object();

    @Override
    protected Object handleGetObject(String key) {
//        Gets an object for the given key from this resource bundle.
//        Returns null if this resource bundle does not contain an object for the given key 0
        Object value = null;
        try {
            value = getString(key, LocaleContextHolder.getLocale());
        } catch (Exception ignored) {
        }
        return value;
    }

    public Questionnaire getString(String key, Locale locale) {
        Locale l = safeLocale(locale);
        return getResources(l).get(key);
    }

    private Locale safeLocale(Locale l) {
        if (l.getLanguage().equalsIgnoreCase("DE")) {
            return Locale.GERMAN;
        } else {
            return Locale.ENGLISH;
        }
    }

    protected Map<String, Questionnaire> getResources(Locale locale) {
        synchronized (lockObject) {
            return questionnaireCache.getQuestionnaireCache().get(locale.getLanguage().toUpperCase());
        }
    }


    @Override
    public Enumeration<String> getKeys() {
        return null;
    }

    public QuestionnaireSource(QuestionnaireCache questionnaireCache) {
        super();
        this.questionnaireCache = questionnaireCache;
    }
}

Update: I found that even simple dependency injection in resourceBundle is failing.

UPdate2: The way I am using in the main class is as follows:

//        ResourceBundle test here
    System.out.println("Test here for resource bundle");
    Locale locale = new Locale("de", "DE");
    ResourceBundle bundle = ResourceBundle.getBundle("com.app.util.QuestionnaireSource", locale);
    System.out.println(bundle.getString("some.test.string"));

Update3

I am writing a simple example to convey the scenario:

Some service class

@Service
public class SomeServiceTest {

    public String testMethod(){
        return "test here and complete";
    }
}

Some example implementation of resource bundle

   @Component
public class MyResourceBundle extends ResourceBundle  {

    private final SomeServiceTest someServiceTest;

    @Autowired
    public MyResourceBundle(SomeServiceTest someServiceTest) {
        this.someServiceTest = someServiceTest;
    }

    @Override
    protected Object handleGetObject(String key) {
        if(key.equals("test"))
            return "test";
        return null;
    }

    @Override
    public Enumeration<String> getKeys() {
        return null;
    }
}

Main.java

 main(){
//        ResourceBundle test here
        System.out.println("Test here for resource bundle");
        Locale locale = new Locale("de", "DE");
        ResourceBundle bundle = ResourceBundle.getBundle("com.app.util.MyResourceBundle", locale);
        System.out.println(bundle.getString("test"));

}

Update4: I changed the annotation on classes as mentioned by on this post https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects but still I have the null dependency injection for SomeServiceTest class. The changes are as shown below.

SomeServiceTest.java

@Service
public class SomeServiceTest {

    public String testMethod(){
        return "test here and complete";
    }
}

MyResourceBundle.java

    @Configurable
public class MyResourceBundle extends ResourceBundle  {

    @Autowired
    private  SomeServiceTest someServiceTest;

    public MyResourceBundle() {
    }

    @Override
    protected Object handleGetObject(String key) {
        if(key.equals("test"))
            return someServiceTest.testMethod();
        return null;
    }

    @Override
    public Enumeration<String> getKeys() {
        return null;
    }
}

still SomeServiceTest class is null.

2

There are 2 answers

9
Kaj Hejer On

Can you please post an example on how you are using this class? Is it you (your code) or spring who instanciate it (on startup)?

@Component only works for beans which Spring instanciate. If you want to inject stuff in classes you instanciate in you code you can annotate the class with @Configurable.

Please see https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects for some examples.

3
Jilliss On

Make sure you have initialized the spring context

If you are using spring boot You can get the application context after it starts and use it to get the bean you want

For example

public static void main(String[] args) {
    ConfigurableApplicationContext run = SpringApplication.run(YouApplication.class, args);
    MyResourceBundle resConfig = run.getBean("myResourceBundle", MyResourceBundle .class);
    resConfig.handleGetObject("test");
}

Unfortunately ResourceBundle.getBundle does not initialize the spring application context