Why is it impossible to inject generic classes? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a generic abstract template class. I thought if I create type-specific Producers, I could inject some DAO service directly in the generic class. But I can't.
Why? And how could I work around this?
abstract class MyView<T> {
#Inject
MyDao<T> dao;
//some more template methods that make use of the dao
void someMethod() {
dao.use();
}
}
class CustomerView extends MyView<Customer> {
//javax.enterprise.inject.AmbiguousResolutionException: Ambigious resolution
}
class DaoManager {
#Produces
MyDao<Customer> getDaoCustomer() {
return DaoFactory.make(Customer.class);
}
#Produces
MyDao<Product> getDaoProduct() {
return DaoFactory.make(Product.class);
}
}
When I inject eg a #Inject MyDao<Customer> dao; it works perfectly. But not with generics...

When you request
#Inject MyDao<Customer> dao;
the container knows that you want a bean specifically of type MyDao<Customer>. If such a bean exists and its type information is known, then the container can satisfy the injection. For example, the type information is preserved in your #Produces annotated method
#Produces
MyDao<Product> getDaoProduct() {
The container uses reflection to retrieve that parameterized type and can match it to the requested #Inject field.
With
abstract class MyView<T> {
#Inject
MyDao<T> dao;
however, all the container knows is that you want a MyDao. T is a type variable, not a concrete parameterization. The container cannot assume a specific type for it. In your case, both of the #Produces beans would match and there would be ambiguity.
In your example, we know from the context that it really wants a MyDao<Customer>. That doesn't seem to be something your container is capable of doing, ie. trying to resolve the type parameter to a concrete type argument for a parameterized subclass.

Related

How to get Spring bean by name [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
How can I get the bean by passing only the class name using BeanFactoryUtils
I'm trying below, but this is not working
import org.springframework.beans.factory.BeanFactoryUtils;
baseDao= BeanFactoryUtils.originalBeanName("RegionDaoImpl");
RegionDao
#Component
public class RegionDaoImpl implements BaseDao<Region> {
...
}
Any suggestions?
You need a ListableBeanFactory, then you call beanOfType(), e.g.:
RegionDaoImpl dao = BeanFactoryUtils.beanOfType(beanFactory, RegionDaoImpl.class);
Generally, the ListableBeanFactory will be an ApplicationContext, so you need the application context of your Spring application. How to get that depends on your application type, and where the code calling beanOfType() is located.
It is usually better to let Spring auto-wire the object into your class, which does the same thing, i.e. lookup the bean by type.
#Component
public class SomeComponent {
#Autowire
private RegionDaoImpl regionDao;
...
}
If you want to lookup by name, you'd call beanFactory.getBean(), but that seems kind of redundant:
RegionDaoImpl dao = beanFactory.getBean("RegionDaoImpl", RegionDaoImpl.class);

#Inject on no-args public method

While reviewing some code I have noticed a POJO (without scope -> #Dependant) which is injected (#Inject) in another bean and that do inject a bean (a field).
But it has also an #Inject annotation on a no-args public method that does initialisations stuff. I thought injection points only happen on field, constructor and setter
public class MyImpl implements MyInterface {
#Inject
private ParamDao paramDao;
private Map<String,List<MyRateDto>> params;
#Inject
public void loadRates() {
params = paramDao....;
}
...
}
To me this method (loadRates) should have been annotated as #PostConstruct. But I was wondering what happen in such case?
I guess the method is simply called after bean creation and field injection... But I have not read anything about it in the spec or elsewhere.
Is it the expected behavior?
Environment: Java 8/JavaEE 7 that targets a JBoss EAP 7.
Thanks
Thanks to #Andreas I have been steered in the right direction.
Looking at the Javadoc of #Inject: "Constructors are injected first, followed by fields, and then methods. Fields and methods in superclasses are injected before those in subclasses. Ordering of injection among fields and among methods in the same class is not specified. --- Injectable methods [...] accept zero or more dependencies as arguments."
So, there is no explicit description for zero arguments. But it's just that #Inject methods are called in arbitrary order, and arguments are resolved.
No argument = nothing to resolve.

Inject the same class with different parameters with Guice [duplicate]

This question already has an answer here:
Guice: inject different implementation depending on who is getting it?
(1 answer)
Closed 5 years ago.
I have 2 different classes(Cart and Payment) trying to use same database accessor class DBAccessor, as DBAccessor only contains logic to read and write data from a DB in a fixed format.
public class Cart{
#Inject
Cart(#Cart DBService db){
}
..
}
public class Payment{
#Inject
Payment(#Payment DBService db){
}
..
}
public class CartDBService implements DBService{
#Inject
public CartDBService(DBAccessor){
}
}
public class PaymentDBService implements DBService{
#Inject
public PaymentDBService(DBAccessor){
}
}
public class DBAccessor{
#Inject
public DBAccessor(String tableName){
}
}
I want to inject dependencies using guice in the give setup making sure everything is created by guice.
I am using binding annotation to inject different DBService instances for Cart and Payment.
bind(DBService.class).annotatedWith(Cart.class).to(CartDBService.class);
bind(DBService.class).annotatedWith(Payment.class).to(PaymentDBService.class);
How do I inject separate DBAccessor classes for cart and order to make sure they get correct table names injected.
The issue is with the design: class DBAccessor is doing too much work since it's reading different kind of data from different tables, now Guice is saving you by showing you that you were a bad boy...
Solution: implement two DBAccessor-classes, if they have common logic you can extract it to default methods in an interface or to an abstract class and inherit from it. Then you'll ask Guice to provide different classes to the constructors.
You need to bind your DbAccessor class twice, with a different qualifier annotation for each table. Then your classes can each inject the right qualified binding they need.

Spring validation don't follow the POJO principle [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've read this guide: http://spring.io/guides/gs/validating-form-input/
I see that the spring's approach of validating a form is to annotate the
properties of a object (which can be a POJO), with validation constraints
like #Min, #Max, #Size, etc..
This is not the best approach to mess-up POJO objects with this
annotations.
How do you write your code for validation a form in spring framework?
Spring offers a design for validation (and data binding) that does not exclude either one of them. Spring features a Validator interface that you can use to validate objects.
The Validator interface works using an Errors object so that while validating, validators can report validation failures to the Errors object.
Person POJO:
public class Person {
private String name;
private int age;
// the usual getters and setters...
}
Implementing a Validator:
public class PersonValidator implements Validator {
/**
* This Validator validates just Person instances
*/
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() 110) {
e.rejectValue("age", "too.darn.old");
}
}
}
Documentaction about Validation, Data Binding in Spring Framework 3.x
There is definitely some debate about whether or not you should use annotations on the POJO or not.
My personal opinion is that if you are not going to be sharing the POJO between modules, annotation configuration is perfectly acceptable.
If you want the validation constrains to be configured without annotations, you should look at Hibernate Validator's (Hibernate Validator is the reference implementation of this JSR 349) XML configuration. The reference for that configuration is here.
Also check out this (somewhat older) post for a tutorial.

Creation of generic type using Spring Config

How can I instantiate a bean with generic type using Spring config
public class GenericService<T>
{
...
}
Note that T is not the concrete type of a bean property. It is really just the type for one of the methods of the service.
In other words..
Can I instantiate new GenericService of type String or new GenericService of type Long using Spring context.
My generic class contains
public <T extends WordplayService> List<S> performTheService(String word, Class<T> clazz)
{
return clazz.newInstance().getAllWords();
...
}
The return type of the generic method depends on the concrete parameter type of the class instantiated.
Is this possible or a wrong usage of DI + generics? TIA
Generics are a compile-time concept, while spring context is loaded at runtime, so they don't intersect. What exactly are you trying to achieve? What is your usecase.
You can safely use DI with generics, because as I said, generics are lost at the time when the dependencies are injected.
Generics are a compile-time concept ...
The truth is, Generic information is not (completely) erased at compile time. You can still retrieve this information via reflection, and that is what the Spring DI container does already for collections. See 3.3.3.4.2. Strongly-typed collection (Java 5+ only) in 2.0.8 Spring documentation (sorry can only post one hyperlink).
However, I do not know (yet) if it is possible to instruct the container to do that for your custom classes as well.
If you want to know how to retrieve this information at runtime, here's the original post from Neal Gafter: http://gafter.blogspot.com/2006/12/super-type-tokens.html
You should just instantiate it using the raw class name. As #Bozho says generics are a compile-time only construct and their full types are not available at runtime.
None of the answers shows any examples, its easy :
#Resource
private CommentService<String> stringCommentService;
#Resource
private CommentService<Integer> integerCommentService;
#Test
public void genericTest(){
System.out.println("Generic test .... :");
stringCommentService.printType("test");
System.out.println("INT Generic test .... :");
integerCommentService.printType(9);
}
Where commentservice looks like you'd imagine:
#Service
public class CommentService<T> {

Categories