Why is the interceptor not called in the same service class? - java

I want to use interceptors in a Java-SE application and I am using weld as CDI implementation and i'm testing this here:
The Main-Class:
public static void main(String[] args) {
WeldContainer weldContainer = new Weld().initialize();
Service service = weldContainer.instance().select(Service.class).get();
service.methodCall();
service.methodCallNumberTwo();
}
The Service-Class:
public class Service {
#TestAnnotation
public void methodCall(){
System.out.println("methodCall...!");
methodCallNumberTwo();
}
#TestAnnotation
public void methodCallNumberTwo(){
System.out.println("methodCallNumberTwo...!");
}
}
The Interceptor-Class:
#Interceptor
#TestAnnotation
public class TestInterceptor {
#AroundInvoke
public Object interceptorMethod(InvocationContext invocationContext) throws Exception {
System.out.println("I'm the TestInterceptor of "+invocationContext.getMethod());
return invocationContext.proceed();
}
}
Aaaand the output:
I'm the TestInterceptor of public void Service.methodCall()
methodCall...!
methodCallNumberTwo...!
I'm the TestInterceptor of public void Service.methodCallNumberTwo()
methodCallNumberTwo...!
My Questions
First: Why isn't the interceptor called in methodCall() when i'm calling methodCallNumberTwo()?
Second: Is there a way to change that?
I'm only studying the behavior of interceptors and want to understand. Thank you in advance!

The interceptor is not called because you are calling it on the same instance of the object. If you're familiar with EJBs it's the same as calling a method on the same object instead of through the EJB context.
If you debug through it you'll notic that the method call on the injected objects goes through a proxy. The method call from methodOne to methodTwo isn't proxied.

Related

Spring bean with #Async method, why singleton bean‘s inner hashcode is different from outside

I'm very confused with the the different behaviors in spring bean with async mehtod. i have a Demo Bean with an #Async method that just print this.hashCode(). and a Main class that injected by Demo. The Demo bean'scope is singleton. but in fact, in Main class, the demo.hashcode() is not equal to this.hashCode() in the method test() of Demo class. why? they are not the same instance?
#Component
public class Demo {
#Async
public void test(){
System.out.println(this.hashCode());
}
}
#Component
public class Main implements CommandLineRunner {
#Autowired
Demo demo;
#Override
public void run(String... args) throws Exception {
System.out.println(demo.hashcode());
demo.test();
}
}
In Main you are calling the hashCode() method on the proxy object. To support #Async Spring places the concrete object inside a proxy to wrap the #Async logic around the concrete method call. Therefore you get the hashCode value of the proxy.
When invoking demo.hashCode() you are returning the hashCode() of the concrete object and not the proxy anymore. Therefore they differ.

Spring AOP expression executed but it shouldn't

I am newbie in Spring and trying to understand AOP. Here's what I got
I have one simple aspect, which I want to run when any non-getter method gets called
#Aspect
#Component
public class LoggingAspect {
#Pointcut("execution(* org.practice.entity.Person.get*())")
private void getter() {}
#Before("!getter()")
public void noGetter() {
System.out.println("NO GETTER GETS CALLED");
}
}
Person class is simply
#Component
public class Person {
public void getPerson() {
System.out.println("GETTING PERSON....");
}
}
I am initializing the config using Java annotations
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("org.practice")
public class DemoConfig {}
And then in my main method i have
public class MyApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
context.close();
}
}
As you can see I am simply creating a context and closing it and not calling any getter or non-getter method. When I run the program, I got the following console output
NO GETTER GETS CALLED....
This makes semi-sense as I am not calling any getter method, but I expected this aspect to execute only if I am explicitly calling any non-getter not by just opening the context. Please let me know if I want my business logic to execute only if any non-getter method gets invoked then how would I do it?
Thanks
Try this:
#Pointcut("execution(* org.practice.entity.Person.*())")
private void methodCall() {}
#Before("!getter() && methodCall")
public void noGetter() {
System.out.println("NO GETTER GETS CALLED");
}
I think its happening during the initializing of Person bean at the time od application context loading
Since you have given joinpoint as not of getter so at the time of default construction execution (provided by compiler) the advice is getting triggered

How can I inject member annotations into my current instantiated object using Guice?

