Probably a duplicate question of experts.hybris
We are using promotion module(deprecated one). OOTB if you have a product restriction and you have mix cart(having allowed and restricted products) then promotion(Say: order threshold promotion) will apply(calculate) on whole cart total. Ideally, restricted products price should be excluded from cart total to trigger promotion and this is what I want to achieve.
To do so I'm trying to override getOrderSubtotalAfterDiscounts
using Spring AOP and its also getting called. But there, I need to get current promotion class instance (OrderPromotion) to call evaluateRestrictions
of PromotionsManager
. But it always getting null using (OrderPromotion) pjp.getTarget()
Aspects:
package com.myproject.aop;
@Aspect
public class AbstractOrderAOP
{
private static final Logger LOG = Logger.getLogger(AbstractOrderAOP.class);
@Pointcut("execution(public * *..OrderThresholdDiscountPercentagePromotion.evaluate(..)) && target(orderPromotion)")
public void evaluatePointcut(OrderPromotion orderPromotion)
{
//
}
@Pointcut("execution(protected * de.hybris.platform.promotions.jalo.OrderPromotion.getOrderSubtotalAfterDiscounts(..)) && args(ctx, order)")
public void subtotalPointcut(SessionContext ctx, AbstractOrder order)
{
//
}
@SuppressWarnings("boxing")
@Around("evaluatePointcut(orderPromotion) && cflow(subtotalPointcut(ctx, order))")
public Object getOrderSubtotalAfterDiscounts(ProceedingJoinPoint pjp, OrderPromotion orderPromotion, SessionContext ctx,
AbstractOrder order)
{
LOG.info("here you go ....");
return 0l;
}
}
aop.xml
<aspectj>
<weaver options="-Xset:weaveJavaxPackages=true">
<include within="de.hybris.platform.promotions.jalo.OrderPromotion"/>
<include within="de.hybris.platform.b2bacceleratorservices.jalo.promotions.OrderThresholdDiscountPercentagePromotion"/>
<include within="com.myproject.extended.interceptor.*"/>
</weaver>
<aspects>
<aspect name="com.myproject.aop.AbstractOrderAOP"/>
</aspects>
</aspectj>
Any help or suggestions would be appreciated!!
Your aspect does not import de.hybris.platform.promotions.jalo.OrderPromotion
and is not in the same package. So I really wonder why it should even compile with the cast to OrderPromotion
you are trying to use.
If you do have the import in your aspect and just erased it before copying it into your SO question, I see no reason why pjp.getTarget()
should yield null
, with one exception: If the method is static, then of course it would not have a target object to be called upon because there is not object instance. In this case your aspect cannot work and you need to intercept another pointcut.
As Hybris does not seem to have any public JavaDoc on the web and I have never used it and thus no access to it, I cannot say for sure, I have to speculate.
Update: Okay, I am back from my trip and have a little time to answer. Basically the idea is to get
In order to achieve that you use the cflow()
pointcut by which you can express that the static method's execution should be captured if it is in the control flow (i.e. directly or indirectly called by) the instance method which gets you the target object. You should
args()
and target()
in order to bind the captured values directly to pointcut parameters@Aspect
public class AbstractOrderAOP {
// (...)
@Pointcut(
"execution(public * *..OrderThresholdDiscountPercentagePromotion.evaluate(..)) && " +
"target(orderPromotion)"
)
public void evaluatePointcut(OrderPromotion orderPromotion) {}
@Pointcut(
"execution(protected * *..OrderPromotion.getOrderSubtotalAfterDiscounts(..)) && " +
"args(ctx, order)"
)
public void subtotalPointcut(SessionContext ctx, AbstractOrder order) {}
@Around("cflow(evaluatePointcut(orderPromotion)) && subtotalPointcut(ctx, order)")
public Object getOrderSubtotalAfterDiscounts(
ProceedingJoinPoint pjp,
OrderPromotion orderPromotion,
SessionContext ctx,
AbstractOrder order
) {
LOG.info("############ AbstractOrderAOP is being evaluated ############");
try {
final Object output = pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
ArrayList products = new ArrayList();
// (...)
return 0l;
}
// (...)
}
See? No more ugly getTarget()
or getArgs()[0]
, but perfectly typesafe parameter binding.
BTW, you do not need to abbreviate the package names to *..
like I did. I just wanted to make it a bit more readable for you and other people around here.
This works and I have tested that it does by replicating all your dozen or so classed as dummies (too much code to post here).