Obtaining config values from within non-spring managed bean - java

I'm using annotation-configuration, not XML for my application...
#Configuration
#ComponentScan(basePackages = {
"com.production"
})
#PropertySource(value= {
"classpath:/application.properties",
"classpath:/environment-${COMPANY_ENVIRONMENT}.properties"
})
#EnableJpaRepositories("com.production.repository")
#EnableTransactionManagement
#EnableScheduling
public class Config {
#Value("${db.url}")
String PROPERTY_DATABASE_URL;
#Value("${db.user}")
String PROPERTY_DATABASE_USER;
#Value("${db.password}")
String PROPERTY_DATABASE_PASSWORD;
#Value("${persistenceUnit.default}")
String PROPERTY_DEFAULT_PERSISTENCE_UNIT;
In this file I've noticed I can obtain configuration values from the #PropertySource files. How can I obtain these values outside of a spring managed bean?
Is it possible for me to use my ApplicationContextProvider to obtain these values?
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext (ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}

If I understand you correctly, yes you can use your ApplicationContextProvider class. #PropertySource properties end up in the ApplicationContext Environment. You can therefore access them like
public static class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext (ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
Environment env = applicationContext.getEnvironment();
System.out.println(env.getProperty("db.user")); // access them
}
}
So basically anywhere you have a reference to the ApplicationContext, you can get the properties declared in a #PropertySources or a PropertySourcesPlaceholderConfigurer.
However, in this case, the ApplicationContextProvider will have to be declared as a Spring bean in your context.
#Bean
public ApplicationContextProvider contextProvider() {
return new ApplicationContextProvider();
}

Related

Initializa Bean with YAML configuration in Spring Boot

I would like to read some properties, like DB access configs, when initializing bean or service in spring boot.
Anyone knows good ways ?
This is my current code snippet.
public class SampleApplication implements ApplicationRunner
{
#Autowired
private YAMLConfig myConfig;
#Override
public void run(ApplicationArguments args) throws Exception
{
System.out.println(myConfig != null); //YAMLConfig has been intialized here
}
public SampleApplication()
{
System.out.println(myConfig == null); //myConfig is null
}
#Configuration
public static class Config
{
#Bean
#ConditionalOnProperty(value = {"batch.execute"}, havingValue = "SampleApplication")
public SampleApplication sampleApplication()
{
return new SampleApplication();
}
}
}
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class YAMLConfig
{
private String environment;
public String getEnvironment()
{
return environment;
}
public void setEnvironment(String environment)
{
this.environment = environment;
}
}
Thanks for taking a look at this!
create this method inside your SampleApplication class
#PostConstruct
public void init() {
// at this point, all the dependency injection has happened already
myConfig.doStuff()
}
it will be called by spring automatically after all bean initialization has been done.

ApplicationContextAware get ApplicationContext is null in spring boot

I build a web project with spring boot 1.5.4
And create a class implements ApplicationContextAware
#Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.context = context;
}
public static ApplicationContext getContext() {
return context;
}
Then I create a controller to test this class
#Controller
public class TestController {
#RequestMapping(value = "test", method = RequestMethod.GET)
public #ResponseBody String test(){
System.out.println(SpringContextUtils.getContext());));
return "aaa";
}
}
than I start the application
#SpringBootApplication
#ServletComponentScan
#EnableTransactionManagement
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I visited this controller but SpringContextUtils.getContext() out put null,why?
I am sure SpringContextUtils scaned by spring.
I know I can use #Autowired to get ApplicationContext,but I want to know why my program is wrong and how can I get it with ApplicationContextAware

Programmatically bind instance of class to qualifier in spring

I have instances of the same class being created from config values such that I need them to be injected/autowired from that config value. I was doing it in guice like:
for (String s : config.getStrings()) {
bind(Foo.class).annotatedWith(Names.named(s)).toInstance(new Foo(s));
}
Is there any way to do something like this in Spring or is there a way to use something like a FactoryBean to create instances of a class given a qualifier?
public final class FLEXSyncFactory implements ApplicationContextAware {
private static AbstractApplicationContext context;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
context = (AbstractApplicationContext) applicationContext;
}
And to register alias of bean
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
Foo fooBean = beanFactory.getBean(Foo.class);
beanFactory.initializeBean(fooBean, "TheAliasForBeanNameYouNeed");
beanFactory.autowireBeanProperties(fooBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);

Not able to load Application Context in Spring Boot app

