Original interface is lost in Spring AOP introduction - java

Here is my Spring AOP configuration.
<bean id="myObject" class="com.madzone.learn.spring.aop.OriginalClass"></bean>
<bean id="aspect" class="com.madzone.learn.spring.aop.AspectClass"></bean>
<aop:config>
<aop:aspect ref="aspect">
<aop:declare-parents
types-matching="com.madzone.learn.spring.aop.OriginalClass+"
implement-interface="com.madzone.learn.spring.aop.IntroducedInterface"
default-impl="com.madzone.learn.spring.aop.IntroducedInterfaceImpl" />
</aop:aspect>
ApplicationContext context = new ClassPathXmlApplicationContext("myApp.xml");
Object myObject = context.getBean("myObject");
if (myObject instanceof OriginalClass) {
System.out.println("This is OriginalClass");
}
if(myObject instanceof IntroducedInterface) {
System.out.println("This is IntroducedInterface");
}
With this introduction I was able to call the methods in the IntroducedInterface. But, I was not able to access the OriginalClass' methods. In the code snippet above, I never got the 'This is OriginalClass' printed out.
From the definition of 'Introduction' I understood that the proxy that implements the new interface will extend from OriginalClass and make its' methods accessible too.
Am I missing something here? Can someone explain the reasons, if any?
PS:
The following is a picture from Spring in Action (3rd Edition) that depicts this.

From the definition of 'Introduction' I understood that the proxy that
implements the new interface will extend from OriginalClass and make
its' methods accessible too.
I'm not sure where you got that impression from. All of Spring AOP is built, by default, on JDK dynamic proxies, which only work for interfaces. It's impossible to proxy a concrete class. There is support in Spring for using CGLIB proxies in order to proxy classes instead, but its use is discouraged by the reference guide in favor of programming to interfaces to reduce coupling.

Related

#DeclareMixin with Spring AOP?

Is it possible to use #DeclareMixin with Spring AOP? Or do they only support #DeclareParents?
I want to write an aspect that mixes in the java.beans.PropertyChangeSupport into a java bean:
public class PropertyChangeSupportWithInterface extends PropertyChangeSupport
implements IObservableBean {
public PropertyChangeSupportWithInterface(Object sourceBean) {
super(sourceBean);
}
}
(IObservableBean simply contains all public methods from the PropertyChangeSupport)
#Aspect
#Named
public class ObservableAspect{
#DeclareMixin("#ObservableBean *")
public static IObservableBean createDelegate(Object object) {
return new PropertyChangeSupportWithInterface(object);
}
}
It seems that this aspect is never used, which makes me think that the #DeclareMixin is not supported by the runtime weaving done by Spring AOP.
Is there any way to get this working with Spring AOP?
You can find a (not) running example here (Maven multi module project):
https://github.com/BernhardBln/SpringAOPObservableBean
See the (only) test case in the springaop-observable-bean-aspect submodule.
No, it's not supported by Spring AOP out the box. I see two options:
Create a DeclareMixinIntroductionInterceptor for Spring AOP.
Switch to Aspectj
I think that PropertyChange interface fits better in Aspectj because usually you will create a lot of proxies for prototype beans and them could be created easily out of the framework, by an ORM for example.
Edit
However I'm interested in this feature too and I already done some work for use it:
A DelegateFactoryIntroductionInterceptor to support creating delegates from the aspect instance.
A DeclareMixinAdvisor to join the inteceptor with the type pattern.
A DeclareMixinAspectJAdvisorFactory to support the DeclareMixin annotation.
To use it you only need to declare a bean of type DeclareMixinAutoProxyCreatorConfigurer
for configuring the AnnotationAwareAspectJAutoProxyCreator with the AdvisorFactory above.
I'm just testing, but seem that work fine.

I want to define a Spring Bean CLASS with NO Interface

