Spring session-scoped bean with construtor argument - java

In Spring I have bean that should not be instantiated without a constructor argument which depend on user input. what is the correct way to instantiate the SessionScoped bean in a controller or another Singleton-Scopped bean ?
public class SingletonScoped{
...
}
public class SessionScoped{
#Autowired
SingletonScoped singletonScopped;
private SessionScoped(){
}
public SessionScoped(Object userInput){
}
}
public class AnotherSingletonScoped{
...
}

basically i should add spring argument in serverlet-context.xml then u can passing argument here. A more detail u can see in this post http://chiase.azurewebsites.net/?p=171

Related

How to use Spring ObjectProvider with more than one bean definition

I am using an ObjectProvider to create instances of a prototype scope bean using the getObject() method. Something like this
#Configuration
class Config {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
SomeType typeOne() {
return new SomeType();
}
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
SomeType typeTwo(String param) {
return new SomeType(param);
}
}
#Service
class Service {
private ObjectProvider<SomeType> objectProvider;
public Service(
ObjectProvider<SomeType> objectProvider) {
this.objectProvider = objectProvider;
}
#Override
public String performAction() {
return getSomeType().doAction();
}
private SomeType getSomeType() {
return objectProvider.getObject();
}
}
But since there are two beans of the type that the ObjectProvider is trying to get (SomeType), I get a NoUniqueBeanDefinitionException. (And I do need the other bean of the same type, because that one I need to provide parameters using objectProvider.getObject(Object... params) )
Playing around and debugging Spring I saw that if you name your ObjectProvider exactly like your bean then it works, something like:
private ObjectProvider<SomeType> typeOne;
My question is, are there other ways to use an ObjectProvider and manage to resolve ambiguity, or is this approach the way to go?
Short answer is you just need to properly qualify the ObjectProvider you want injected, like this:
public Service(#Qualifier("typeOne") ObjectProvider<SomeType> objectProvider) {
this.objectProvider = objectProvider;
}
With Spring configuration, when you specify a bean via a method, and don't specify it's name with #Bean("NAME"), Spring uses the method name as the bean name.
Similarly, when injecting a bean that is not specified by #Qualifier("NAME"), Spring takes the injected variable as the name, if that don't exists or is not unique, you might get some exceptions informing you about this (like the NoUniqueBeanDefinitionException you facing).
So, if you match the bean name and the injected variable name you don't need to be more specific, but if you don't, #Qualifier is there to your rescue :D

How can I make a field which is generic field autowired with dynamic generate in Spring?

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.

Make Bean depend on list of beans in springboot

I have following #Configuration class, in which I am declaring a #Bean that depends on an #Autowired list of beans. However, this list is not complete when I am accessing to it. All #Bean definitions been executed, except the one defined in the same class.
#Configuration
public class MyConfig {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="ProblemHere")
public CustomObject customObject() {
log.info(requiredBeans.size()); // 1 (debugging, I can see is the one defined in "AnotherConfigClass")
}
#Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Having other classes like;
#Configuration
public class AnotherConfigClass {
#Bean(name="ThisOneGetsExecuted")
public RequiredBean reqBean() {
// this gets executed, and therefore, added to the list
return new RequiredBean();
}
}
Probably, the easiest solution would be to add #DependsOn("reqBeanInsideClass").
However:
I wonder why it works for all #Beans defined in different classes, but not in this one.
I'm not really sure that's exactly like that, and I'm afraid later on, another #Bean does not get executed
I guess the correct approach should be something like
#DependsOn(List<RequiredBean>) // Obviously this does not work
How should I solve this?
Update
I have copied the exact same class twice, in order to see what would happen, so now I have also:
#Configuration
public class MyConfig2 {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="ProblemHere2")
public CustomObject customObject() {
log.info(requiredBeans.size());
}
#Bean(name="reqBeanInsideClass2")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Amazingly, by doing this, both #Beans methods (ProblemHere & ProblemHere2) are called before both reqBeanInsideClass and reqBeanInsideClass2 methods.
For some reason I guess, Springboot is able to recognize #Beans required for a class as long as they are defined in another class.
Does this sound logic to anyone?
Can you not utilize the array input for #DependsOn rather than passing singular value, since it accepts String[]? That would wait for all the beans that are explicitly declared in the array before initializing, though has to be defined manually.
#Configuration
public class MyConfig {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="customObject")
#DependsOn({"reqBeanInsideClass", "thisOneGetsExecuted"})
public CustomObject customObject() {
log.info(requiredBeans.size());
}
#Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
return new RequiredBean();
}
}
#Autowired list of beans will be same as a single bean of same type, it will contain all beans with that type or with that superclass via springs injection, the problem is the ordering of bean initialization is not controlled properly, #DependsOn with array bean input should resolve this!
Or
You can make CustomObject bean #Lazy, so it will be initialized only when it is used within the code after initialization is done. The bean must not be used within another non-lazy bean I think. Just call some logic where an #Autowired CustomObject is used, it should instantiate the bean at that moment, where the list will contain all possible RequiredBeans
#Lazy
#Bean(name="customObject")
public CustomObject customObject() {
log.info(requiredBeans.size());
}

Spring: How to autowire or (use new) a bean with constructor parameter and which is not a managed bean

There are many similar questions here but none showing how to do it. Here, how can I autowire CreateDatabaseAction bean and use it? It expects a Shoppingcart object, and it is NOT a spring managed bean. Or do I have to create it with new keyword?
public abstract class AbstractServiceActions {
#Autowired
protected DatabaseModel dbModel;
protected User user;
public AbstractServiceActions(ShopingCart cart) {
this.user = user;
}
And implement it:
#Component
public class CreateDatabaseAction extends AbstractServiceActions {
public CreateDatabaseAction(ShoppingCArt cart){
super(cart);
}
}
There's no way for Spring to know what ShoppingCart instance to use when instantiating CreateDatabaseAction if there is no managed bean of that type. I think that you should reconsider the design. For example send it as method parameter where it's actually used and remove it from the constructor.
Considering only the names, I would say that ShoppingCart would be a good candidate for a session scoped bean.

CDI: manual creating beans with constructor arguments

I have a class which I want to be a bean
public class SomeBean{
public SomeBean(){
//default constructor
}
public SomeBean(String someStr){
//constructor with arguments.
}
}
In order to create manually CDI bean I do the following
Bean<?> bean = (Bean<?>) beanManager.resolve(beanManager.getBeans(SomeBean.class));
SomeBean someBean =(SomeBean) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
However the above method will create SomeBean instance wth default constructor. How can I create bean and pass String argument to construcot?
P.S. CDI - WELD
The standard way to define beans with given constructor arguments is via a producer method, e.g.
#Produces #ApplicationScoped #MyQualifier
public SomeBean myBean() {
return new SomeBean("foo");
}
Application code should not normally have to use the BeanManager, unless you want to create a CDI extension.

Categories

Resources