<tx:advice id="txAdvice" transaction-manager="jtaTxManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:pointcut id="fooServiceOperation"
expression="execution(* x.y.SampClass.save(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" />
</aop:config>
<bean id="Samp1" class=" x.y.SampClass"></bean>
<bean id="SearchDispatchRpcGwtServlet" class="x.y.server.SearchDispatchRpcGwtServlet">
<constructor-arg>
<list>
<ref bean="webServiceClient"/>
</list>
</constructor-arg>
</bean>
<!-- Service Clients -->
<bean id="webServiceClient" class="x.y.KSBClientProxyFactoryBean">
<property name="serviceEndpointInterface" value="x.y.service.WebService" />
<property name="serviceQName" value="{http://x.y.org/wsdl/organization}WebService" />
</bean>
This is the part of sample spring context file. I am trying to create a transaction advice for SampClass to execute on the save method.
So from my understanding it should create a proxy for SampClass only.
I have a SearchDispatchRpcGwtServlet which takes as an argument a webservice Client which is also a proxy in itself. This bean is also getting proxied for some reason where it fails because it cannot create a proxy of a proxy.
I must add that SearchDispatchRpcGwtServlet creates an instance of SampClass and calls the save method.
I get the following exception:
java.lang.IllegalArgumentException:
Cannot subclass final class class
$Proxy118 at
net.sf.cglib.proxy.Enhancer.generateClass(Enhancer
.java:446) at
net.sf.cglib.transform.TransformingClassGenerator.
generateClass(TransformingClassGenerator.java:33)
I dont understand why SearchDispatchRpcGwtServlet proxy is getting created. Can someone explain.
Addition Stack Trace
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy117]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy117
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:473)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:348)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:309)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:361)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1427)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:139)
... 85 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy117
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
a subclass of AbstractAutoProxyCreator is trying to proxy a bean, but that bean is already itself a CGLIB proxy created using another mechanism such as aop:config proxy-target-class="true.
To avoid this, make sure to avoid mixing the different aspect weaving mechanisms (ProxyBeanFactory and aop:config ) for the same bean.
In this case the transaction aspects can also be weaved via <tx:annotation:driven/> via the #Transactional annotation.
Alternatively it would be possible to remove the autowiring/scan from the bean and do the injection of dependencies via XML using setters.
Another alternative is to use load time weaving everywhere by declaring <context:load-time-weaver/> and adding the needed jars.
Have a look also at this post, it general it would be better to use only one one way of applying the aspects in the whole application, in order to avoid this problem.
Related
I am using spring jpa. I have implemented transaction management using
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'find' are read-only -->
<tx:method name="find*" read-only="true" />
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transactionalServiceOperation"
expression="execution(* com.test..*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionalServiceOperation" />
</aop:config>
Recently i noticed that although in some cases transaction management is working but in other cases it is not. For example , i have this piece of code inside a service method which is annotated by #org.springframework.transaction.annotation.Transactional.
The code inside the method
guardianService.save(newFather);
parentsSet.add(newFather);
Guardian oldMother = guardianService.findById(motherId);
In the above case the data in the database does not persis till the 3rd line. As soon as the application finishes executing the 3rd line the data of newFather gets comited to the database even if the application generates Exception after the 3rd line.
Code snippet of guardianService.findById(motherId)
#Override
public Guardian findById(long guardianId) {
return guardianRepository.findByGuardianId(guardianId);
}
Inside GuardianRepository
public interface GuardianRepository extends JpaRepository<Guardian, Long> {
Guardian findByGuardianId(long id);
}
Code snippet of guardianService.save(newFather);
#Override
#Transactional
public Guardian save(Guardian guardian) {
return guardianRepository.save(guardian);
}
So my question is does the find() method somehow calls the flush() or commit()?
The find() method actually does invoke the flush method. By default in JPA, FlushModeType is set to AUTO, which means that if query to database occurs, the data in database has to be up to date for current transaction. From definition:
When queries are executed within a transaction, if FlushModeType.AUTO
is set on the Query object, or if the flush mode setting for the
persistence context is AUTO (the default) and a flush mode setting has
not been specified for the Query object, the persistence provider is
responsible for ensuring that all updates to the state of all entities
in the persistence context which could potentially affect the result
of the query are visible to the processing of the query.
I've come across a little problem concerning the utilization of Configuration classes in bean injection when migrating to Hibernate 4.3.
The configuration class I inject overrides certain methods from the org.hibernate.cfg.Configuration Class like validateSchema()
In Hibernate 3, I have this in my configuration file and it works because the get/set methods for configurationClass exists :
<bean id="SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="$[DATA_SOURCE]" />
</property>
<property name="entityInterceptor">
<ref bean="entityInterceptor"/>
</property>
<property name="configurationClass">
<value>com.hibernate.cfg.CustomSchemaValidationConfiguration</value>
</property>
Meanwhile, in Hibernate 4.3, I get this error because the setConfigurationClass() method doesn't exist anymore.
Invalid property 'configurationClass' of bean class [org.springframework.orm.hibernate4.LocalSessionFactoryBean]: Bean property 'configurationClass' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
Thing is that I still want/need to use que configuration class.
I've seen many examples in code but I want to stay with the spring injection way. Is it posible ? Any suggestions ?
I'm trying to use Oval 1.84 for getting around some validation constraints without boilerplates. The validation works when I mark fields with #NotNull (javax.validation.constraint and net.sf.oval.validator).
But doesn't work in the case of implementing constarints to method and constructor parameters.
Parameter validation requires the use of some method invocation intercepting bytecode. OVal provides ready to use implementations for AspectJ and Spring AOP.
With AspectJ
How to use it with AspectJ is documented in detail at http://oval.sourceforge.net/userguide.html#programming-by-contract
With Spring AOP
The usage with Spring AOP is outlined in the test case at
https://svn.code.sf.net/p/oval/code/trunk/src/test/java/net/sf/oval/test/integration/spring/SpringAOPAllianceTest.java
In Spring you need to configure your beans for which you want to have method parameter validation, e.g.:
<bean id="myService" class="com.example.MyService" />
And an Invocation Interceptor:
<bean id="ovalGuardInterceptor" class="net.sf.oval.guard.GuardInterceptor" />
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="false" />
<property name="interceptorNames">
<list>
<value>ovalGuardInterceptor</value>
</list>
</property>
<!-- the next line tells which beans you want to use validation for -->
<property name="beanNames" value="myService" />
</bean>
I'm trying to create a FreeMarker configuration in Spring 4 using org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean, and then customising the resulting freemarker.template.Configuration (to change the arithmetic engine).
I'm using the following XML config (simplified):
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPaths">...</property>
...
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="freemarkerConfiguration" />
<property name="targetMethod" value="setArithmeticEngine" />
<property name="arguments" value="#{T(freemarker.core.ArithmeticEngine).CONSERVATIVE_ENGINE}" />
</bean>
It works, but I get a lot of warnings during the application startup:
2015-02-27 13:53:03,321 [localhost-startStop-1] [:] WARN support.DefaultListableBeanFactory - Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.beans.factory.config.MethodInvokingFactoryBean#0' defined in ServletContext resource [/WEB-INF/spring/freemarker.xml]: Cannot resolve reference to bean 'freemarkerConfiguration' while setting bean property 'targetObject'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'freemarkerConfiguration': FactoryBean which is currently in creation returned null from getObject
My understanding is that it happens because the FreeMarkerConfigurationFactoryBean implements the FactoryBean<> interface. As such, this FactoryBean is "prepared" first, and then FactoryBean.getObject() is called whenever the actual bean it creates (freemarker.template.Configuration) needs to be accessed.
It seems the MethodInvokingFactoryBean gets invoked while the underlying bean is still being "prepared" by FreeMarkerConfigurationFactoryBean, resulting in FreeMarkerConfigurationFactoryBean.getObject() returning null and the method invocation failing.
I suspect I'm getting a lot of warnings because Spring repeatedly tries to invoke the method and fails. At some point the bean produced by the factory is ready, and the method invocation works.
So:
Is my analysis correct?
Why is that happenning? I would think the dependency injection system should detect the dependency between the MethodInvokingFactoryBean and the freemarkerConfiguration, and invoke the method after the factory bean is ready. I tried to add depends-on="freemarkerConfiguration" on the MethodInvokingFactoryBean but it didn't help.
Is there a way to achieve what I want in XML (I can't switch to Java #Configuration right now). Basically I need a way to call freemarker.core.Configurable.setArithmeticEngine() from XML.
Thanks.
After reading some spec I find this, hope is useful for you:
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="arithmetic_engine">conservative</prop>
</props>
</property>
</bean>
ref: Freemarker Docs
A FactoryBean is supposed to create a bean, not to call a method on a bean! Also the method invoking version will try to create a bean by calling the configured method of the object passed to create a new bean.
What you should look on instead, is the freemarkerSettings property of the FreeMarkerConfigurationFactoryBean and set properties including the arithmetic engine:
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPaths">...</property>
<property name="freemarkerSettings">
<map>
<entry key="#{T(freemarker.core.Configurable).ARITHMETIC_ENGINE_KEY}"
value="#{T(freemarker.core.ArithmeticEngine).CONSERVATIVE_ENGINE}"/>
</map>
</property>
...
</bean>
I've got some trouble while configuring spring transaction manager. The application I'm working on has a layered architecture. Therefore it has a service layer containing all the transactional services. I wanted for spring to rollback the transaction when a checked (application specific) exception has occurred. I succeeded doing that by annotation as follows:
#Transactional(value="transactionDds", rollbackfor="Throwable")
This works fine. But since I've so many services hence I want to move this configuration to XML (spring DAO context file). This is what I've done:
<tx:advice id="txAdvice" transaction-manager="transactionManagerDds">
<tx:attributes>
<tx:method name="*" read-only="false" propagation="REQUIRED" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transRollbackOp" expression="execution(*fr.def.iss.ult.moduleManagement.service.dds.*.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transRollbackOp"/>
</aop:config>
<bean id="transactionManagerDds" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="beanDataSourceFactory" />
<qualifier value="transactionDds"/>
</bean>
So basically, I'va a transaction manager which is associated to an advice which rolls back for the possible methods when a Throwable exception occurs. And this advice is linked to an AOP config that way we specify all the interfaces in the service layer of application on which this transaction configuration is to be applied. But this doesn't work. Transaction doesn't roll back Throwable exception occurs. I don't understand that this works with annotation but not with declarative configuration in XML.
I'm really looking forward for your suggestions. I'm totally blocked. Plz help me out. Thanx in advance.
<aop:config>
<aop:pointcut id="transRollbackOp" expression="execution(*fr.def.iss.ult.moduleManagement.service.dds.*.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transRollbackOp"/>
</aop:config>
In your <aop:config /> the expression you entered is invalid. It should at least contain a whitespace between * and fr.def.
Next instead of .*.*.* I suggest writing ..*.* which selects all classes in all subpackages regardless of depth.
In short change your expression to execution(* fr.def.iss.ult.moduleManagement.service.dds..*.*(..)) should make it work.