Is there a simple way to inject simple primitive type parameters (string and int) to the beans?
What i need is to find the guice equivalent of something like this from spring.xml:
<bean id="aBean" ...>
<property name="fieldName" value="aStringValue"/>
<property name="anotherFieldName" value="123"/>
</bean>
The values could be constructor injected, field injected or method injected, but i don't want to use separate named annotation or factory or provider for every value that i need to pass to the bean.
EDIT: my solution
Here is what i finally came to. I think it is closest to what i'm looking for, but any improvements would be welcome.
I found that in the module, i can declare a provider method and use it to set any properties i need:
MyModule extends AbstractModule{
...
#Provides #Named("testBean") MyTestBean createTestBean(MembersInjector<TestBean> mi){
TestBean test = new TestBean();
mi.injectMembers(test);
test.setFieldName("aStringValue");
test.setAnotherFieldName(123);
return test;
}
...
}
The good point is that the Provides method replaces the bind() for the bean and this way the actual line count doesn't increase much.
I'm still not 100% sure about any side effects, but it looks promising.
There is a build in mechanism to inject properties.
Properties File:
name=jan
city=hamburg
Module
#Override
protected void configure() {
Names.bindProperties(binder(), properties);
}
then in your bean, just inject by Name
class Customer {
#Inject
#Named("name")
String name;
....
}
There are a couple different ways you could do this, including your way. The only drawback to using a Provider method is that it's essentially a hand-rolled factory that you have to remember to maintain. (And in this specific case, you're also not getting the benefits of constructor injection).
Absent a Provider method, you have to use a binding annotation of some kind. If #Named won't work for you, then you'd need to create an annotation for each binding.
bindConstant().annotatedWith(FieldName.class).to("aStringValue");
public SomeClass {
public void setFieldName(#FieldName String fieldname) {}
}
In some cases this might require a 1-to-1 annotation per primitive/String instance to be bound. But I try to make my annotations somewhat orthogonal to the actual instance being described, preferring instead to use the annotation to describe the relationship between the bound objects and the injection points.
It's not always possible, but a whole group of related primitives could then potentially be described by a single binding annotation, as long as each primitive type is only used once in the set. So, this could hypothetically work:
bindConstant().annotatedWith(MyAnnotation.class).to("aStringValue");
bindConstant().annotatedWith(MyAnnotation.class).to(123);
Parenthetically, I'm curious why you can't used #Named annotations on the property, but you can use them on the injected bean?
Related
Assume I have a configuration class accessible via the stock CDI that defines some application-wide parameters:
#ApplicationScoped
class AppConfig {
public double getMaxAllowedBrightness() { ... }
};
And I have a simple class for my data objects:
class LightSource {
double brightness;
...
boolean isValid() {
double maxAllowedBrightness = ...; // Somehow use AppConfig#getMaxAllowedBrightness() here
return brightness <= maxAllowedBrightness;
}
}
How can my data object access the single AppConfig instance?
Somehow I hate the idea of autowiring AppConfig into every single data object (there are lots of them). Is there any other way to get access to AppConfig in the above example from my data object?
What's the best pattern to use here?
The simplest example is a runtime lookup akin to:
import jakarta.enterprise.inject.spi.CDI;
CDI.current().select(cls).get();
With cls being the class that you're looking up. (Note the package name, this is the latest version of CDI 2.x in the new jakarta namespace, the original is in javax.)
It gets more detailed from there, but that's the gist of it.
Note, that semantically there's little difference between autowiring something and doing a runtime lookup, especially for something mostly static at the instance level. It's still a dependency. You still have to touch the code of the classes to pull it off.
A nice thing of relying on the autowiring is that you can disable it situationally, and the class reverts to a simple bean, that you can do with what you will. Coding in the lookup, it's a little bit more than that.
Dynamic lookup is more for special circumstances.
On my current project, our team has been doing this using the #Value annotation. In our case, we have all the properties in a properties bean, which I'll call mainAppConfiguration. The bean is populated from a properties file like main-app-config.properties (which was read into the bean with a Properties prop = new Properties().load(mainAppConfigFilePath) method.
Assuming you have something like that set up, then we inject the properties into the classes that need them using a little SpEL magic something like:
private Integer refreshRateSeconds;
#Value("#{ mainAppConfiguration.getProperties()['funny-property-base-name.refreshRateSeconds'] }")
public void setRefreshRateSeconds(Integer refreshRateSeconds) {
if (refreshRateSeconds == null) {
throw new IllegalArgumentException("Required config property 'funny-property-base-name.refreshRateSeconds' was not found"));
}
this.refreshRateSeconds = refreshRateSeconds;
}
Baeldung has examples (without defaults) and more with defaults.
I have the following code:
public interface DummyInterface {
}
and
#Singleton
#Creatable
public class DummyInterfaceImpl1 implements DummyInterface {
}
And when I want I can simply inject this, and it works just fine, (see below):
#Inject
DummyInterfaceImpl1
However I can't do
#Inject
DummyInterface
Because I get an
Unable to process "ClassWhereIInject.dummyInterface": no actual value was found for the argument "DummyInterface".
So, I am trying to understand, if I use the combination of #Creatable and #Singleon, without adding the instance that I want to inject in the IEclipseContext, then I can only inject implementation classes and not interfaces?
I can see how this can get problematic, especially when one has multiple implementation classes for the same interface, and the dependency injection framework doesn't know which to inject...that is if you don't use the #Named annotation to specify...
The injection system only looks for something with the name you specify. It does not try and find a class that happens to implement that interface. So no you can't use an #Creatable class with a different name to the interface.
An alternative is to use a 'ContextFunction'. This is a function which is called when the injection system is looking for a name. The context function can create an instance of something suitable and put it in the context for the injector. Full details on context function are here
Right now I use the f:viewParam tag to inject the request parameter into a field of my bean
<f:viewParam name="id" value="#{surveyController.id}" />
But I would much rather prefer to use annotations for this. I know about the #Value annotation, and I guess I could do something like this
#Component
#Scope("view")
public class SurveyControlador {
#Value("#{new Long.parseLong('${param.id}')}")
private Long id;
....
}
But this is just plain ugly.
Is there a better way, where I don't need to convert the value explicitly, and maybe even omit the "param"? I'm even willing to install third party libraries
I've used omnifaces' #Param successfully, like so:
#Named #ViewScoped
public class SurveyController {
#Inject #Param(name = "id")
private ParamValue<Long> idParam;
public void doStuff() {
if (idParam.getValue().equals(1)) {
throw new IllegalAccessException("you don't dare");
}
}
}
Pro: You additionally get access to the raw submitted value and omnifaces optionally applies validations/conversions (check the docs).
Con: Wrapper around your real parameter. And you still need to specify <f:viewParam> (you don't need to bind it to a backing bean, tho) if you want to keep the parameter for navigation.
Note that this leverages CDI, which may or may not fit the way you do things.
I have a situation where I would like to dynamically create an object through a factory object, but the object needs to be created through the spring context, to allow autowiring of dependencies. I know that there are lots of other ways that I can solve this problem - using a service locator pattern for example - but I'd like to do it this way if possible.
Imagine I have two objects:
class OuterObject {
List<InnerObjectInterface> innerObjs;
...
}
class InnerObject implements InnerObjectInterface{
#Autowired
SomeDependency someDependency;
...
}
I want to create a factory that does something along the lines of:
class OuterObjectFactory {
private innerObject = new InnerObject();
public OuterObject construct(params){
OuterObject o = new OuterObject();
List<InnerObjectInterface> inners = new ArrayList<InnerObjectInterface>();
...
for(some dynamic condition){
...
inners.add(createInnerObject());
...
}
}
public createInnerObject(){
return innerObject;
}
}
My spring-context.xml would looks something like:
<bean id="outerObjectFactory" class="path.OuterObjectFactory" />
<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" />
This however, doesn't work. Only one innerObject is ever created, where I want it to act like it has scope="prototype". If I add scope="prototype" to the bean definition:
<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" scope="prototype"/>
Then it seems to create many innerObjects, but they aren't correctly wired. My co-worker believes that the documentation found here implies that the factory bean is only used to initialize a bean, but I don't find that obvious.
I'd appreciate it if anyone could clear up my understanding here, and possibly even suggest a better way of modelling the factory pattern with wiring than what I am doing.
Thanks!
I think what you're saying is that you have a factory which is a singleton and you want it to create new objects of which you want a new one each time with full dependency injection. The old way of doing that was Method Injection which you link to above. The new (and arguably cleaner way) is to use a Scoped Proxy. You can either use annotations or regular config but the idea is that you create a proxy around the bean (e.g. the InnerObject). When ever you need a reference to it, spring will automatically provide you with a new copy with the appropriate dependencies inserted.
Resolution: No I'm no longer extending the original parent.
Original:
Is there a way to annotate an inherited final setter method? I am extending a class which has a final setter which I would like to #Autowire with Spring. The parent class is from a library and cannot be modified.
A workaround I have found is to write a proxy method, but this seems like more work than necessary.
public abstract class SqlMapClientDaoSupport ... {
public final void setSqlMapClient(SqlMapClient smc) {
...
}
}
#Component
public class AccountDao extends SqlMapClientDaoSupport {
// all this just to annotate an existing method?
#Autowire
public final void setSqlMapClientWorkaround(SqlMapClient smc) {
super.setSqlMapClient(smc);
}
}
Edit 1: Above example modified to reflect use case:
The use case is implementing DAO objects for Ibatis/Spring
which extend a common base class. Each DAO needs the same
property set, and each needs to be configured as a bean. I currently
do this by configuring each individually in applicationContext.xml.
<bean id="accountDAO"
class="com.example.proj.dao.h2.AccountDAOImpl"
p:sqlMapClient-ref="sqlMapClient" />
<bean id="companyDAO"
class="com.example.proj.dao.h2.CompanyDAOImpl"
p:sqlMapClient-ref="sqlMapClient" />
<!-- etc... -->
I would prefer to use component-scan to discover and autowire the DAO
objects automatically, which I can't copy/paste botch.
<context:component-scan base-package="com.example.proj.dao.h2" />
I do not see in the annotation guide how one would annotate a
property/member other than where declared. I'm hoping that is
something I'm missing though.
Edit 2: I am no longer extending the SqlMapClientDaoSupport class, instead my AccountDao is a POJO which implements what little functionality was being provided by the Support class. This allows me to use #Autowire at will.
Have you tried configuring it with xml? Because it's an existing class which it looks like you can't change, it's a definite candidate for configuring it with xml. Then you can specify it as autowire", or even configure the property in the xml.
It sounds to me like you shouldn't be trying to set a final field.
There is usually a good reason why fields are final.
Have you setup a SqlMapClientFactoryBean object ?
See here for help
No, there is no way to annotate an inherited final method.
Rather than extend the support class (SqlMapClientDaoSupport) I reimplemented it in my project (it's behavior is minimal) annotating the methods as needed, and my DAO extend that support class.
You could create a new constructor with params for all the setters that are final and #Autowired the constructor, then call the setters in the constructor.