I am using Aspect for logging activities in my spring mvc based application. I am using #controller annotations to define any controller in my application. I have two different controller in two different package say
com.package1 contains controller 1 class, let's name it as AController
com.package2 contains controller 2 class, let's name it as BController
I am able to apply aspect to one particular package of controllers by using
<aop:config>
<aop:pointcut id="pointcut1"
expression="execution(* package1.*.*(..))"
id="policy1" />
<aop:aspect ref="aspect1" order="1">
<aop:before pointcut-ref="pointcut1" method="before" arg-names="joinPoint" />
<aop:after-returning returning="returnValue" arg-names="joinPoint, returnValue" pointcut-ref="pointcut1" method="after" />
</aop:aspect>
</aop:config>
<bean id="aspect1" class="com......aspectclass" />
My question is how to specify more that one different package in expression(* package1...(..))**.
Right now I am declaring one separate pointcut for each package and in aspect one separate aop:before and aop:after entry for each pointcut. But I think this should be ideal way to define multiple packages pointcut.
You can use boolean operators:
expression="execution(* package1.*.*(..)) || execution(* package2.*.*(..))"
In case you use Annotations
#Pointcut("within(com.package1..*) || within(com.package2..*)")
In spring Boot
#Before("execution(* PackageName.Controller.Service.MethodName(..))
||execution(* PackageName.Controller.Service.*.*(..))")
Example Spring-projects/AOP
#Pointcut("execution(* pakageName.anyClassNameX.*(..)) || execution(* pakageName.anyClassNameY.*(..))")
public void allMethods() {
}
#Around("allMethods()")
public Object intercept(ProceedingJoinPoint thisJoinPoint) throws Throwable {
try {
return thisJoinPoint.proceed();
} catch (Exception ex) {
}
}
Related
I am writing a new spring boot app that is using existing jar files that work fine in other non spring boot applications (they are using spring).
In our service layer, we are using spring transactions and spring AOP that have their configurations defined in an XML file. For example:
<!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
<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" propagation="REQUIRED"/>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" propagation="REQUIRED"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for any execution
of an operation on any service -->
<aop:config>
<aop:advisor pointcut="com.company.app.common.aspect.SystemArchitecture.serviceTransaction()"
advice-ref="dbTransaction" order="1010" />
<aop:aspect ref="verifyDatasourceSwitch" order="1001">
<aop:around pointcut="com.company.app.common.aspect.SystemArchitecture.serviceOperation()"
method="verifyDatasource" />
</aop:aspect>
<aop:aspect ref="appDatasourceSwitch" order="12">
<aop:around pointcut="com.company.app.common.aspect.SystemArchitecture.controlDatasource()"
method="switchToControl" />
</aop:aspect>
<aop:aspect ref="controlMongoDatabaseSwitch" order="13">
<aop:around pointcut="com.company.app.common.aspect.SystemArchitecture.controlMongoDatabase()"
method="switchToControl" />
</aop:aspect>
</aop:config>
The aspects and pointcuts are defined like this:
#Aspect
public class SystemArchitecture
{
/**
* A join point in the service layer if the method is defined
* in a type in the com.company.app.service package or
* any sub-package under that
*/
#Pointcut("within(com.company.app.service..*)")
public void inServiceLayer() {}
#Pointcut("inServiceLayer() && this(com.company.app.service.Service)")
public void serviceRegularOperation() {}
/**
* A service operation is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementations are in sub-packages.
*/
#Pointcut("serviceRegularOperation() || serviceBrandOperation() || serviceCustomerOperation() || serviceWithChangeLoggingOperation() || serviceNonStandardService()")
public void serviceOperation() {}
#Pointcut("serviceOperation() && !#annotation(com.company.app.service.advice.NoTransaction)")
public void serviceTransaction() {}
}
This is all working correctly in other apps that are using it.
In the spring boot app, I have a configuration class that includes the xml config containing the above.
#Configuration
#PropertySource("classpath:config/application.properties")
#ImportResource({ "classpath:aspect.xml",
"classpath:rabbit.xml",
"classpath:email.xml",
"classpath:approval.xml",
"classpath:event.xml",
"classpath:facades.xml",
"classpath:general.xml",
"classpath:velocity.xml",
"classpath:mongo.xml",
"classpath:services.xml",
"classpath:velocity-service.xml",
"classpath:velocity-facade.xml",
"classpath:sharedservices.xml",
"classpath:jobs.xml",
"classpath:cachesharedfacades.xml",
"classpath:sharedContext-security.xml",
"classpath:hibernate-common-session-factory.xml",
"classpath:hibernate-datasource.xml",
"classpath:hibernate-local-transaction-manager.xml",
"classpath:hibernate-mysql-session-factory.xml",
"classpath:hibernate-repositories.xml",
"classpath:mysql-repositories.xml",
"classpath:hibernate-template.xml",
"classpath:repository-mbeans.xml",
"classpath:spring-transaction.xml" })
public class ApplicationConfiguration
{
}
The main application is created as:
#SpringBootApplication
public class GraphqlApplication
{
public static void main( String[] args )
{
SpringApplication.run( GraphqlApplication.class, args );
}
}
When the application is started up, I see warnings such as:
Bean 'adminTypeService' of type [com.company.app.service.impl.AdminTypeServiceImpl]
is not eligible for getting processed by all BeanPostProcessors
(for example: not eligible for auto-proxying)
Which I assume is causing the proxying not to happen, which is probably what is stopping the AOP calls from working.
Am I missing something? I can see the beans defined in the services.xml are created, but when calling a service methods, they interface isn't proxied, so there are no transactions or other supporting functions called via AOP that need to happen.
Thanks in advance!
I am using Guice to manager my class dependence. I have a LogicHandler class which depended on several Components class.
public interface LogicHandler {
private Component component1;
private Component component2;
private Component component3;
}
public interface Component {
public String doWork();
}
I will have 3 instances of LoigcHanlder. Using which instance will be decided in run time. Each of instance will have different Component implementation and all implementation are pre-defined.
If I were using spring DI, the xml config would be look like:
<bean id="handler1" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationA" />
<property name="component2" ref="componentImplementationB" />
<property name="component3" ref="componentImplementationC" />
</bean>
<bean id="handler2" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationD" />
<property name="component2" ref="componentImplementationE" />
<property name="component3" ref="componentImplementationF" />
</bean>
<bean id="handler3" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationG" />
<property name="component2" ref="componentImplementationH" />
<property name="component3" ref="componentImplementationI" />
</bean>
Note: all handlers are implemented by DefaultHanlder.
Using which handler instance bases on some parameters.
Assuming I am understanding your question correctly, you would like to pick a particular concrete implementation to bind based on a particular parameter. One way to do this is to create a module that takes as a constructor the parameters you need for deciding which module to bind. The logic to bind the particular concrete implementation would be in the bind method of the module. E.g
public class YourModule extends AbstractModule {
Parameters settings;
public YourModule(Parameters settings) {
this.settings = settings;
}
#Override
protected void configure() {
if(settings.val == 1) {
bind(DefaultHanlder.class).toInstance(ComponentA.class);
} else if(settings.val == 2) {
bind(DefaultHanlder.class).toInstance(ComponentB.class);
}
.
.
.
}
When you create the injector, use the YourModule module so that the right wiring is put in place. The injector then should inject the proper concrete class for DefaultHanlder without your client code knowing how to pick the right concrete implementation.
There are probably other ways to do this as well (e.g. AssistedInjection might also work) but using a separate module is pretty straightforward.
Use Qualifiers (for example #Named("handler1")) and explicitly bind your instances.
bind(Component.class).annotatedWith(Names.named("handler1").toInstance(...);
transaction has been initiated using following codes in Application Context file:
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*InOwnTransaction" propagation="REQUIRES_NEW"
rollback-for="com.dummy.common.exception.DummyException" />
<tx:method name="*" propagation="REQUIRED"
rollback-for="com.dummy.common.exception.DummyException" />
</tx:attributes>
</tx:advice>
In Service impl, function for updating entity
public Offering selectiveUpdateInOwnTransaction(Map<String, String> offeringData) throws DummyException
{
// search data from DB
AbstractJpaEntity priceObj = selectEntityByCriteria(Price.class, paramMap);
// now "priceObj" contain requied data;
..
priceObj.setPublishedStatus(true);
// some businesslogic which is throwing exception <-- Point 1 : This is throwing exception
priceObj.setPrice(23);
..
updateEntity(priceObj);
}
Two function calling same above mentioned function "selectiveUpdateInOwnTransaction"
public boolean updateOffering(Offering offering) // In same Service Impl
public boolean updateOfferingInOwnTransaction(....) throws DummyException // In different Service Impl
In Both these function, call to "selectiveUpdateInOwnTransaction" is as follow:
try
{
selectiveUpdateInOwnTransaction(dataMap);
}
catch (DummyException e)
{
....
}
Issue:
Point 1 is throwing exception and "priceObj" should not be updated in DB, but when "selectiveUpdateInOwnTransaction" is called from "updateOffering", it get persisted in DB.
Also only contents that are persisted in DB are contents which are updated in object before exception throw.
Call from "updateOfferingInOwnTransaction" is showing no such error.
I am not able to understand why "updateOffering" is not working as per expectation.
A workaround
As quick fix, i did following changes in "selectiveUpdateInOwnTransaction", and after that, it worked fine (entity not persisted in DB on exception throw, as expected):
Price priceObj1 = new Price();
BeanUtils.copyProperties(priceObj, priceObj1);
updateEntity(priceObj1);
But in this also, I do not understand, why this is working ?
Other configuration details
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.dummy.offering.db.service..*Service.*(..)) || execution(* com.dummy.common.db.service..*Service.*(..))" />
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
</aop:config>
If you rely on name="*InOwnTransaction" propagation="REQUIRES_NEW" to be working for the method call from updateOffering then this won't happen. You make an internal call (self-invocation) for a proxied class: the internal call to selectiveUpdateInOwnTransaction from updateOffering will be a call to a regular (non-proxied) method.
I strongly suggest to read carefully this section of the documentation.
To directly apply what you have in your code with the sample in the documentation: SimplePojo is your ServiceImpl, foo() is your updateOffering and bar() is your selectiveUpdateInOwnTransaction. Think about a proxy as an entirely new class that intercepts calls to your own methods and classes.
So, basically, when you call updateOffering from your controller you are calling updateOffering on a different class (which is not ServiceImpl) instance.
This new class applies the transactional behavior (starting a new transaction, associating transactional resources with the current thread etc) and then calls the real updateOffering from your own ServiceImpl.
updateOffering then calls selectiveUpdateInOwnTransaction, but since this call is like this.selectiveUpdateInOwnTransaction then the call would be on your ServiceImpl, not the newly created class that acts as a proxy. Because of this, Spring treats your selectiveUpdateInOwnTransaction as a regular, nothing special method.
On the other hand, if selectiveUpdateInOwnTransaction is called from anther class, that another class will call that method on the proxy, and this is why it works if you call it from a different ServiceImpl.
In that section of the documentation, there is an ugly solution to this restriction
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
but the real acceptable approach would be to redesign your classes a bit: move updateOffering to another class.
I'm trying to configure Spring so that it executes advice when a specific exception subclass (MyTestException) is thrown:
public class MyTestExceptionInterceptor implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception exc) {
// I want this to get executed every time a MyTestException is thrown,
// regardless of the package/class/method that is throwing it.
}
}
And the XML config:
<bean name="interceptor" class="org.me.myproject.MyTestExceptionInterceptor"/>
<aop:config>
<aop:advisor advice-ref="interceptor" pointcut="execution(???)"/>
</aop:config>
I have a feeling that I should be using the target pointcut specifier (instead of execution) since - according to the Spring docs - it seems as though target allows me to specify the type of exception to match against, but I'm not sure if that's wrong, or what my pointcut attribute needs to look like.
I would greatly prefer to keep the AOP config done in XML (as opposed to Java/annotations, but I could probably translate an annotation-based solution into XML if need be.
I'd use an <aop:after-throwing> element and its throwing attribute.
Spring config
<bean name="tc" class="foo.bar.ThrowingClass"/>
<bean name="logex" class="foo.bar.LogException"/>
<aop:config>
<aop:aspect id="afterThrowingExample" ref="logex">
<aop:after-throwing method="logIt" throwing="ex"
pointcut="execution(* foo.bar.*.foo(..))"/>
</aop:aspect>
</aop:config>
The throwing attribute is the parameter name of the aspect's handler method (here it's LogException.logIt) that gets called on the exception:
Aspect
public class LogException {
public void logIt(AnException ex) {
System.out.println("*** " + ex.getMessage());
}
}
The XML and method combo defines the exception type that the aspect applies to. In this example, ThrowingClass throws AnException and AnotherException. Only AnException will have the advice applied because of the advice's method signature.
See example project on github for full source.
Check out a AfterThrowingAdvice. An example is found here (search for "After throwing advice") and you'll find it.
I have the following setup:
#Component
public class ImplOne implements IFace{
}
#Component
public class ImplTwo implements IFace{
}
public interface IFace{
}
I am trying to get a reference of ImplOne by type:
#RunWith(SpringJUnit4ClassRunner.class)
public class ImplOneTest {
#Autowired
private ImplOne impl;
#Test
public void test(){
Assert.assertNotNull(impl);
}
}
Though with this I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [some.package.TestBean] 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)}
I tried the following workarounds:
Remove "implements IFace" from ImplOne so the implementation class itself gets Proxied by cglib. Not acceptable because I also need to be able to get all implementations of IFace in my application code.
Doing method injection via a #Autowired public void setImplOne(IFace[] beans) and filtering the instance through instanceof check does not work, because the injected beans are subclasses of type java.lang.reflect.Proxy which doesn't offer any useful methods.
Changing #Component of ImplOne to #Component("implone") and using #Qualifier("implone").
Code:
#RunWith(SpringJUnit4ClassRunner.class)
public class ImplOneTest {
#Autowired
#Qualifier("implone")
private ImplOne impl;
#Test
public void test(){
Assert.assertNotNull(impl);
}
}
But I don't like the idea of having to name my beans just to be able to inject the concrete implementation.
Is there some way to do this elegantly, or atleast in some manner that only affects my test code? Also is there some special reason why my first example is unsupported?
Check if the exception is about the beans you think it is. Because the names don't match
Even if 1 is fixed, it is preferable to autowire by interface, not by concrete implementation. Most often (I can' know if this is true in your case), concrete implementations are proxied by spring (for transaction support, for example), and can be injected by interface only. And since you have two implementations of one interface, you have to provide a name, and either use #Autowired + #Qualifier, or use #Resource(name="") to inject what you want. And there is nothing wrong with this.
Ok, today i found a way to make this work afterall. Seems like the Spring-AOP-Autoproxy was to blame for this not to work.
Currently I am using AJDT in Eclipse for compile time weaving (CTW) and the TransactionAnnotationAspect. I also removed the aspectjweaver and cglib dependency in my project, so autoproxy is not even supported anymore, after removing the following config part from applicationcontext:
<aop:pointcut id="serviceOperation" expression="execution(* some.package..*(..)) && #target(org.springframework.stereotype.Service)" />
<aop:advisor pointcut-ref="serviceOperation" advice-ref="serviceTxAdvice" />
</aop:config>
<tx:advice id="serviceTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" read-only="true" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
And that was also the reason why #Configurable didn't work for me...
Adding the following line worked for me:
<aop:aspectj-autoproxy proxy-target-class="true"/>