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);
}
}
Related
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.
I am studying for the Spring Core certification and I have the following doubt related how can Spring instantiate classes with private constructors (such as Singleton pattern) or how can instantiate objects from Factories (that are not the Spring context).
For example I have the following singleton factory:
public class AccountServiceSingleton implements AccountService {
private static AccountServiceSingleton inst = new AccountServiceSingleton();
private AccountServiceSingleton() { ... }
public static AccountService getInstance() {
// ...
return inst;
}
}
This is a singleton factory because it build a private static object builded with a private constructor and I have a public method to get this object.
So I think that the problem how can Spring build this object? depends on the fact that that the constructor is private so I can't do something like this in my Java configuration class
#Confguration
public class ApplicationConfig{
#Bean
public AccountServiceSingleton accountServiceSingleton(){
return new AccountServiceSingleton();
}
}
because I can't access to the private AccountServiceSingleton() constructor.
At the same time I can't use the equivalent XML configuration for the same reason.
Have I understand what is the problem or am I missing something?
I think that I am missing something because on the documentation I read that I can use the following 2 solutions for the previous problem:
Use a #Bean method in #Configuration class: so, reading it, I think that the previous Java configuration class work...but why?
XML factory-method attribute in the XML configuration, searching online I found that have to be something like this, but how can I use this to configure the previous AccountServiceSingleton bean in an XML configuration?
Tnx
It's really easy, and you can do it, too:
Constructor cxor = AccountServiceSingleton.class.getDeclaredConstructor();
cxor.setAccessible(true);
return cxor.newInstance();
I found the answer by myself still reading the documentation. I think that the right answer for the question is:
If I want to configure this class as a Spring bean:
public class AccountServiceSingleton implements AccountService {
private static AccountServiceSingleton inst = new AccountServiceSingleton();
private AccountServiceSingleton() { ... }
public static AccountService getInstance() {
// ...
return inst;
}
}
using the Java configuration I simply have to annotate the relative bean method using #Bean in the configuration class.
If I want configure the beans using the XML configuration I have to use the factory method attribute, something like it:
<bean id=“accountService” class=“com.acme.AccountServiceSingleton”
factory-method="getInstance" />
So it say that the getInstance() method will be call to obtain the singleton object from my singleton factory
How about doing like this:
#Confguration
public class ApplicationConfig{
#Bean
public AccountServiceSingleton accountServiceSingleton(){
return AccountServiceSingleton.getInstance();
}
}
I am using Java7 and Spring3. I have below classes.
Request.java
public interface Request {
public void doProcess();
}
RequestImpl.java
#Transactional
public class RequestImpl implements Request{
private String name;
private String age;
//setters and getters
public void doProcess(){
//use name and age and call third party class which will save data into database
}
}
SpringConfig.xml
<bean id="request" class="pkg.RequestImpl.java" />
Now clients will use RequestImpl as below.
RequestImplreq = (RequestImpl)applicationContext.getBean("request");
req.setName("someName");
req.setAge("20");
req.doProcess();
Now my question is do i need to declare above RequestImpl.java scope as prototype or singleton?
Thanks!
IMHO you are not working well: processes and data to process should be separated (Can DTOs be spring managed beans?) so doProcess() should be defined as doProcess(name,age) or shaded behind a factory or something similar.
Probably the best option is to define
public interface Request {
public void doProcess(String name,String age);
}
#Transactional
public class RequestImpl implements Request{
public void doProcess(String name,String age){
// do what you want
}
}
your SpringConfig.xml stay the same and call code will change to:
Request req= applicationContext.getBean(Request.class);
req.doProcess("someName", "20");
Beside all, perform a ApplicationContext.getBean() and cast result to an implementation is (usually) bad pratice because Spring can proxy returned object and cast to implementation will fail with a ClassCastException
#user3269829 : By default the scope would be singleton now it is totally depend upon your requirement, if you want a bean object for every request then you can go for "prototype" and if you want to share single bean object among the multiple request then you can go for "singleton"
It depends on how your third party class is implemented. If you want to ensure a single instance of your class you can use factory-method of spring beans and ensure single instance.
Check "3.3.2.2 Instantiation with a static factory method" part of Spring Documentation
It should look like this in bean definition:
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
and singleton creator:
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private DefaultServiceLocator() {}
public ClientService createClientServiceInstance() {
return clientService;
}
}
I have an abstract class "Command" with an #Autowired dependency and classes extending the abstract class. The dependency is not being injected. The abstract and concrete classes are annotated with #Component and are being scanned. It seems that the base(abstract) class is not spring managed. What needs to be done for it to be? Is there an annotation to define it as abstract? I don't want to define the bean in XML.
public abstract class Command {
#Autowired
private SecurityUtils securityUtils;
....
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
#Component
public class NoteCommand extends Command {
...
}
My mistake I apologize. The command classes are injected in my controllers and one of them (NoteCommand) out many was instantiated manually via "new". All is good.
This can be achieved with XML configuration(not sure about annotations). Read this http://docs.spring.io/spring-framework/docs/3.0.0.RC3/reference/html/ch03s07.html
Try this(add other config to child bean?)
<bean id = "command" class = "some.package.name.Command" abstract = "true">
<property name = "securityUtils" ref = "securityUtils"/>
</bean>
<bean id ="noteCommand" class = "some.package.name.NoteCommand" parent="commadn">
</bean>
cheers!
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring can you autowire inside an abstract class?
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.
I know it's possible to inject a request scoped bean into a singleton bean in Spring so I know what I'm trying to do will work, I'm just wondering if there is a way to express it more concisely without so many extra unnecessary class definitions. I'm new to Spring annotations so maybe there's an annotation I don't know about.
I have an abstract class that will be extended maybe 100 times in my application as different singleton spring beans. Take this class definition for an example:
/** The abstract class with a field that needs to be request-specific **/
public abstract class AbstractSingletonBean {
private SampleState state;
public SampleState getState() { return state; }
public void setState(SampleState state) { this.state = state; }
// Other fields that are just singleton here
}
And an example of what one of the bean definitions might look like:
#Component
public class SampleSingletonBean extends AbstractSingletonBean {
#Resource(name="sampleState")
public void setState(SampleState state) { super.setState(state); }
}
Now of course we need a bean called sampleState. So I have to create two classes: a base class to define the fields in SampleState and then a request-scoped bean definition. This is because each extension of AbstractSingletonBean will need it's own request-scoped instance of the state field.
Here might be the base class:
public class SampleState {
private String fieldOne;
public String getFieldOne() { return fieldOne }
public void setFieldOne() { this.fieldOne = fieldOne }
}
And here is this silly bean definition:
#Component ("sampleState")
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SampleStateBean extends SampleState {}
The thing that bothers me is that if I have 100 extensions of AbstractSingletonBean, I'll need 100 extensions of SampleStateBean with just boilerplate code to make it request-scoped. Is there a way to just override setState() in the extensions of AbstractSingletonBean and indicate to spring that it should create a new request scoped bean on the fly and inject it here? So my SampleSingletonBean could look like this:
#Component
public class SampleSingletonBean extends AbstractSingletonBean {
#Resource
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public void setState(SampleState state) { super.setState(state); }
}
Of course this doesn't work because #Resource needs to refer to a bean that already exists. Is there another annotation to accomplish this without creating a new class for every SampleState bean?
Spring can inject into abstract classes too. So you can move the injection of the SampleState to the abstract class, if each AbstractSingletonBean descendant needs just a SampleState (as in your example).
It doesn't look like this was available out of the box so I created an annotation I call #AnonymousRequest that I put on the field I want, and a BeanDefinitionRegistryPostProcessor to do the work of creating the bean. It basically goes like this:
for each bean in the BeanFactory
if bean class has AnonymousRequest annotation
create request scoped bean from field class
create singleton bean to be request scoped bean wrapper
set the annotated property value to the singleton wrapper
This took a lot of work to figure out how Spring registers request scoped beans. You create the bean definition you want as a request scoped bean. Then you create a singleton bean of type RootBeanDefinition that acts as a wrapper to the request scope bean and set a property on the wrapper called "targetBeanName" to whatever you named the request scoped bean ("scopedTarget." + the singleton bean name by convention).
So this could probably be improved by someone who actually knows this stuff but here's what I came up with:
public void createRequestBeanFromSetterMethod(String containingBeanName, BeanDefinition containingBean, Method method, BeanDefinitionRegistry registry)
{
String fieldName = ReflectionUtil.getFieldNameFromSetter(method.getName());
String singletonBeanName = containingBeanName+"_"+fieldName;
String requestBeanName = "scopedTarget."+singletonBeanName;
BeanDefinition requestBean = createAnonymousRequestBean(ReflectionUtil.getFieldTypeFromSetter(method), containingBean);
RootBeanDefinition singletonBean = new RootBeanDefinition();
singletonBean.setBeanClass(ScopedProxyFactoryBean.class);
singletonBean.getPropertyValues().addPropertyValue("targetBeanName", requestBeanName);
registry.registerBeanDefinition(singletonBeanName, singletonBean);
registry.registerBeanDefinition(requestBeanName, requestBean);
beanDefinition.getPropertyValues().addPropertyValue(fieldName, new RuntimeBeanReference(singletonBeanName));
}
private BeanDefinition createAnonymousRequestBean(Class<?> beanType, BeanDefinition parentBean)
{
BeanDefinition newBean = null;
if (parentBean != null)
{
newBean = new GenericBeanDefinition(parentBean);
}
else
{
newBean = new GenericBeanDefinition();
}
if (beanType != null)
{
newBean.setBeanClassName(beanType.getName());
}
newBean.setScope("request");
newBean.setAutowireCandidate(false);
// This would have come from the Proxy annotation...could add support for different values
String proxyValue = "org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass";
BeanMetadataAttribute attr = new BeanMetadataAttribute(proxyValue, true);
newBean.setAttribute(proxyValue, attr);
return newBean;
}
It seems to work! I effectively have now a request scoped bean created just before the context initialization that is localized to this one containing bean. It's a request-scoped property, more or less.
You can try defining single SampleState request scope bean and then use spring's lookup method to inject this bean wherever you want to.That's works just fine with prototype-scope beans. Fingers crosses it would work with request scope as well.
AFAIK, there is no annotation support for lookup method as of now, so either use it's xml vis-a-vis
or have a look at javax.inject.Provider relevant question here