I have a spring bean that extends HibernateDaoSupport. I want this bean injected into my Controllers, but I do NOT want it to implement any interface. I just want to refer to the concrete class from within the rest of my code (not use the AopProxy perhaps?) Does anyone have a way of doing this?
<bean id="mySampleService" class="com.sample.MySampleService">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
#Autowired
private MySampleService mySampleService;
... getters and setters ....
I know it's a good idea to use the interface and that's the whole point of IoC, but PLEASE DON'T suggest I use the interface.
If class to be proxied (by transactional proxy in your case) implements any interface (InitializingBean implemented by HibernateDaoSupport in your case), Spring by default uses proxying strategy based on JDK dynamic proxies.
So, it creates a proxy of type InitializingBean, that, obviously, cannot be injected into a field of type MySampleService.
If you don't want to use interface you can override the strategy used by transactional aspect by declaring <tx:annotation-driven> with proxy-target-class = "true".
See also:
7.6 Proxying mechanisms
Check the following. Ensure you have CGLIB on your classpath.
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch08s06.html
you can write everything including the mapped controller in the xml as beans, then you don't need to write interfaces.
otherwise, with using annotation you need to build interfaces to proxy them.

Implementing DAO with Spring

I'm thinking of implementing Objectify DAO with dependency injection, such that I can maintain my code to access the same "Dao" while the implementation may change from Objectify to Hibernate-MySQL or MongoDb in the future without me worrying on changing any code in the UI or client side.
UserDao is based on the example here:
http://turbomanage.wordpress.com/2010/01/28/simplify-with-objectify/
UserObjectifyDaoImpl implements Dao<User> {
private UserDao dao = null;
public void put(User entity) {
if (dao == null) {
dao = new UserDao();
}
dao.put(entity);
}
// other put and set methods
}
Such that, I have the context.xml:
<bean id="userDao" class="com.example.server.daoimpl.UserObjectifyDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
And if I need to change the implementation, I just need to change this bean from UserObjectifyDaoImpl to something like:
UserHibernateDaoImpl or UserMongoDBDaoImpl or whatever implementation saving to whatever database.
And still have my code in the UI / Client intact, like:
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
Dao dao = (Dao) ctx.getBean("userDao");
dao.put(something);
One reason I need to do this right now, I need to develop using app engine (via objectify), however in the future I may need to change some data access objects to hibernate and some to mongodb (so its a mix).
I haven't tested this code, will this strategy work?
Yes, this will work. In fact this is one of the major reasons why DI and coding to an interface was invented. Just make sure that all DAO implementations follow the same contract (DAOs very often introduce leaky abstractions).
Also you have several other options to achieve the same goal:
Several #Service annotated classes with one marked as #Primary (if you are using autowiring)
Spring profiles and selective activation of beans
BTW if you are considering switching to a different DAO implementation, have a look at CrudRepository from Spring Data. Spring Data project provides several modules that implement this interface for MongoDB, Neo4J, JPA, etc.
For the time being it seems like several Spring Data modules do not play together nicely (see: DATAJPA-146), so if you choose to implement CrudRepository make sure this issue is fixed or you can work it around. Thanks to #iddqd for pointing that out.
You can changes context config to selected Dao implementation if you only need one implementation in application but if you need more than one implementation in your application(mixing mode), you need design Factory Layer. You trying design a layer with name Factory and with its APIs and implementations and it decide witch Dao(Hibernate, MongoDB, JP or etc) in any time must select.

Spring #Transactional persist method not working

