where to apply ApplicationContextAware - java

I have a Service class which is a spring bean and I want to use this Service class inside a class (Class A) which is not a spring bean.
Where exactly should I implement ApplicationContextAware ?
Following is my code
#Service("sharedListsService")
public class SharedListsService
{
}
public class A
{
// I want to call my service class methods here
}

I'm not sure that it is a best solution but you can refactor your A class like following:
public class A {
private SharedListsService sharedListsService;
public void setSharedListsService(SharedListsService sharedListsService) {
this.sharedListsService = sharedListsService;
}
}
and then inject spring bean when you create an A class instance (for example):
SharedListsService sharedListsService = WebApplicationContextUtils.getWebApplicationContext(appContext).getBean(SharedListsService.class);
A a = new A();
a.setSharedListsService(sharedListsService);

ApplicationContextAware applies to spring beans only.
It will inject application context into a bean. That's why you cannot directly use it to get instance of SharedListsService into "A".
You need a bean, possibly a factory for "A" to wire that for you.

Related

Factory returns Bean with EJB injected field Null

I've got a Factory class in Java with some methods which return some Java Bean. All of these Java Beans have some DAO object as fields which are injected with the annotation #EJB. However in every case these DAO are all Null, so I suppose I've a problem with EJB injection. I use WebLogic for deploy. Any suggestions to resolve the issue?
//Factory class
public class Factory extends AbstractFactory {
#Override
public InterfaceService getService() {
return new ClassBean();
}
}
//Bean class
#Stateless(mappedName = "ClassBean")
#LocalBean
public class ClassBean implements IBeanService {
#EJB(beanName = "ClassDAO")
private ClassDAO classDAO;
public List<String> getList() throws ExpectedModelException {
return classDAO.getStringList(); //this one throws NullPointerException
}
Never create Enterprise-Beans using new.
The creation, caching, deletion,... is done by the container.
You must declare ClassDao as #Stateless or #Singleton, ... and the container will create and find it, hopefully if the names are correct.
The Factory is not necessary.

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.

How to manually create a class instance with Spring

I am using Spring Framework for Dependency Injection. At one point I inject an instance of a certain class into another class and I need to create an additional temporary object of the same class. I probably could change the scope of the injected bean to prototype but I wonder if there's another simple way to do that?
My only idea is to create it using new but wanted to know if there is a proper way to do it with Spring.
Just a general example:
#Inject
private ClassA classA;
public void methodA() {
// here I need another instance of ClassA to be used in the scope of this method
}
Just subclass it and use prototype scope.
#Component
#Scope("prototype")
public class ClassB extends ClassA {
}
Then, to use it:
#Autowired
private ApplicationContext context;
public void methodA(){
// will return a new instance (still a bean) every time its called
ClassB bean = context.getBean(ClassB.class);
...
}
You can also cast down to ClassA and use bean name if you like.
There are two ways you can do this based on the purpose of another instance of ClassA.
First,
you can create a new object using "new" keyword.
public void methodA()
{
ClassA antherClassAInstance = new ClassA();
}
This approch is suitable when you want to use the new instance only for this method.
Second,
Declare global instance using #Autowired annotation.
#Autowired
ClassA antherClassAInstance;

Assign data member of a domain class using Spring

Is it possible?
Here is a more detailed case:
class A {
private service x;
//other members
//some more methods.
}
bean definition is available for service but I do not want class A to be a spring bean and neither x to be static.
Is this achievable.
EDIT:
My spring configuration:
<bean id="Service" class="com.xx.yy.Service" />
<--!I do not register class A as a bean. Hence cannot use #autowired directly.-->
It can only be achieved by manually getting the bean from the context.
Service service = context.getBean(Service.class);
A a = new A(service);
I think you should create the factory for instances of class A which should take care of setting x.
#Service
class FactoryA {
#Autowired service x;
public A create() {
return new A(x);
}
}

How can I select Spring bean instance at runtime

Based on parameters passed to a method, I need to select from one of many Spring beans that are implementations of the same class, but configured with different parameters.
E.g. if user A invokes the method, I need to call dooFoo() on bean A, but if it's user B then I need to call the very same method, only on bean B.
Is there a 'Springier' way of doing this other than sticking all the beans in a map, and deriving a key from the parameters passed to my method?
We face that issue in our project, and we solve it through a Factory-Like class. The client class -the one that needed the bean at runtime- had an instance of the factory, that was injected through Spring:
#Component
public class ImTheClient{
#Autowired
private ImTheFactory factory;
public void doSomething(
Parameters parameters) throws Exception{
IWantThis theInstance = factory.getInstance(parameters);
}
}
So, the IWantThis instance depends on the runtime value of the parameters parameter. The Factory implementation goes like this:
#Component
public class ImTheFactoryImpl implements
ImTheFactory {
#Autowired
private IWantThisBadly anInstance;
#Autowired
private IAlsoWantThis anotherInstance;
#Override
public IWantThis getInstance(Parameters parameters) {
if (parameters.equals(Parameters.THIS)) {
return anInstance;
}
if (parameters.equals(Parameters.THAT)) {
return anotherInstance;
}
return null;
}
}
So, the factory instance holds reference to both of the posible values of the IWantThis class, being IWantThisBadly and IAlsoWantThis both implementations of IWantThis.
Seems like do you want a ServiceLocator using the application context as registry.
See ServiceLocatorFactoryBean support class for creating ServiceLocators mapping keys to bean names without coupling client code to Spring.
Other option is to use a naming convention or annotation based configuration.
for example, assuming that you annotate Services with #ExampleAnnotation("someId"), you can use something like the following Service Locator to retrieve them.
public class AnnotationServiceLocator implements ServiceLocator {
#Autowired
private ApplicationContext context;
private Map<String, Service> services;
public Service getService(String id) {
checkServices();
return services.get(id);
}
private void checkServices() {
if (services == null) {
services = new HashMap<String, Service>();
Map<String, Object> beans = context.getBeansWithAnnotation(ExampleAnnotation.class);
for (Object bean : beans.values()) {
ExampleAnnotation ann = bean.getClass().getAnnotation(ExampleAnnotation.class);
services.put(ann.value(), (Service) bean);
}
}
}
}
Sticking them in a map sounds fine. If it's a Spring-managed map (using util:map, or in Java config), that's better than creating it somewhere else, because then Spring owns all the object references and can manage their lifecycle properly.
If the beans (A, B) you are talking about are SessionScope its no problem at all, they will be selected correctly.
public class BusinessLogic {
private BaseClassOfBeanAandB bean;
public void methodCalledByUserAorB() {
bean.doFoo();
}
}

Categories

Resources