I am working on a project for parsing files that uses Chains of Responsibility of an abstract class called EntityMapper that are used for parsing. Currently we have 2 types of Files/Entities:
GrantEntity
BillEntity
All EntityMappers extend the abstract class:
public abstract class EntityMapper<T extends AbstractBaseEntity> implements Function<MapperExchange, T>
Soon we will have a DonationEntity that will represent a file that has some structural characteristics as grantEntity.
Instead of creating new classes of Type extends EntityMapper<DonationEntity> I wanted to ask if there is a way to filter an #AutoWired collection using package names or a regex.
Something like ?:
#Autowired
#ComponentScan("com.my.package.first,com.my.package.second")
private List<EntityMapper<GrantEntity>> entityMappers;
I unfortunately did not find an answer in the link below except to do it by hand and remove the elements from the collection:
How to filter a collection of beans using a collection of regex in Spring?
You can use #Qualifer annotation to indicate logically similar components. Then specify a matching #Qualifier to the injection target. For example
class DependencyToInject{
}
#Configuration
public class AppConfig{
#Bean
#Qualifier("main")
public DependencyToInject dependency1(){
//return instance
}
#Bean
#Qualifier("main")
public DependencyToInject dependency2(){
//return instance
}
#Bean
#Qualifier("sub")
public DependencyToInject dependency3(){
//return instance
}
}
#Component
public class DependentClass{
#Autowired
#Qualifier("main")
private List<DependencyToInject> mainList;
#Autowired
#Qualifier("sub")
private List<DependencyToInject> subList;
}
Related
I try to create 2 instances of the same class using Spring and I want to let Spring manage the Dependency Injection. The problem I encounter is the fact that any of these instances already have some #Autowired fields, same fields for both instances, so I cannot use #Configuration class (or I don't know how). For example, this is a sketch of my use case:
// what annotation to use here?
class A {
#Autowired
private SomeClass first;
#Autowired
private OtherClass second;
private boolean aBool;
// what annotation to use here? From where and how to call this constructor?
public A(boolean aBool) {
this.aBool = aBool;
}
}
class B {
#Autowired
#Qualifier("aBoolTrue") // or a similar annotation
private A oneInstanceOfA; // oneInstanceOfA.aBool == true
#Autowired
#Qualifier("aBoolFalse")
private A theOtherInstanceOfA; // theOtherInstanceOfA.aBool == false
}
In this example, I need Spring to create and manage 2 distinct instances of the same class created through the same constructor (see the comments related to aBool), but with different parameter values. Is it possible to achieve this scenario using Spring?
Hello you could maybe just add a #Configuration class with 2 method
#Configuration
class ConfigurationClass{
#Bean
#Qualifier("aBoolTrue") //
public A oneInstanceOfA(SomeClass someClass, OtherClass second){ //Maybe With Other Qualifier for the parameter if needed
return new A(someClass, second, true);//Need another construtor
}
#Bean
#Qualifier("aBoolFalse")
public A oneInstanceOfA(SomeClass someClass, OtherClass second){
return new A(someClass, second, false);//Need another construtor
}
}
I defined some interfaces with generic, and I have some classes injected in Spring context as Beans, could I dynamic create a manager bean to manage them, and it could be autowired in fields without any Bean def code of this manager?
I have tried FactoryBean way to implement it, but not worked, it couldn't transmit generic class info and the FactoryBean bean couldn't transmit any changable arguments.
I have tried BeanFactory way to implement it, when I getBeansOfType, these objects created without autowired, not worked...
Now I have a finally method which I think it's not very smart that is using ImportBeanDefinitionRegistrar and ClassPathBeanDefinitionScanner to scan all classes, then insert the manager's beanDefinition.
I'll be very appreciate if you supply any method, Thank you very much !
I want to implement it like this:
public interface Strategy<E extends BaseEnum>
{
public E getType();
}
public interface LoginStrategy extends Strategy<LoginType>
{
public LoginStrategy getType();
}
#Strategy
public class ALoginStrategy implements LoginStrategy
{
public getType()
{
return LoginType.OTP;
}
}
#Strategy
public class BLoginStrategy implements LoginStrategy
{
#Autowired
private UserMapper;
public getType()
{
return LoginType.PASSWORD;
}
}
public LoginServiceImpl implements LoginService
{
#Autowired
private StrategyManage<LoginType, LoginStrategy> strategyManager;
}
I want the strategyManager in LoginServiceImpl which is marked Autowired could be auto generated.
I also have a other question. It may be easier to explain what I want.
I have a model convertor implements a ModelConvertor interface, TL is lowerModel's class, TU is upperModel's class.
now there is a bean include code like this:
#Autowired
private ModelConvertor<UserPO, UserDO> userConvertor;
normally Spring frame would throw a Exception with a "no such bean" message, so I want to make this field could auto inject a value like this:
#Autowired
private ModelConvertor<UserPO, UserDO> userConvertor[ = new DefaultModelConvertor(UserPO.class, UserDO.class)];
How can I do to solve these problems, thanks a lot again!
I have resolved this problem, scan specific packages and dynamic generate beans to put on context.
I have a parent class called BaseService and I have other services that inherit from BaseService as they all need those methods to do their jobs. As always the methods of the superclass are available inside the subclass... However, when I use #Autowired DI to inject the subclass I am not able to use the methods defined by the parent class, I am only able to use what is defined separately in the subclass. How can I inject the subclass and have it properly instantiate the subclass such that the methods of the parent class are available to me?
Ex. Parent Class
#Service
public class BaseService{
public BooleanExpression combineBools(Predicate predicate, BooleanExpression bool){
BooleanExpression result = runupBool.and(predicate);
return result;
}
}
Ex. Child Class
#Service
public class EqServiceImpl extends BaseService implements EqService{
public EqServiceImpl(){
super();
}
#Override
public Iterable getAllData(Map<String, String> params, Predicate predicate) {
// Some Method Specific to Child Class
}
}
Ex. Controller
#RestController
public class EqController {
#Autowired
EqService eqService
...
}
If I wanted to access the method eqService.combineBools() inside the controller I am unable to. Why is this? How can I fix it?
As DarrenForsythe pointed out I am instantiating with EqService as the type so it would not have all of the methods of the BaseService since it does not extend that class, rather it is the EqServiceImpl that extends that class. Therefore I would need the type to be EqServiceImpl. Without making some other changes #Autowired is not the best choice for DI here.
There exist following classes
class Entity{
}
class Dto{
}
public abstract class BaseMapper<E extends Entity, D extends Dto>{
}
And several sepcific implementation of mappers like:
FooMapper extends BaseMapper<Foo, FooDto>{
}
FeeMapper extends BaseMapper<Fee, FeeDto>{
}
No I want to integrate some "Wrapper" which does a bit more than normal mapping of the data, because I got a new concept/issue
#Component
public final class RevMapper<ENTITY extends Entity, DTO extends Dto> {
private BaseMapper<ENTITY, DTO> baseMapper;
#Autowired
public <MAPPER extends BaseMapper<ENTITY, DTO>> RevMapper(MAPPER mapper) {
this.baseMapper = mapper;
}
public List<RevDto<DTO>> toDto(final List<Rev<ENTITY>> revList) {
for(Rev<ENTITY> rev: revList){
...
baseMapper.toDto(rev.getEntity(), true);
}
...
}
}
And include it in my service like:
#Autowired
private RevMapper<Foo, FooDto> fooRevMapper;
The problem now is:
Parameter 0 of constructor in com.test.package.RevMapper required a single bean, but 2 were found:
- FooMapper
- FeeMapper
Spring doesn't know which to take. And yeah what I know is about the type erasure in generics. So basically after compile the application just know that there is a
RevMapper<Entity,Dto>
but not which type it is specifically. How could I tell Spring to insert the right component, or how would you handle this problem. I do not want to write the same lines of code for each type of Mapper....
The solution I can think of is not as time consuming than creating many many subclasses.
First make the RevMapper not a #Component and then create a class like follows:
#Configuration
public final class Mappers{
private final FooMapper fooMapper;
private final FeeMapper feeMapper;
#Autowired
public Mappers(FooMapper fooMapper, FeeMapper feeMapper){
this.fooMapper = fooMapper;
this.feeMapper = feeMapper;
}
#Bean
public RevMapper<Foo, FooDto> fooRevMapper(){
return new RevMapper(fooMapper);
}
#Bean
public RevMapper<Fee, FeeDto> feeRevMapper(){
return new RevMapper(feeMapper);
}
}
It's no more than just creating a method for every different RevMapper you want to provide.
I have an abstract class
public abstract class SecSchema {
........
}
I have some child classes. I have following service with all implementations of interfaces.
#Service
public class SecSchemaService {
#Autowired
Collection<SecSchema> secSchemas;
....getters and setters....
}
When I do DI in controller:
#Autowired
private SecSchemaService secSchemaService;
it works properly.
However I have another abstract class:
public abstract class Currecny {
#Autowired
SecSchemaService secSchemaService;
...... }
In child class I have the following code:
#Component
public class USD extends Currecny implements PreValidateListener {
#PostConstruct
public void registerListeners() { secSchemaService.getSecSchemas(); }
I've got NullPointerException because collection
secSchemaService.secSchemas
is null.
I don't know why but the the collection is initialized after class USD. I tried to use annotation #Dependson but it didn't help.
If I'd inject
#Autowired
Collection<SecSchema> secSchemas;
in class USD it works ok. So It's not working only when I'm injecting the wrapper of the collection SecSchemaService
I've had great fun and games with post constructs trying to use other beans that haven't yet been initialised.
A guaranteed way of getting it working is to forget about post constructs and have a bean that implements ApplicationListener for ContextRefreshedEvent, and then do your final initialisation in there. You can inject any existing beans in there and do any manual wiring you want. Not ideal, but works fine.
There was one more class child of USD and it was marked as #Component.
That was the problem. Only the last class in the hierarchy must be marked as #Component because I need only this class.