I have AOP based loggin functionality with the following settings
Context xml configuration:
<bean id="performanceMonitor"
class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor" />
<aop:config>
<aop:pointcut id="allServiceMethods"
expression="execution(* com.eshop.sfweb.service.impl..*(..))" />
<aop:pointcut id="allEpServices"
expression="execution(* com.service.catalog..*(..))" />
<aop:advisor pointcut-ref="allServiceMethods"
advice-ref="performanceMonitor" order="2" />
<aop:advisor pointcut-ref="allEpServices"
advice-ref="performanceMonitor" order="2" />
</aop:config>
Log4j properties:
log4j.logger.org.springframework.aop.interceptor.PerformanceMonitorIntercept
or=${ep.perflog.level},PERFORMANCE
log4j.appender.PERFORMANCE.File=webAppRoot:WEB-INF/log/performance.log
log4j.appender.PERFORMANCE.threshold=DEBUG
log4j.appender.PERFORMANCE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.PERFORMANCE.DatePattern='.'yyyy-MM-dd
log4j.appender.PERFORMANCE.layout=org.apache.log4j.PatternLayout
log4j.appender.PERFORMANCE.layout.ConversionPattern=%d -- %-5p [%t | %F:%L]
-- %m%n
Is there any way that I can disable the AOP invocations itself depending upon the enviroment?
I can disable the logging very easily but can I disable/enable the entire background process and invocations?
Please let if any clarifications are required.
Since you are using Spring AOP, one quick way to enable or disable aspects could be to simply use Bean profiles.
Define a profile say enableAOP:
Wrap the aop:config in say a configuration file under the specific profile
<beans profile="enableAOP">
<aop:config> <aop:pointcut id="allServiceMethods"
expression="execution(* com.eshop.sfweb.service.impl..*(..))" />
<aop:pointcut id="allEpServices" expression="execution(*
com.service.catalog..*(..))" />
....
</beans>
Now, whichever environment you want the specific aspects enabled, just run with enableAOP profile on.
it's been a while since this question was asked, but here is what I came up with for Spring 2:
Create an empty xml file (aop-context-off.xml) with an empty <beans> declaration.
Then create for example an aop-context-enabled.xml file with your AOP declaration.
Finally when importing the XML you could use :
<import resource="aop-context-${AOP_CONTEXT_SUFFIX:off}.xml" />
This will look for a system variable called AOP_CONTEXT_SUFFIX and if not found force the value to off.
So in the example above, by setting AOP_CONTEXT_SUFFIX to enabled it will load the aop-context-enabled.xml
So the switch being the system variable, you can easily Enable/Disable it at server start.
Related
I have an aspect, which at this moment doesn't do anything special:
#Named
public final class PreventNullReturn {
public void replaceNullWithSpecialCase() {
System.out.print("ASPECT CALLED!");
throw new AssertionError();
}
}
It simply should throw an error to prove that it was called. I have spring-aspects.xml file where I declare aspects:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>
<aop:aspectj-autoproxy/>
<bean class="aspects.PreventNullReturn"
id="preventNullReturn"
></bean>
<aop:config>
<aop:aspect
ref="preventNullReturn"
>
<aop:pointcut
id="preventNull"
expression="execution(* *.getById(..))"
></aop:pointcut>
<aop:before
pointcut-ref="preventNull"
method="replaceNullWithSpecialCase"
></aop:before>
<aop:after
pointcut-ref="preventNull"
method="replaceNullWithSpecialCase"
></aop:after>
</aop:aspect>
</aop:config>
</beans>
And in configuration file for Spring unit tests I use it in this way:
<import resource="classpath*:spring-aspects.xml" />
But aspect is not called. What is funny, even IDE shows Navigate to advised methods tooltip and it navigates properly. I try to follow "Spring in Action, Fourth Edition book in chapter 1.1.3. Applying aspects (and that's why I use XML instead of classes), but I am doing something wrong and I can't figure it out. Please write if I can provide more useful details. I would be grateful if you decide to help me, thank you in advance.
I found an answer on my own, instead importing it as a resource in configuration file for Spring unit tests:
<import resource="classpath*:spring-aspects.xml" />
I have to have its content directly in configuration file for Spring unit tests:
<!--TODO: Move it to separated file-->
<aop:aspectj-autoproxy/>
<bean class="aspects.PreventNullReturn"
id="preventNullReturn"
></bean>
<aop:config>
<aop:aspect
ref="preventNullReturn"
>
<aop:pointcut
id="preventNull"
expression="execution(* *.getById(..))"
></aop:pointcut>
<aop:before
pointcut-ref="preventNull"
method="replaceNullWithSpecialCase"
></aop:before>
<aop:after
pointcut-ref="preventNull"
method="replaceNullWithSpecialCase"
></aop:after>
</aop:aspect>
</aop:config>
Which of course is worse solution than having it in separated file, but it's only way I can make it work.
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.
we are using Spring and hibernate in our project and i have noticed that we have defined <tx:annotation-driven /> in sprint context file and if i put #Transactionalannotation for method i am successfully able to interact with database but if i remove #Transactional annotation from method i am getting exception stating that "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"
is there any way by which i can define all the select operation as non Transactional(i mean without #Transactional annotation) and update and insert as Transactional
Using #Transactional(readOnly=true) is usually the best thing for select-only operations. Using hibernate in auto-commit mode can be wasteful when multiple select statements are needed to complete an operation.
I am able to resolve this issue by using below code in context xml file.
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allServiceMethods" expression="execution(* com.test.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>
</aop:config>
As by default read-only="false" for #Transactional annotation.
So we need to make it as read-only="true" for all read operation(Thanks Affe for pointer)
to set read-only="true" for all select select operation make sure that you start your method name from get and rest below code will code for us. you can change your below configuration as per your need.
<tx:method name="get*" read-only="true"/>
For more information you can refer to below link
Spring Docs
Found in following leagacy code the expression
<aop:config>
<!-- the execution of any method defined in the 'service' package or a sub-package -->
<aop:pointcut id="apiServicesPointCuts"
expression="execution(* my.example.api..service..*.*(..)) && !execution(* java.lang.Object.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="apiServicesPointCuts" />
</aop:config>
the expression
!execution(* java.lang.Object.*(..)
If I read it correct that means do not match advice on any method withhin the java.lang.Object.
Does that make sense when the advice is for a transaction manager?
I'm using aspectj 1.6.8
I have "inherited" an old legacy Spring application. Currently it is using Spring 2.5 (just upgraded it once), and am looking to further upgrade it to Spring 3.
I understand most of the application configuration. There is just one part that I am "not 100%" about. I can guess roughly what it might mean but I need to be absolutely sure hence posting this question:
Here is the configuration snippet (depends on an annotation driven transaction manager not shown here):
<aop:config>
<aop:advisor pointcut="execution(* *..ProductManager.*(..))"
advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="save*" />
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>
My specific two questions are:
What does "execution(* ..ProductManager.(..))" mean (I understand pointcut parlance)
In the attributes section of the advice we are saying apply transaction to all save* related methods, and for everything read-only is false. Can anyone explain why that setting makes sense? Is it additive and effectively saying, for all methods with transaction support (ie. just save* methods) I also want those methods to NOT be read-only transactions. Or is it applying something different (ie. some form of transaction support) to every method of inclusive transacion filter (defined in pointcut).
Thanks for any clarifications. Please, no general answers - I need a concrete explanation for this.
As tx:method has attribute read-only with default value as false, means transaction is read/write.
So in my opinion,
<tx:method name="save*" read-only="false" />
<tx:method name="*" />
is equivalent to
<tx:method name="*" />
execution(* *..ProductManager.*(..)) means that, "for all the methods in the ProductManager class"
tx:advice settings are not additive.
It says that for all methods beginning with save use the default transaction settings.
For the others, this setting means they are NOT read-only transactions.
For the common sense, one would expect
<tx:method name="save*" read-only="false" />
<tx:method name="*" />