I'm trying to create an ExceptionMapper with an abstract parent class and some injected fields. Here is the part of code, simplified:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class MyExceptionMapper extends GenericExceptionMapper<MyException> {
#Override
public Response toResponse(MyException exception) {
...
}
}
public abstract class GenericExceptionMapper<T extends WebApplicationException> implements ExceptionMapper<T> {
#Inject
private ClassA fieldInParentA; // will be null.
#Inject
private ClassB fieldInParentB; // will be null.
// all kind of other stuff, including getters
...
}
ClassA and ClassB are simple classes with #Dependent, #ApplicationScoped or #Singleton scopes (tried all these).
The problem is, that the fields of the parent don't get injected (nor do I see any error report in logs) and the result of getFieldInParentA() or of getFieldInParentB() return null in toResponse(), although the problem is not with the injected objects (they gets injected properly in other places).
Further, to my biggest surprise, all of fieldInParentA, fieldInParentB and fieldInChild will be injected when also the child class contains injected field. This is so with any dependent, singleton or application scoped fields:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class MyExceptionMapper extends GenericExceptionMapper<MyException> {
#Inject
private ClassC fieldInChild; // **will be initialized!**
#Override
public Response toResponse(MyException exception) {
...
}
}
public abstract class GenericExceptionMapper<T extends WebApplicationException> implements ExceptionMapper<T> {
#Inject
private ClassA fieldInParentA; // **will be initialized!**
#Inject
private ClassB fieldInParentB; // **will be initialized!**
...
}
I might not understand properly the scopes (might it be the #Provider for blame?) or the inheritance of injected fields in Jakarta Dependency Injection, but besides not being able to initialize my classes (you might have guessed, that I don't want fields in the child class :) ) it is also bothering, that I do not understand this (apparently strange) behavior: how can the injection of a field in a parent depend on whether we there are fields in the child or not?!
1.
I did a lot of search, but I unfortunately couldn't find anything useful.
Related
I spent a plenty of time for finding any answers, but I think I have to ask.
I'm using Weld-SE for testing my entities.
I prepared entity randomizer for testing.
abstract class BaseEntityRandomizer<T extends BaseEntity>
implements Randomizer<T> {
#Override public T getRandomValue() {
...
}
}
class MySomeOtherEntityRandomizer
extends BaseEntityRandomizer<MySomeOther> {
#Override public MySomeOther getRandomValue() {
...
}
}
Now, with my test class, I want to inject those randomizers which each matches generic parameters
#ExtendWith(WeldJunit5Extension.class)
#AddPackages({BaseEntityRandomizer.class})
abstract class BaseEntityTest<T extends BaseEntity> {
#Test void doSome() {
}
#Inject
private BaseEntityRandomizer<T> entityRandomizer;
}
class MySomeOtherTest extends BaseEntityTest<MySomeOther> {
...
// I expect an instance of MySomeOtherRandomizer in injected
// into the entityRandomizer field.
}
Subclasses of randomizers and tests are prepared.
But I failed to make it work.
How can I make it work?
I tried with following factory class
class BaseEntityRandomizerFactory {
#Produces
public BaseEntityRandomizer<MySome> produceMySomeRandomizer() {
return new MySomeRandomizer();
}
}
I got
org.jboss.weld.exceptions.IllegalArgumentException:
WELD-001408: Unsatisfied dependencies for type BaseEntityRandomizer<T extends BaseEntity> with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject protected transient ....BaseEntityTest.entityRandomizer
at ....BaseEntityTest.entityRandomizer(BaseEntityTest.java:0)
One way to achieve this is to use CDI Programmatic lookup. In your case, I'd start with #Inject Instance<Object> and then you can use subsequent calls to select() and get() methods to pick up whichever bean you desire. Usage looks something like this (assumes existence of beans with types Foo, Bar and List<String>):
#Inject
private Instance<Object> instance;
#Test void doSome() {
// selecting and obtaining instances of beans
Foo foo = entityRandomizer.select(Foo.class).get();
Bar bar = entityRandomizer.select(Bar.class).get();
// in case you need to select a parameterized type from instance, use TypeLiteral
List<String> listBean = entityRandomized..select( new TypeLiteral<List<String>>(){}).get()
}
I have an abstract bean with injected ISomeOtherBean interface:
public abstract class AbstractBean {
#EJB ISomeOtherBean myService;
}
The ISomeOtherBean is interface. He have many implementations, for example: SomeBeanA, SomeBeanB...
#Stateless
public class SomeBeanA implements ISomeOtherBean {
}
#Stateless
public class SomeBeanB implements ISomeOtherBean {
}
How can I inject concrete implementation of ISomeOtherBean inside some implementation of the AbstractBean?
#Stateless
public class BeanImpl extends AbstractBean {
// how write that I want inject SomeBeanB which implements ISomeOtherBean
}
First i tried to inject concrete implementation inside BeanImpl, then I passed it to additional method of superclass (Abstractbean) which writed it to field myService.
But this solution is bad for me. I remember Spring has ability to pass some beans to constructor of given bean. But it was inside XML configuration. I want something like this, but with EJB and annotation configurations.
Anyone knows how do it?
I am trying to create a Component that will be Autowired unless the user creates a different implementation.
I used the following code to try and isolate the problem:
The interface:
public interface A {...}
The implementation:
#Component
#ConditionalOnMissingBean(A.class)
public class AImpl implements A {...}
The usage code:
public class AUsage {
#Autowired
private A a;
}
In this example, I don't get AImpl autowired into AUsage.
If I implement A in another class without the ConditionalOnMissingBean it works.
I tried copying existing uses of #ConditionalOnMissingBean from the internet and noticed that they all reference a #Bean method.
Indeed, when I added this code to AUsage:
public class AUsage {
#Autowired
private A a;
#Bean
#ConditionalOnMissingBean
public A createA() {
return new AImpl();
}
}
and removed the annotations from AImpl:
public class AImpl implements A {...}
everything works as expected.
I'd be pleased to get an explanation to this, if anyone knows.
In my spring-based project I have a core module ('core') with a class
#Component
public class Superclass {
// stuff
}
instances of which are injected by type throughout the code like this:
public class AService {
#Autowired
private Superclass superclass;
// service stuff
}
I also have two other modules that depend on the core module and one of which (let's call it 'module1') extends Superclass:
#component
public class Subclass extends Superclass {
// overridden stuff
}
The other module ('module2') uses Superclass as is.
Now I want that when I compile and run 'child1' an instance of Subclass is used everywhere an instance of Superclass is expected. So I write a configuration class:
#Configuration
public class Module2Configuration {
#Bean
public Superclass superclass(){
return new Subclass();
}
}
When I run this I see both Superclass and Subclass instantiated which is definitely not what I want. How do specify in 'module1' which type Spring should instantiate?
You can use #Qualifier("some name") annotation.
There is more information about that: http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
Spring eagerly instantiates singleton beans as stated in the documentation:
By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process.
which might explain why both #Components are created.
To specifiy which implementation is provided as a dependency you might want to check on Qualifiers that enable to choose between different implementations. In combination with lazy loading this should do the trick.
Depending on your personal taste you could also use delegation instead of inheritance using a separated interface:
public interface MyService {
public String foobar(int baz);
}
public static class CommonBehavior {
// whatever is used by Superclass and Subclass
}
#Component #Lazy
public class FormerSuperClass implements MyService {
private final CommonBehavior ...;
...
}
#Component #Lazy
public class FormerSubClass implements MyService {
private final CommonBehavior ...;
...
}
Good luck!
There are 2 methods: Use #Qualifier("SubclassName") Or Mark your subclass as #Component and declare the subclass when #Autowired
In your case:
Use #Qualifier("SubclassName")
#Component
public class Superclass {
// stuff
}
#component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
#Autowired
#Qualifier("Subclass")
private Superclass superclass;
// service stuff
}
2.Mark your subclass as #Component and declare the subclass when #Autowired
public class Superclass {
// stuff
}
#component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
#Autowired
private Subclass subclass;
// service stuff
}
Please bear with me:
We have a setup of Hibernate and Spring IoC, in which for each entity (User, Customer, Account, Payment, Coupon, etc) there's a bunch of "singleton" interfaces and implementation classes that support it.
For example: forCustomer:
#Entity
public class Customer extends BaseEntity {
...
public name();
}
/* base API */
public interface Service {
public create();
public list();
public find();
public update();
public delete();
}
/* specific API */
public interface CustomerService extends Service {
public findByName();
}
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
...
}
And this pattern goes on and on (CustomerManager, CustomerDataProvider, CustomerRenderer, etc.).
finally, in order work against an instance of a specific API (e.g. CustomerService.findByName()), a static global holder had evolved - which makes references like the following available:
public class ContextHolder {
private static AbstractApplicationContext appContext;
public static final CustomerService getCustomerService() {
return appContext.getBean(CustomerService.class);
}
//... omitting methods for each entity class X supporting class
}
#Configuration
public class ServicesConfiguration {
#Bean(name = "customerService")
#Lazy(false)
public CustomerService CustomerService() {
return new CustomerServiceImpl();
}
//... omitting methods for each entity class X supporting class
}
So, the question is:
what would be the proper way to inject those supporting classes, e.g. CustomerService, given an entity instance, for the following uses:
I have a specific entity (e.g. a Customer), and would like to get a service and call a specific API (e.g. findByName())?
I have an entity (don't care which one in specific), and would like to call a general API (e.g. find())
All this, while avoiding global static references (and thus, swap implementations in e.g. tests, and simplify the caller code).
So i can get a any supporting class if I have an entity instance
BaseEntity entity = ... // not injected
Iservice service = ...// should be injected
service.create(entity);
or, get all the supporting classes I need for a given entity type
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
// inject specific supporting classes
#Autowire CustomerManager manager;
#Autowire CustomerDataProvider provider;
#Autowire CustomerRenderer renderer;
#Autowire CustomerHelper helper;
...
}
and, change the configuration a bit in other scenarios
// how to configure Spring to inject this double?
Class CustomerManagerDouble extends CustomerManager {...}
#Autowired #Test public void testSpecificAPI(CustomerService service) {
service.doSomethingSpecific();
assert ((CustomerManagerDouble) service.getManager()).checkSomething();
}
I'm not entirely sure what you're asking, but I think you want to inject entity objects (created by Hibernate) with services, right?
If that's the case, use the #Configurable annotation as described in the Spring 3.1 documentation:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-atconfigurable
Note that you have to use AspectJ to weave the entity classes (load-time or compile-time) for this to work.