I am trying to extract the bean from application context.
so I defined class:
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext _applicationContext) throws BeansException {
applicationContext = _applicationContext;
}
}
and in my applicationContext.xml
<bean id="workflowService" class="com.mycompany.util.WorkflowService">
<bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
<context:annotation-config />
However in my code when I try:
WorkflowService service = (WorkflowService) ApplicationContextProvider.getApplicationContext().getBean("workflowService");
I get:
java.lang.ClassCastException: $Proxy40 cannot be cast to com.mycompany.util.WorkflowService
EDITED:
WorkflowService code:
public class WorkflowService implements Serializable {
...
#PostConstruct
public void init() {
}
...
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public Collection<lData> findData(Integer contractId) {
}
}
I guess WorkflowService is a class implementing at least one interface (you haven't provided enough code). You are trying to lookup the exact class from Spring, while you should ask for one of the interfaces.
This is because Spring most of the time wraps beans in several proxies (e.g. transactional ones). If the class implements at least one interface, resulting proxy implements all of them, but cannot be cast into original class. If the class does not implement any interfaces (commonly considered a bad practice for heavyweight services, questionable though), Spring will use CGLIB subclassing from original class. In this case you code would be valid.
Your problem is this bit:
WorkflowService implements Serializable
Any proxies that Spring generates will implement all of the interfaces that your class does - in this case, Serializable, which is almost certainly not what you want.
What you should do is extract a new interface from WorkflowService, which includes the findData method (let's call it WorkflowOperations). By implementing that interface, you'll then be able to cast to that interface, e.g.
public interface WorkflowOperations {
Collection<lData> findData(Integer contractId);
}
public class WorkflowService implements WorkflowOperations {
...
#PostConstruct
public void init() {
}
...
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public Collection<lData> findData(Integer contractId) {
}
}
and then:
WorkflowOperations service = (WorkflowOperations) ApplicationContextProvider.getApplicationContext().getBean("workflowService");
You should probably also remove Serializable from WorkflowService. You almost certainly don't need this, it makes no sense to serialize Spring beans like this. If you just added Serializable out of habit, then remove it (and get out of that particular habit).
You are annotating your service with #Transactional, so Spring is wrapping your service bean with a transactional JDK dynamic proxy that implements the same interfaces as your bean, but is not a WorkflowService. That is why you get a ClassCastException when you try to assign it to a WorkflowService variable. I see two possible solutions:
Specify an interface WorkflowService with your business methods and implement it in a WorkflowServiceImpl class. Then in the Spring context change the bean definition from WorkflowService to WorkflowServiceImpl. This is what I recommend, both as a general design principle and specially to work in a Spring environment: Spring likes interfaces.
In your Spring context, add proxy-target-class="true" to your <tx:annotation-driven/> element in order to force Spring to implement proxies by subclassing, so that proxy instanceof WorkFlowService is true. I find this solution dirtier. Also note that you add a dependency on CGLIB this way.
Related
I'm not so familiar with Spring and I have the following situation:
A repository class:
#Repository
public class MyRepository {
// ...
}
A class that uses the repository class:
public class MyClass extends AbstractClass {
#Autowired
private MyRepository myRepository;
//...
}
I know that if I annotate my MyClass with #Component and use it with an #Autowired, then the #Autowired MyRepository is resolved just fine.
Problem is I am in a situation that I need to create new instances of MyClass with reflection. So MyRepository is never resolved and is null all the time.
Is there a way to use #Autowired in this situation?
Explaining better my situation:
I have some implementations of AbstractClass.
In a setup phase of my application I create a HashMap of these implementations. Basically:
{"MyClass", MyClass.class}
//...
Then I have a generic Controller that maps to the url /{class}?options=...
Using the {class} #PathVariable, the HashMap above and reflection I am able to create a instance of a class based on the given options (this part is important). Do you guys think there's a better way of doing this?
Thanks in advance
Spring itself offers some functionality for doing auto-wiring in your objects
which you created by new or newInstance() or whatever.
To use it you need an AutowireCapableBeanFactory
which you get by Spring's normal dependency injection with #Autowired.
#Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
Then you use its autowireBean(Object) method
to inject the #Autowired properties into your bean.
Object myBean = map.get(className).newInstance();
autowireCapableBeanFactory.autowireBean(myBean);
Design note:
Think well if you really need the approach above.
The javadoc of AutowireCapableBeanFactory advises against using this interface for most use-cases:
This subinterface of BeanFactory is not meant to be used in normal application code: stick to BeanFactory or ListableBeanFactory for typical use cases.
Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example.
You can use Factory Design Pattern over here.
This might seem a little complicated in start but I am sure you will love it after you have implemented it.
Steps:
Add #Component on all implementations of AbstractClass.
Create a factory class as:
#Component
public class MyFactory {
private final Map<String, AbstractClass> impletationMap = new HashMap<>();
#Autowired
ApplicationContext context;
#PostConstruct
public void initialize() {
populateDataMapperMap(context.getBeansOfType(AbstractClass.class).values().iterator());
}
private void populateDataMapperMap(final Iterator<AbstractClass> classIterator) {
while (classIterator.hasNext()) {
AbstractClass abstractClassImpl = (AbstractClass) classIterator.next();
impletationMap.put(abstractClassImpl.getClass().getName(), abstractClassImpl);
}
}
}
When the Bean of this MyFactory class is initialized, then it will lookup for all beans of type AbstractClass and put them in the HashMap(implementationMap).
Now from this factory you can get the HashMap and then get the implementations as and when you require. It will be very easy when you add new implementation of AbstractClass as factory will take care of it.
One work around is instead of binding the MyClass to the Hashmap to bind a Factory class. MyClassFactory. This way you will delegate the construction to a concrete factory that will do the job to instantiate the correct class and initialize the correct repository.
Here is an example:
{"MyClass", MyClassFactory.class}
The factory can be Component as well, then you need to bind the hashmap to the factory instance instead of the factory class. But lets say it is not a component:
//#Component this is optional
public MyClassFactory {
//#Autowired optional
ApplicationContext ctx;
public MyClass createInstance() {
MyRepository repo = ctx.getBean("")
MyClass myclass = new MyClass(repo)
return myclass;
}
}
If you mark it as component you can well also use ApplicationContextAware interface if you are going to autowire the ApplicationContext.
One approach is to declare #Component on top of MyClass.
Then, in the setup phase, you can pass the instance of MyClass instead of MyClass.class itself, in the HashMap. There won't be any need to create instances via reflection.
Note: You can fetch the instance of MyClass from your ApplicationContext in the setup phase.
Try this
#Component
public class SomeClass extends AbstractClass {
private static ApplicationContext applicationContext;
public MyClass getMyClass(){
// Now #Autowired MyRepository will work
return applicationContext.getBean(MyClass.class);
}
}
Yes, you can annotate all your AbstractClass implementation beans with #Component and use the next declaration
#Autowired
private List<AbstractClass> beans;
You can then convert that to a Map in a #PostConstruct method.
Spring won't complain about duplicate definitions if you autowire Lists.
My Spring 4 application, which uses Reactor 2, fails to start with:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'orderHandlerConsumer' could not be injected as a 'fm.data.repository.OrderHandlerConsumer' because it is a JDK dynamic proxy that implements:
reactor.fn.Consumer
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
The OrderHandlerConsumer is really simple:
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
Any ideas what might be going awry?
In your application class file where you define it as Spring application, add underneath it.
#SpringBootApplication
#EnableCaching(proxyTargetClass = true)
While the accepted answer will solve this issue, I think it will be more appropriate for me to explain why appling proxyTargetClass = true will fix this.
First of all, Spring, as a framework, utilizes proxing in order to supply the bean with some extended functionality, such as declaritive transactions via #Transactional, or caching by the means of #Cacheable and e.t.c. There are, in general, 2 ways(*) Spring can create proxy on top of your bean:
Jdk dynamic proxing
CGLib proxing
Offical documentation on this, in case you are interested.
Spring can create jdk dynamic proxy of the bean (in case proxing is required for this bean of course) if original class of the bean implements at least one interface. So spring basically create another implementation of this interface at runtime with some additional logic on top of original class.
What is the problem: if the bean is proxied by the means of jdk dynamic proxing , then you cannot inject this bean via its original class. So something like this:
#SpringBootApplication
#EnableTransactionManagement(proxyTargetClass = false)
public class StackoverflowApplication {
#Autowired private SomeService service;
public static void main(String[] args) {
SpringApplication.run(StackoverflowApplication.class, args);
}
}
#Service
class SomeService implements SomeInterface {
#Override
#Transactional
public void handle() { }
}
interface SomeInterface {
void handle();
}
wont work. Why? Well, becuase #Transactional tells Spring that it needs to create proxy of SomeService at runtime, and within #EnableTransactionManagement I specifically asked Spring to make it by the means of jdk dynamic proxy - spring will succeed, since jdk dynamic proxy can be created, but the problem is at runtime there is not bean of type SomeService, there is only a bean of type SomeInterface (by the way, if you inject service here not by the class, but by the interface - it will work, I assume you understand the reason by reading explaination above).
Solution: by applying #EnableTransactionManagement(proxyTargetClass = true) (notice true value here) you force spring to create CGlib proxy (this rule is applicable only for beans that utilize declarative transaction management, i.e. via annotations). In case of CgLib proxing, Spring will try to extend the original class, and add additional functionality at runtime in the generated child class. And in this case injection by class will work - because the bean extends class SomeService, so
#Autowired
private SomeService someService;
will work perfectly fine. But, in general, if possible, inject bean by interface, not by class. In this case both Cglib and jdk dynamic proxy will work. So, be aware of proxing mechanisms spring can use. Hope it helped, have a nice day.
You can assign a bean name to your OrderHandlerConsumer class so that Autowire resolution will be easier, Moreover, Instead of Autowiring with the concrete class, try to auto-wire with the interface. So that you can change #Service annotation to,
#Service(value="orderHandlerConsumer")
and try to Autowire with the interface type,
#Autowire
reactor.fn.Consumer orderHandlerConsumer;
Please try autowiring as below
class Test{
#Autowired
private Consumer orderHandlerConsumer;
}
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch08s06.html
You can call it two ways.
1st way is without mentioning the proxy [with default proxy], you can Autowire it by the interface like below.
#Autowired
private Consumer orderHandlerConsumer;
Spring AOP will create an instance for OrderHandlerConsumer.
2nd way is, mention the proxy in the bean as ScopedProxyMode.TARGET_CLASS.
then you can Autowire an instance without the interface [based on the class].
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
and Autowire by the class like below.
#Autowired
private OrderHandlerConsumer orderHandlerConsumer;
I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described
Need some help in spring here.
In our project we use XML and annotation configurations (Spring 4.1)
Recently I've faced the following task:
I have a list of beans of scope prototype, all of them implement the same interface.
In addition I have one singleton bean that has execute method. Inside the method the bean should access the list of those prototype beans.
Every time the 'execute' method gets executed I would like to get the access to the different instances of those prototype beans).
In singleton I don't have the whole list of beans known in advance, so I just #Autowire the whole collection so that every bean implementation known in the application context will be loaded.
interface SomeInterface {
}
class PrototypeBean1 implements SomeInterface {
...
}
class PrototypeBean2 implements SomeInterface {
...
}
class MySingletonBean {
#Autowire (????)
List<SomeInterface> allPrototypeBeansLoadedIntoTheApplicationContext;
public void execute() {
// this one is called many times,
// so I would like to get different lists of
//"allPrototypeBeansLoadedIntoTheApplicationContext"
// with different actuals bean upon every invocation
// how do I achieve this???
}
}
So my question is: What is the most clean way to achieve this? Ideally I would like to get a solution totally decoupled from spring interfaces (like injecting ApplicationContext/BeanFactory stuff)
I don't mind to use Aop here (performance is not that critical), but I can't really wrap my head around a clean spring solution. So any help will be appreciated.
Thanks in advance
I have been trying to achieve similar goal with Spring and after reading Spring docs using either ServiceLocatorFactoryBean or method injection (with #Lookup) came up and looked promising.
However after tried both approach results turned out to be frustrating. Neither way supports returning beans in List. And I got this exception:
No qualifying bean of type 'java.util.List' available
Apparently Spring treated the return type as a regular Object.
So eventually my solution became creating a new object to wrap the list as return type.
#Component
#Scope("prototype")
public class ProcessorList
{
private List<Processor> processors;
public ProcessorList(List<Processor> processors)
{
this.processors = processors;
}
public List<Processor> getProcessors()
{
return processors;
}
public void setProcessors(List<ChangeSetProcessor> processors)
{
this.processors = processors;
}
}
then create a Factory class for the List Object:
#Component
public interface ProcessorFactory
{
ProcessorList getProcessorList();
}
Then use ServiceLocatorFactoryBean to register the factory:
#Configuration
public class MyConfiguration{
#Bean
public FactoryBean serviceLocatorFactoryBean()
{
ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
factoryBean.setServiceLocatorInterface(ProcessorFactory.class);
return factoryBean;
}
}
Finally implement the interface and make sure mark them all with #Scope("prototype")
Now you'll get new instance each time you use the factory method!
It's similar to use method injection if you prefer.
I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described