I'm trying to define the service bean name using a property placeholder value. But getting error saying no bean found for the specific name. I got to know that the issue is with reading the property value, because while hardcoding the value it's working. Please help as I need to read the value from property file. Code snippet below:
application.properties
event.testRequest=TEST_REQUEST
Service Class
@Service("${event.testRequest}") // This is not working, getting "No bean named 'TEST_REQUEST' available" error
// @Service("TEST_REQUEST") // This is working
public class TestRequestExecutor extends DefaultExecutionService {
...
}
Also, to confirm the property value is reading correctly I tried using @Value("${event.testRequest}") private String value where I'm getting the value "TEST_REQUEST" as expected. Not sure how to use that with @Service annotation.
Edit: To elaborate the need of externalising the service bean name, I'm using factory pattern in getting the implementation based on the event name (event names such as Event1, Event2..). If there's a change in the event name, the change will be just on property file rather than the Service bean name which is using the property placeholder.
@RestController
public class RequestProcessController {
@Autowired
private ExecutorFactory executorFactory;
..
ExecutionService executionService = executorFactory.getExecutionService(request.getEventType());
executionService.executeRequest(request);
..
}
@Component
public class ExecutorFactory {
private BeanFactory beanFactory;
public ExecutionService getExecutionService(String eventType) {
return beanFactory.getBean(eventType, DefaultExecutionService.class);
}
Here DefaultExecutionService has different implementations like below..
@Service("${event.first}")
public class Event1Executor extends DefaultExecutionService {..}
..
@Service("${event.second}")
public class Event2Executor extends DefaultExecutionService {..}
event.first = Event1
event.second = Event2
So basically in future if Event1 name is updated to EventOne, I just need to update the property file, not the service class.
Any help much appreciated! Thanks!
There is something you can try. Although, I won't recommend doing this.
Try creating a
BeanNameGeneratorand supply it toSpringApplicationBuilderusing the methodbeanNameGenerator(BeanNameGenerator beanNameGenerator). If you are curious, here is a link to the default implementation.If I understand correctly, you have multiple implementations for this service, and you have to choose one based on the name that is provided in the properties file. If that is the case, take a look at this. And if those implementations depend on different profiles, take a look at this.
Edit after detailed explanation:
I think the simplest way to achieve this is to register your own beans. So remove
@Serviceannotations from your executors. Then, useDefaultListableBeanFactoryto register your ownBeanDefinitionfor the executors.The code would look something like this:
You can probably use
BeanFactoryAwareto get the bean factory, andBeanDefinitionBuilderif you want to set additional parameters before registering the bean.