I am working on a Spring Boot application wherein I am using that application to expose a SOAP webservice. I am using Apache CFX framework for SOAP impl in Spring boot app. I am using Annotation based approach.
I am facing issue in setting the Application Context from the Spring Boot Configuration file in one of the Beans. Below is my code.
#SpringBootApplication
#ComponentScan("com.test")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The configuration file is as below.
#Configuration
public class WebServiceConfiguration {
//All individual bean definitions should go here
#Autowired
ApplicationContext appContext;
#Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/soap-api/*");
}
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
#Bean(name="IValidator")
public IValidator getValidator(){
return new Validator();
}
#Bean(name="SOAPprocessImpl")
public IPSoap getService() {
return new SOAPprocessImpl();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), getService());
endpoint.publish("/WS_1.0");
endpoint.setWsdlLocation("process.wsdl");
return endpoint;
}
Now I have the bean SOAPprocessImpl implementation in which I need to get the Application Context so that I can get handle to the Validator bean. I have declared SOAPprocessImpl as a bean in the configuraton file. The code is as below
#javax.jws.WebService (endpointInterface="com.test.IPSoap")
public class SOAPprocessImpl implements IPSoap, ApplicationContextAware {
private static ApplicationContext context;
public static ApplicationContext getApplicationContext() {
return context;
}
#Override
public void setApplicationContext(ApplicationContext ac)
throws BeansException {
context = ac;
}
private static final Logger logger = Logger.getLogger(SOAPprocessImpl.class.getName());
private IValidator validator = (IValidator) context.getBean("IValidator"); // context is NULL here
public IRResponse GetBalance(TSSearchParams SearchParams) {
// Some processing logic
}
}
So the issue is that when I run the boot application by deploying to the embedded Tomcat then the Application Context is not getting set in the SOAPprocessImpl class even after implementing the ApplicationContextAware. I also tried Autowiring but that also is not working.
Strangely I tried to see if I can get the ApplicationContext in the Configuration file where all the bean are defined. Here it is getting setting properly.
Can anyone help me how to solve this issue. I am new to Spring Boot and may have missed some configutaion. Thanks in advance.
Option(1): To fix the issue, you need to use #Configuration to register your SOAPprocessImpl bean to the Spring container as shown below so that ApplicationContext object can be injected :
#Configuration
#javax.jws.WebService (endpointInterface="com.test.IPSoap")
public class SOAPprocessImpl implements IPSoap, ApplicationContextAware {
private static ApplicationContext context;
private IValidator validator;
public static ApplicationContext getApplicationContext() {
return context;
}
#Override
public void setApplicationContext(ApplicationContext ac)
throws BeansException {
SOAPprocessImpl.context = ac;
}
#PostConstruct//use PostConstruct
public void init() {
validator = (IValidator) context.getBean("IValidator");
}
//add your current code
}
The important point is that you can't use the context object until the bean is prepared by the container, so you need to use #PostConstruct method as shown above to initialise your variables.
Option2 (recommended):
The best approach is that you can use #Autowired to inject IValidator object into SOAPprocessImpl as shown below so that you don't need your SOAPprocessImpl bean to be aware of ApplicationContextAware. Spring container will inject the instance for the implementation provided for the IValidator class (provided it is under the packages of #Componentscan).
#Component
#javax.jws.WebService (endpointInterface="com.test.IPSoap")
public class SOAPprocessImpl implements IPSoap {
private static final Logger logger = Logger.getLogger(SOAPprocessImpl.class.getName());
#Autowired //spring directly injects this object
private IValidator validator;
public IRResponse GetBalance(TSSearchParams SearchParams) {
// Some processing logic
}
}

Inject spring bean in custom el functions

i want to create a custom el functions to get in a fast way select options from dao. I'm using Spring and i want to inject spring bean dao in my custom el functions class.
In el functions class i'm using static methods and i'm unable to access application context.
I used an implementation of ApplicationContextAware in this way
public class AppContextUtil implements ApplicationContextAware
{
private ApplicationContext applicationContext;
private static final AppContextUtil instance=new AppContextUtil();
private AppContextUtil()
{
}
public static AppContextUtil getInstance()
{
return instance;
}
public <T> T getBean(Class<T> clazz)
{
return applicationContext.getBean(clazz);
}
/**
* {#inheritDoc}
*/
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
}
but applicationContext is null.
The only way to access to applicationContext is as belove
WebApplicationContext appCtx =
WebApplicationContextUtils.getWebApplicationContext(context.getServletContext());
MyDAO myDAO = appCtx.getBean(MyDAO.class);
but in this way i need to pass PageContext in el functions params.
How i can create an el functions class with spring bean support? how i can access in static way to applicationContext?
Thank you.
A dirty solution to "inject" a bean or Application Context into an static field:
#Component
public class AppContextUtil {
private static ApplicationContext applicationContext;
#Autowire
private set ApplicationContext(ApplicationContext applicationContext) {
AppContextUtil.applicationContext = applicationContext;
}
}

Categories

Resources