I have a Spring MVC sample application it uses UserDaoImpl class to save a User type object to database. Following is the UserDaoImpl code.
public class UserDaoImpl implements UserDao<User> {
private EntityManagerFactory emf;
#PersistenceContext
private EntityManager em;
#Transactional
public void saveUser(User user){
em.persist(user);
}
}
and my UserDao interface looks like this.
public interface UserDao<User> {
public void saveUser(User user);
}
Weird thing is happening when when my UserDaoImpl class implements the UserDao interface. When trying to persist it gives the following error.
java.lang.ClassCastException: $Proxy71 cannot be cast to org.samith.UserDaoImpl
When I remove the "implements UserDao" part from the UserDaoImpl class user is persisted to database as expected.
Also I tried UserDao interface without User parameter(that is non generic version). Still above error occurs.
This may be a trivial question to answer but I am scratching my head finding a solution for about few hours.
What wrong am I doing ??
You're not providing the problem code, (or the full stack trace) but the rundown is this:
When you annotate a class as #Transactional, and Spring creates an instance for you, what you get is not that class, but a Java Dynamic Proxy that implements that classes' interfaces. http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
Because of this, you cannot cast that object to the original type (it's not that type anymore!) and must use it's interface(s) instead.
If there aren't interfaces to implement, it will give you a CGLib proxy of the class, which is basically just a runtime modified version of your class, and so is assignable to the class itself.
Search for where you're injecting, or casting to type UserDaoImpl, and change the reference to UserDao instead, and it will work properly.
I've read the performance difference between CGLib proxies and Dynamic Java Proxies is quite minimal, so you can also add the following to your spring config to force it to use CGLib proxies instead of Java Dynamic Proxies:
<aop:config proxy-target-class="true">
In general however, I'd recommend you not use CGLib Proxies, but instead access your class from its interface. Loose coupling will allow you to do runtime substitution, and limits your ability to accidentally introduce brittle class dependencies.
There are some problems that using Java Dynamic Proxies will introduce however, and what you're doing is close enough to what I was doing that you should be aware of this:
How to use Dynamic Proxies with JSF when the method signature contains Object ... args
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
worked for me too. the point was proxy-target-class="true" thanks to owner of the accepted answer. But then cglib dependency will be needed.

Java EE 6 injection to create different strategies

Say that I have class Controller with property strategy of type IStrategy. In Spring, I can create different instances of Controller and inject different strategy implementations by defining beans in xml configuration file as shown below:
<bean id="strategyAController" class="com.test.Controller">
<property name="strategy" ref="strategyAImpl">
</bean>
<bean id="strategyBController" class="com.test.Controller">
<property name="strategy" ref="strategyBImpl">
</bean>
<bean id="strategycController" class="com.test.Controller">
<property name="strategy" ref="strategycImpl">
</bean>
I can then reference these beans using #Autowired and #Qualifier("strategyAController"), etc. What is the equivalent way of doing this in Java EE 6
Funny you should ask! Gavin King, who designed Java EE 6 CDI, got into a nasty fight with someone on exactly the same problem.
http://www.tsolak.com/?p=59
The Spring code, of course, looks awfully like Java. We can do that in java - create some variables, set some properties, no biggie. I am curious, in your perticular application, what's the drawback of doing it in plain Java? What's the specific benefit you get from Spring for these beans?
In CDI you can use Qualifer to identify the different instances and producer methods to provide that instances.
public class ControllerFactory {
#Produces
#StrategyA
public Controller createControllerA {
return new Controller(configA);
}
#Produces
#StrategyB
public Controller createControllerB {
return new Controller(configB);
}
}
#StrategyB
#Inject
Controller howToAccessIt;
If you do not like to create a new StrategyA/B/C Annotation for each strategy, you could use one Annotation with an Field (for example an Enum) that identify the strategy. So that you can write: #Strategy(StratType.A).
Then you can use the InjectionPoint in your producer method, so that you can create the instance depending on the annotation in a generic way, instead of writing a new producer method for each Strategy:
#Produces
//must add a Annotation to clarify that this producer produces for all Strategies!
public Controller createController(InjetionPoint ip) {
Annotated annotated = ip.getAnnotated();
if (annotated.isAnnotationPresent(Strategy.class)) {
Strategy stragtegyAnnotation = (Strategy) annotated.getAnnotation(Strategy.class);
switch(stragtegyAnnotation.value) {
case A: return new Controller(configA);
...
}
}
}
So, I'm not really familiar with EE6 annotations, but I solved a similar issue using pure Spring annotations in a question that I asked and then answered myself. It's not quite the same thing because it only creates once instance, but with all of the different dependencies injected into a Map. Basically, it will allow to switch implementations based on a config flag, but not instantiate all of them at once.

Categories