I am trying to inject a custom annotation using the Guice bindInterceptor into my currently instantiated Service.java class. Unfortunately when I call myMethod() the OnAnnotationEvent::invoke method is not called. How can I use Guice to call OnAnnotationEvent::invoke when the #OnAnnotation annotation tag is used on a method in the current class?
My code looks like this:
Service.java
//Instantiated by another service
public class Service extends AbstractVerticle {
private DataAccess dataAccess;
#Inject
public void setDataAccess(DataAccess dataAccess){
this.dataAccess = dataAccess;
}
#Override
public void start() throws Exception {
Guice.createInjector(new DataAccessModule()).injectMembers(this);
myMethod();
}
#MyAnnotation
public void myMethod() {
dataAccess.doStuff();
}
}
DataAccessModule.java
public class DataAccessModule extends AbstractModule {
#Override
protected void configure() {
OnAnnotationEvent onAnnotationEvent = new OnAnnotationEvent();
bindInterceptor(Matchers.any(), Matchers.annotatedWith(MyAnnotation.class), onAnnotationEvent);
bind(DataAcess.class).to(DataAccessImpl.class);
}
}
OnAnnotationEvent
public class OnAnnotationEvent implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Annotation called on: " + invocation.getMethod().getName();
return invocation.proceed();
}
}
MyAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {}
I think that your problem is that you creating new injector that does not knows anything about your class. If you just need injector in your class - use #Inject private Injector injector;. If you need to load some aditional modules locally you just need to create child injector :
#Inject private baseInjector;
...
injector = baseInjector.createChildInjector(new Module1(),new Moddule2());
This doesn't work because your Service instance isn't managed by Guice. To make it work you must either create Service with Guice or annotate method doStuff in DataAccessImpl with MyAnnotation.

Mocking static method of the interface in Java

I got an interface with a static method in it. And I want to mock this method for unit tests.
Here's an example of such an interface:
public interface IClass {
static String create(String s) {
System.out.println("Method create is called");
return s;
}
}
I was trying to mock this method using PowerMockito:
#RunWith(PowerMockRunner.class)
#PrepareForTest(IClass.class)
public class IClassTest {
#Before
public void setUp() {
PowerMockito.mockStatic(IClass.class);
ClassImpl cl = mock(ClassImpl.class);
Mockito.when(IClass.create(any())).thenReturn(cl);
}
#Test
public void mockInterfaceClassTest() {
System.out.println(IClass.create("Test"));
}
}
Unfortunately, the mocking is not being done and even more, as soon as in my setUp() method I'm trying to setup mock: Mockito.when(IClass.create(any())).thenReturn(cl); actually, the method is being called (I got message in console "Method create is called"), which is undesired for sure.
Is there any possibility to mock static method inside interface?

Guice Provider Interception

I need to access to an instance provided via Guice #Provides, so i'm testing a way to access the #Provides Method via a Interceptor...but no way, the interceptor never distpaches.
Also i can't change Provider Method Signature , cause inherits from another class ....
public class MyModule extends AbstractModule{
public static class MyInterceptor implements MethodInterceptor{
#Override
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
System.out.println("MyModule ::: Intercepted#invoke! : "+ methodInvocation.getMethod().getName());
return methodInvocation.proceed();
}
}
#Provides
StampInterface getStamp(){
StampExampleImpl se = new StampExampleImpl();
se.setId("theID");
se.setTst(System.currentTimeMillis());
return se;
}
#Override
protected void configure() {
bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Provides.class),
new MyInterceptor());
}
public static void main(String... args) {
StampInterface s = Guice.createInjector(new MyModule()).getInstance(StampInterface.class);
System.out.println( s.getTst());
System.out.println("---------------------------");
}
}
Please check the limitations of guice aop as described here: https://github.com/google/guice/wiki/AOP#limitations
Instances must be created by Guice by an #Inject-annotated or no-argument constructor It is not possible to use method interception on instances that aren't constructed by Guice.
You are creating the StampExampleImpl yourself via "new" (doesn't matter that you do so inside a produces method). Thus guice does not know about it in regard to interception.
Quick fix: let guice create the impl instance for you:
#Provides
StampInterface getStamp(StampExampleImpl se){
se.setId("theID");
se.setTst(System.currentTimeMillis());
return se;
}
2nd Problem: why matching on "annotatedWith(Provides)"? You want to intercept the getTsd() method of your StampInterface, and that is not annotated. The annotation is on the producer method of your module, which is a different thing.

Categories