I have inherited an application that is written using Spring 3.2. The application works absolutely fine when built when it is not obfuscated. Once obfuscated (using ProGuard) I get the following exception in my logs.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailStoreFactoryImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [de.aeromaritime.messaging.roudistsrv.data.RdsDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.annotation.Resource(mappedName=, shareable=true, description=, name=, type=class java.lang.Object, lookup=, authenticationType=CONTAINER)}
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1120)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
at de.aeromaritime.messaging.roudistsrv.ServiceMain.main(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.rzo.yajsw.app.WrapperJVMMain.executeMain(WrapperJVMMain.java:53)
at org.rzo.yajsw.app.WrapperJVMMain.main(WrapperJVMMain.java:36)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [de.aeromaritime.messaging.roudistsrv.data.RdsDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.annotation.Resource(mappedName=, shareable=true, description=, name=, type=class java.lang.Object, lookup=, authenticationType=CONTAINER)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:818)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:730)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:438)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
... 19 more
The thing is that the RdsDAO object is never made into a bean in the config.xml. This means it must be instanced by some other part of Spring. So I looked around and found that the PersistenceExceptionTranslationPostProcessor apparently loads objects that annotated with #Resource#Repository. So I checked the RdsDAO object and sure enough it has the correct annotation to be read.
#Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE, readOnly = true)
#Repository
public class RdsDAO implements Serializable
{ ...
}
Then I looked into the config.xml and find
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
<!-- ### enable annotations -->
<context:annotation-config/>
<!-- ### scan for annotations -->
<context:component-scan base-package="de.aeromaritime.messaging.roudistsrv"/>
<!-- ### AOP support -->
<!-- force use CGLIB to proxy classes even if there is an interface -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:spring-configured/>
<!-- Exception translation bean post processor -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<!-- ### Create the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource"/>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!-- ### TX enable transaction annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
So the bean for PersistenceExceptionTranslationPostProcessor is there and should be working (as it does when the application is not obfuscated).
Finally I looked at the code for my mailStoreFactoryImpl bean which has the RdsDAO as a field like this:
public final class MailStoreFactoryImpl extends UnicastRemoteObject implements
ICMailStoreFactory, Serializable
{
#Resource
private RdsDAO rdsDAO;
...
}
Finally just to check, I decompiled my Jar file and looked at both the RdsDAO class, and MailStoreFactoryImpl class and found that they still have the same naming and contain the same fields, so basically Obfuscating didn't do anything to either of these classes. I'm beating my head on the desk trying to understand what Obfuscated did to break this application, but I'm at a loss. If anyone has any ideas I would love to hear from you.
[UPDATE]
I'm adding below the contents of my library.pro file:
#
# This ProGuard configuration file illustrates how to process a program
# library, such that it remains usable as a library.
# Usage:
# java -jar proguard.jar #library.pro
#
# Specify the input jars, output jars, and library jars.
# In this case, the input jar is the program library that we want to process.
-injars dist/ASYM_RDS-unobfuscated.jar
-outjars dist/ASYM_RDS.jar
-libraryjars <java.home>/lib/rt.jar
-libraryjars dist/lib
# Save the obfuscation mapping to a file, so we can de-obfuscate any stack
# traces later on. Keep a fixed source file attribute and all line number
# tables to get line numbers in the stack traces.
# You can comment this out if you're not interested in stack traces.
-printmapping out.map
#-keepparameternames
#-renamesourcefileattribute SourceFile
#-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
# SourceFile,LineNumberTable,EnclosingMethod
# Preserve all annotations.
-keepattributes *Annotation*
# Preserve all public classes, and their public and protected fields and
# methods.
-keep public class * {
# public protected *;
public *;
}
# Preserve all .class method names.
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
# Preserve all public applications.
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
native <methods>;
}
# Preserve the special static methods that are required in all enumeration
# classes.
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# You can comment this out if your library doesn't use serialization.
# If your code contains serializable classes that have to be backward
# compatible, please refer to the manual.
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#Added as per answer to SO question http://stackoverflow.com/posts/25419369
-keepclassmembers class * {
#javax.annotation.Resource *;
}
# Your library may contain more items that need to be preserved;
# typically classes that are dynamically created using Class.forName:
# -keep public class mypackage.MyClass
# -keep public interface mypackage.MyInterface
# -keep public class * implements mypackage.MyInterface
-ignorewarnings
-dontoptimize
Try setting -keepclassmembers to #javax.annotation.Resource?
-keepclassmembers class * {
#javax.annotation.Resource *;
}
If that doesn't work, you might have to wire your context together by name, since your class names are likely getting mangled. Add #Bean("somename") to the classes and update the fields to #Resource("somename") so they match.
Related
Whenever I m running the code attached below I m facing this error....
g4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'proxy': FactoryBean threw exception on object creation; nested exception is java.lang.ExceptionInInitializerError
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:150)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1387)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:244)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1048)
at Sample.Test.main(Test.java:14)
Caused by: java.lang.ExceptionInInitializerError
at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:166)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:144)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:116)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104)
at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69)
at org.springframework.aop.framework.Cglib2AopProxy.createEnhancer(Cglib2AopProxy.java:228)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:170)
at org.springframework.aop.framework.ProxyFactoryBean.getProxy(ProxyFactoryBean.java:362)
at org.springframework.aop.framework.ProxyFactoryBean.getSingletonInstance(ProxyFactoryBean.java:316)
at org.springframework.aop.framework.ProxyFactoryBean.getObject(ProxyFactoryBean.java:242)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:143)
... 6 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module #3e92efc3
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at net.sf.cglib.core.ReflectUtils$2.run(ReflectUtils.java:56)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:46)
... 20 more
BeforeAdviceTest.java
package Sample;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeAdviceTest implements MethodBeforeAdvice {
#Override
public void before(Method method, Object[] args, Object target)throws Throwable {
System.out.println("Additional concern " +"before business logic.");
}
}
BuisnessLogic.java
package Sample;
public class BusinessLogic {
public void implementBusinessLogic(){
System.out.println("Business logic executed.");
}
}
Test.java
package Sample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//Get ApplicationContext using spring configuration file.
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//Get BusinessLogic bean object from ApplicationContext instance.
BusinessLogic businessLogic =
(BusinessLogic) context.getBean("proxy", BusinessLogic.class);
//Call implementBusinessLogic method of BusinessLogic bean.
businessLogic.implementBusinessLogic();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="businessLogic"
class="Sample.BusinessLogic"/>
<bean id="beforeAdviceTest"
class="Sample.BeforeAdviceTest"/>
<bean id="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="businessLogic"></property>
<property name="interceptorNames">
<list>
<value>beforeAdviceTest</value>
</list>
</property>
</bean>
</beans>
Issue is not with AOP, For logging, your using log4j dependency, We needs to do some configuration for log4j. May be configuration missed, Causing these issues
Spring aop configuration problem in eclipse
-- Same code compile and run in Spring tools suite. But does not compile and run in eclipse. What is the problem I can't found out?
-- bean classes --
package com.obydul.spring.aop;
public class Camera {
public void snap() {
System.out.println("SNAP!");
}
}
-- another bean classes --
package com.obydul.spring.aop;
public class Logger {
public void aboutToTakePhoto() {
System.out.println("About to take photo...");
}
}
-- Spring aop configuration in beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="camera" class="com.obydul.spring.aop.Camera"></bean>
<bean id="logger" class="com.obydul.spring.aop.Logger"></bean>
<aop:config>
<aop:pointcut
expression="execution(void com.obydul.spring.aop.Camera.snap())"
id="cameraSnap" />
<aop:aspect ref="logger" id="loggeraspect">
<aop:before method="aboutToTakePhoto"
pointcut-ref="cameraSnap" />
</aop:aspect>
</aop:config>
</beans>
main function:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/obydul/spring/aop/beans.xml");
Camera camera = (Camera) context.getBean("camera");
camera.snap();
context.close();
}
-- exception in console output --
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'camera' defined in class path resource [com/obydul/spring/aop/beans.xml]: Initialization of bean failed; nested exception is java.lang.ExceptionInInitializerError
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:636)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:934)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.obydul.spring.aop.App.main(App.java:8)
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:166)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at org.springframework.cglib.core.KeyFactory$Generator.create(KeyFactory.java:144)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:116)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:108)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:104)
at org.springframework.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69)
at org.springframework.aop.framework.CglibAopProxy.createEnhancer(CglibAopProxy.java:234)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:176)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:479)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:364)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:324)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:409)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1520)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
... 11 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module #179ece50
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.springframework.cglib.core.ReflectUtils$2.run(ReflectUtils.java:56)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
at org.springframework.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:46)
... 28 more
-- I don't know what is the problem in my aop configuration code in beans.xml. Please any one suggest to me how can I solved this problem.
This is the example I'm working on
The problem is I get errors from this code like:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'documentaristOne' defined in class path resource .... for property 'guitarist': no matching editors or conversion strategy found
at org.springframework.beans.factory.support...
Interface:
public interface Singer {
public void sing();
}
Classes:
public class GrammyGuitarist implements Singer{
#Override
public void sing() {
System.out.println("sing: Gravity is working against me\n" +
"And gravity wants to bring me down");
}
public void sing(Guitar guitar) {
System.out.println("play: " + guitar.play());
}
public void talk(){
System.out.println("talk");
}
}
public class Documentarist {
protected GrammyGuitarist guitarist;
public void execute() {
guitarist.sing();
guitarist.talk();
}
public void setGuitarist(GrammyGuitarist guitarist) {
this.guitarist = guitarist;
}
}
public class ProxyFactoryBeanDemo {
public static void main(String... args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("spring/app-context-xml.xml");
ctx.refresh();
Documentarist documentaristOne = ctx.getBean("documentaristOne", Documentarist.class);
Documentarist documentaristTwo = ctx.getBean("documentaristTwo", Documentarist.class);
System.out.println("Documentarist One >>");
documentaristOne.execute();
System.out.println("\nDocumentarist Two >> ");
documentaristTwo.execute();
}
}
app-xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="johnMayer" class="com.apress.prospring5.ch5.GrammyGuitarist"/>
<bean id="advice" class="com.apress.prospring5.ch5.AuditAdvice"/>
<bean id="documentaristOne" class="com.apress.prospring5.ch5.Documentarist"
p:guitarist-ref="proxyOne"/>
<bean id="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdviceNames"/>
<util:list id="interceptorAdviceNames">
<value>advice</value>
</util:list>
<bean id="documentaristTwo" class="com.apress.prospring5.ch5.Documentarist"
p:guitarist-ref="proxyTwo"/>
<bean id="proxyTwo" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdvisorNames">
</bean>
<util:list id="interceptorAdvisorNames">
<value>advisor</value>
</util:list>
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
p:advice-ref="advice">
<property name="pointcut">
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut"
p:expression="execution(* sing*(..))"/>
</property>
</bean>
</beans>
As I see the issue is in an attempt to initialize the GenericXmlApplicationContext In app-xml the row:
<bean id="documentaristOne" class="com.apress.prospring5.ch5.Documentarist"
p:guitarist-ref="proxyOne"/>
Trying to create a documentaristOne instance of Documentarist but for property guitarist we provide not the bean instance of GrammyGuitarist but a proxy one. Yes, proxyOne has ref to GrammyGuitarist via "johnMayer":
<bean id="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdviceNames"/>
But as I see JAVA/Spring doesn't want to accept it. Is it possible somehow to cast type proxy to the target type? If no, what to do then to make this code work?
Full stack below:
org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'documentaristOne' defined in class path resource [ch5/ProxyFactoryBeanDemo/app-context-xml.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist': no matching editors or conversion strategy found
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'documentaristOne' defined in class path resource [ch5/ProxyFactoryBeanDemo/app-context-xml.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at ch5.ProxyFactoryBeanDemo.ProxyFactoryBeanDemo.main(ProxyFactoryBeanDemo.java:14)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist': no matching editors or conversion strategy found
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1748)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1704)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
... 9 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'com.sun.proxy.$Proxy7 implementing ch5.ProxyFactoryBeanDemo.Singer,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.core.DecoratingProxy' to required type 'ch5.ProxyFactoryBeanDemo.GrammyGuitarist' for property 'guitarist': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585)
... 15 more
Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
at org.apache.commons.exec.DefaultExecutor.executeInternal (DefaultExecutor.java:404)
at org.apache.commons.exec.DefaultExecutor.execute (DefaultExecutor.java:166)
at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:764)
at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:711)
at org.codehaus.mojo.exec.ExecMojo.execute (ExecMojo.java:289)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:64)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
The root cause is that Spring Core (not Spring Boot) by default creates JDK proxies, if the target class implements an interface. This is also true for the ProxyFactoryBean example you tried to modify. I.e., as soon as you make GrammyGuitarist implement Singer, you no longer get a CGLIB proxy but a JDK proxy. The JDK proxy is not a subclass of GrammyGuitarist, which means it cannot be cast to that class, but code and configuration refer to that class explicitly, not simply to Singer. Therefore,
either you need to make the bean type Singer
or you configure Spring to create CGLIB proxies by using <aop:aspectj-autoproxy proxy-target-class="true"/> in the <beans> section and p:proxyTargetClass="true" in the two bean configurations using the proxy factory bean.
I am showing you how to change the XML configuration.
This is the diff:
diff --git a/chapter05/proxyfactorybean/src/main/java/com/apress/prospring5/ch5/GrammyGuitarist.java b/chapter05/proxyfactorybean/src/main/java/com/apress/prospring5/ch5/GrammyGuitarist.java
--- a/chapter05/proxyfactorybean/src/main/java/com/apress/prospring5/ch5/GrammyGuitarist.java (revision Staged)
+++ b/chapter05/proxyfactorybean/src/main/java/com/apress/prospring5/ch5/GrammyGuitarist.java (date 1630836290986)
## -1,11 +1,12 ##
package com.apress.prospring5.ch5;
import com.apress.prospring5.ch2.common.Guitar;
+import com.apress.prospring5.ch2.common.Singer;
/**
* Created by iuliana.cosmina on 4/9/17.
*/
-public class GrammyGuitarist {
+public class GrammyGuitarist implements Singer {
public void sing() {
System.out.println("sing: Gravity is working against me\n" +
"And gravity wants to bring me down");
diff --git a/chapter05/proxyfactorybean/src/main/resources/spring/app-context-xml.xml b/chapter05/proxyfactorybean/src/main/resources/spring/app-context-xml.xml
--- a/chapter05/proxyfactorybean/src/main/resources/spring/app-context-xml.xml (revision Staged)
+++ b/chapter05/proxyfactorybean/src/main/resources/spring/app-context-xml.xml (date 1630838376150)
## -2,12 +2,17 ##
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://www.springframework.org/schema/aop
+ http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
+
+ <aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="johnMayer" class="com.apress.prospring5.ch5.GrammyGuitarist"/>
<bean id="advice" class="com.apress.prospring5.ch5.AuditAdvice"/>
## -16,7 +21,8 ##
p:guitarist-ref="proxyOne"/>
<bean id="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean"
- p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdviceNames"/>
+ p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdviceNames"
+ p:proxyTargetClass="true"/>
<util:list id="interceptorAdviceNames">
<value>advice</value>
## -27,7 +33,8 ##
p:guitarist-ref="proxyTwo"/>
<bean id="proxyTwo" class="org.springframework.aop.framework.ProxyFactoryBean"
- p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdvisorNames">
+ p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdvisorNames"
+ p:proxyTargetClass="true">
</bean>
<util:list id="interceptorAdvisorNames">
And this is the full XML config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="johnMayer" class="com.apress.prospring5.ch5.GrammyGuitarist"/>
<bean id="advice" class="com.apress.prospring5.ch5.AuditAdvice"/>
<bean id="documentaristOne" class="com.apress.prospring5.ch5.Documentarist"
p:guitarist-ref="proxyOne"/>
<bean id="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdviceNames"
p:proxyTargetClass="true"/>
<util:list id="interceptorAdviceNames">
<value>advice</value>
</util:list>
<bean id="documentaristTwo" class="com.apress.prospring5.ch5.Documentarist"
p:guitarist-ref="proxyTwo"/>
<bean id="proxyTwo" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="johnMayer" p:interceptorNames-ref="interceptorAdvisorNames"
p:proxyTargetClass="true">
</bean>
<util:list id="interceptorAdvisorNames">
<value>advisor</value>
</util:list>
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
p:advice-ref="advice">
<property name="pointcut">
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut"
p:expression="execution(* sing*(..))"/>
</property>
</bean>
</beans>
I believe you have to let spring beans know which components you are using.
Try adding #Component() annotation above Documentarist GrammyGuitarist class initialization
Here's the portion of our xml that is related to transaction management
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice"/>
<aop:config proxy-target-class="true">
<aop:pointcut id="transactionalMethods"
expression="#annotation(org.springframework.transaction.annotation.Transactional)" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionalMethods" />
</aop:config>
I came up with this
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement( proxyTargetClass = true )
public class TransactionConfig
{
#Bean
PlatformTransactionManager transactionManager( final DataSource dataSource, final EntityManagerFactory emf ) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource( dataSource );
jpaTransactionManager.setEntityManagerFactory( emf );
return jpaTransactionManager;
}
#Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
}
and it seems to work, but reading the config I can't help but wonder if I'm supposed to use mode = ASPECTJ, but when I tried that the context blew up with an exception about not able to inject "Concrete class", as some things depend on the class and not the interface.
I'm not sure why we added that pointcut, or whether we make use of it, if I have to rewrite it as a pointcut, I'm actually not sure how I should do that.
Do I need to add something more to get parity? is this already the same? if I need to add more what should I write?
update
When trying
#Configuration
#EnableAspectJAutoProxy( proxyTargetClass = true )
#EnableTransactionManagement( mode = AdviceMode.ASPECTJ )
and aspectj itself was working via our xml config (the aspects do work in our xml config)
<context:spring-configured/>
<aop:aspectj-autoproxy/>
with deps
[INFO] +- org.springframework.data:spring-data-jpa:jar:1.9.4.RELEASE:compile
[INFO] | +- org.springframework:spring-orm:jar:4.2.7.RELEASE:compile
[INFO] | +- org.springframework:spring-context:jar:4.2.7.RELEASE:compile
[INFO] | | \- org.springframework:spring-expression:jar:4.2.7.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:4.2.7.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | +- org.springframework:spring-beans:jar:4.2.7.RELEASE:compile
[INFO] | +- org.springframework:spring-core:jar:4.2.7.RELEASE:compile
[INFO] | \- org.aspectj:aspectjrt:jar:1.8.9:compile
[INFO] +- org.springframework:spring-aspects:jar:4.2.7.RELEASE:compile
[INFO] +- org.aspectj:aspectjweaver:jar:1.8.9:compile
I get errors like
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.myapp.CatalogItemViewDao com.myapp.ProviderTestHistoryDao.catalogItemViewDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.myapp.CatalogItemViewDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 40 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.myapp.CatalogItemViewDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
No you dont need to set mode = ASPECTJ , unless you expect transaction to be applied on self invocation calls, means calling from another methods in the same class. Other mode proxy which default, will only support calls that coming externally through proxy interfaces.
In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
transaction at runtime even if the invoked method is marked with
#Transactional. Also, the proxy must be fully initialized to provide
the expected behaviour so you should not rely on this feature in your
initialization code,
if you set mode = aspectj , it will use spring AspectJ weaving using byte code modification for affected class and methods. But This will require spring-aspect.jar and CGLIB jars to be present in the class path.
And,
if you are just using #Transactional annotation you don't need define any aop point cuts. You only need to define the transaction manager
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-declarative
If you use ASPECTJ (with spring-aspects-4.x.y.RELEASE.jar), a pointcut definition shouldn't be necessary.
Take a look at aop.xml in the mentioned jar, the AnnotationTransactionAspect is defined there.
I'm using eclipse and when I try to run my spring-GWT application in development mode I get the following Exception when parsing the applicationContext.xml file:
Ignored XML validation warning
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/tx/spring-tx-3.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.warning(ErrorHandlerWrapper.java:96)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:380)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
(...)
Context initialization failed
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 51 in XML document from ServletContext resource [/WEB-INF/applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'tx:annotation-driven'.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
And my applicationContext.xml file starts like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
(...)
Line 51 ---> <tx:annotation-driven transaction-manager="transactionManager"/>
Does anyone know what's happening??
Check you have spring-tx dependencies (or any other spring dependency) in your class path for it to use your schema. All schemas referenced should map to a spring dependency.
xmlns:tx="http://www.springframework.org/schema/tx"
Check this:
http://www.dashaun.com/2010/03/10/springframework-applicationcontext-woes-unable-to-locate-spring-namespacehandler/
Found workaround:
When running GWT devmode, there is an issue starting the spring appcontext,
the tx...xsd cannot be found. This is related to the classloader defined
in this Devmode class of GWT, which delegates to the systemclassloader
(override of jetty)
see: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/ac495ee6605d21b4
This occurs only when defining the tag in spring which is needed for
processing #Transactional annotations for transactions.
The only way to solve it I found (after 2 days) is to look in the stacktrace and find which class of Spring
invoked xerces (since it is xerces which can't find the file). This was "DefaultDocumentLoader"
This class is in spring-beans.jar.
=> So what I did is, I copied all classes from spring-tx.jar into the new spring-beans.jar
so those classes will be loaded by the same classloader
Then I also merged the META-INF/spring.handlers, spring.schemas, spring.tooling files,
All is now in a new jar i've created: spring-beans-tx-3.0.5.RELEASE.jar
This new jar is the first in the classpath of my project.
In this case it works !!