I have a situation and im trying to figure out why it is so. The scenario is I have a class A that implements an operation exposed by a webservice. For each request for the operation a new instance of A is created. The entire thing is manged by Spring internally and I am not sure how exactly the Class A in instantiated by the webservice.
Now i have a class variable whose value i want to inject during runtime through
#Value("${someValue}")
String someVariable
someValue is defined a system property. But each of the beans created has someVariable as NULL.
I tried the same thing in another class annotated with #Configuration in the same package and it is resolving the variable fine.
So, Im thinking if the ability to inject through #Value depends on the way a bean is created like #Component, #Configuration-#Bean, XML definiti
Not really. Actually You can inject value with #Value in both the component scan bean and xml definition bean. But pay attention to this, It depends on which xml file that you put the Placeholder in, it just valids in the per-container. For example, you put it in applicationContext, then the bean create in xxx-servlet.xml can not inject value with #Value.
Related
I would like to inject a bean (lets call it clientStub) into my service bean.
There are two requirements for that:
In order to create the clientStub bean, I need to access the #Client annotation, that carries some important information that are used to lookup the relevant configuration in the properties.
It must support constructor based injection (and #Bean method parameter injection)
Expected usage:
#Autowired
public MyService(
#Client("invoice-manager") InvoiceManagerClientStub clientStub,
SomeOtherBean bean1, ...) {
or
#Bean
MyService myService(
#Client("invoice-manager") InvoiceManagerClientStub clientStub,
SomeOtherBean bean1, ...) {
So I would like to do the same as the #Value annotation e.g. derive the value from the annotation on the parameter (plus some internal lookups).
Unfortunately, the usual BeanFactorys don't seem to be aware of the target's annotations.
Alternatives considered
Using an BeanPostProcessor to inject the values into annotated fields. Well, this is what I'm currently doing, but it doesn't feel right to have an immutable class with a single setter for injection.
Injecting it to a field and then exposing it as a bean or manually invoking the constructor is even worse.
Creating a proxy instance of the injected class. This isn't possible since the injected classes are generated + final and not part of my library.
Derive the configuration from the bean name: Not sure how to implement this and how to explain the user what the configuration parameters should be named in their properties files. I also would like to avoid bean name conflicts.
Non-Goals
Overwriting any core beans. I would like to distribute the extension as a library (spring-boot based), so any excessive replacement of spring internal beans should be avoided.
TLDR
How do I tell spring to resolve the parameter using my annotation's value (resolver)?
I want to choose a property file based which is decided by calling a method in another bean. Example
#Component
#PropertySource("classpath:app-${app.getName('value')}.properties")
class AppConfig{}
class App is a bean in my spring boot program.
Is there a way to do it?
TLDR: I want to provide a value in placeholder by calling a method from other bean.
I'm wondering if there is possibility to recreate a bean which was already created in java configuration on web app startup.
What I want to do is to reconfigure bean settings.
For example I create new bean with path to database:
#Bean
public TestBean getTestBean() {
TestBean tb = new TestBean("some_path_taken_from_external_point");
return tb;
}
During runtime I want to change the path. Let's assume that this bean doesn't have the setter method for database path.
I will have some kind of event and a listener for this event. Listener should reinitialize TestBean with new path.
Is this possible?
I was thinking of some kind of wrapper. In such case I would have class TestBeanWrapper which will have method get() which will return TestBean instance and recreate(String path) which will create new object with given path.
I'm not sure exactly if such wrapper would work for me, as the TestBean is a class from external library, and I'm not sure if it's not injected somewhere (but probably it's not injected).
More possible is that the other beans may rely on TestBean, so they also must be reinitialized (in case if they won't have setters for my TestBean).
Is this even possible in Spring (4.1) ? What is the best approach for such cases?
So I'm still unsure why you would want to change the path but I have 2 suggestions:
1. Look at setting the scope on the Bean.
By setting the scope on the bean, you can regenerate the bean based on context. Look at Bean Scopes for more information.
2. Look at maybe using a controller or a service.
Controllers and services allow getters and setters which may give you more control.
I have a project where I use heavily autowiring, e.g.
#Component("componentA")
public class ComponentAImpl implements ComponentA
#Component("componentB")
public class ComponentBImpl implements ComponentB {
#Autowired
private ComponentA componentA;
}
But I want customer to extend all the classes, so ideally they would just add a single jar into the classpath the the extended class should be used instead of the original one.
What I think would be great if they could just set a different name for the bean, e.g.
#component("componentA-custom)
I just need some way to customize the autowire process to look for a bean with "-custom" at the end and load it instead of the original bean.
Is there any way to do that?
Any help appreciated.
Thank you,
Mariusz
I found a solution, there is
#Primary
annotation that can be used to specify that the custom code added should be loaded instead of the original code.
What you are looking for is something similiar to this.
This should help you solve your problem.
If you need to get the bean name, you can inject in an instance of applicationContext which will get you the correct bean name (through a reverse lookup). or force all beans (ComponentA and CustomImplementation) to implement BeanNameAware
What You are asking about can be done via #Qualifier annotation, but it cannot generate bean names dynamically.
To allow external beans, You will need to create XML configuration for this, as it overrides annotation - based configuration. Your customers would have to provide:
New beans
XML configuration for your application that uses the new beans.
I have a class A with a date field annotated with #Value to take as default value the current date.
When I create a bean in an XML file, this field appears to be initialized with the current date, as expected.
When I create a new object with new A() in main of a test class, the field is null.
My question is how does #Value work. In the documentation, it said it gives a default value to a field, but does it work only for beans? How is it processed?
When creating the bean using the XML file, Spring creates the bean and applies the injection of configured fields, via XML configuration or decorated by annotations e.g. #Autowired, #Value, etc...
When creating the bean using new YourClass, then you're manually creating an instance of the class, thus not being handled by Spring.
If you want Spring to handle new beans created on demand i.e. using new keyword, you can refer to Spring injecting or autowiring datasource bean to class, point 3 and the explanation at the bottom using #Configurable.