Conditional matching in Google Guice - java

I have a MethodInterceptor bound to methods in a class in order to do some simple logic before on the data before the class gets to touch it.
However, teh class itself makes calls to some of its own intercepted methods, but at that point I don't need to re-run that logic anymore.
public class MyModule extends AbstractModule {
#Override
public void configure() {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(MyAnnotation.class), new MyInterceptor());
}
}
public class MyInterceptor implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// logic
}
}
public MyClass {
#MyAnnotation
void foo() {
bar();
}
#MyAnnotation
void bar() {
}
}
Is there a way for the call for bar within foo to not be itnercepted?

To be honest, the easiest solution is to simply avoid the problem by never calling another public/annotated method of the same class from within the class:
public class MyClass {
#MyAnnotation
public void foo() {
doBar();
}
#MyAnnotation
public void bar() {
doBar();
}
private void doBar() {
//doesn't go through interceptor
}
}
If for some reason that's not an option, then you might look at this approach. More expressive AOP libraries like AspectJ give you a greater level of flexibility for defining a pointcut.
In Guice, the pointcut is simply a method with an annotation belonging to an instance instantiated by Guice. So this logic has to be moved to the interceptor itself.
One approach for doing so might be to use a ThreadLocal to track entries into the interceptor. Extending something like this might be a start:
public abstract class NonReentrantMethodInterceptor implements MethodInterceptor {
private final ThreadLocal<Deque<Object>> callStack = new ThreadLocal<>();
#Override
public final Object invoke(MethodInvocation invocation) throws Throwable {
Deque<Object> callStack = this.callStack.get();
if (callStack == null) {
callStack = new LinkedList<>();
this.callStack.set(callStack);
}
try {
return invokeIfNotReentrant(callStack, invocation);
} finally {
if (callStack.isEmpty()) {
this.callStack.remove();
}
}
}
private final Object invokeIfNotReentrant(Deque<Object> callStack, MethodInvocation invocation) throws Throwable {
Object target = invocation.getThis();
if (callStack.isEmpty() || callStack.peek() != target) {
//not being called on the same object as the last call
callStack.push(target);
try {
return doInvoke(invocation);
} finally {
callStack.pop();
}
} else {
return invocation.proceed();
}
}
protected abstract Object doInvoke(MethodInvocation invocation) throws Throwable;
}
This uses a thread local stack to track the stack of calls into the interceptor. When the last call into this interceptor targeted the same object, it calls proceed() and bypasses the interceptor. When this is the first call into the interceptor, or if the last call was not targeting the same object, it applies the interceptor.
Then the actual logic you would want to apply when the interceptor is active would go into doInvoke().
Example usage:
public class NonReentrantTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module());
MyClass instance = injector.getInstance(MyClass.class);
instance.foo();
}
static class Module extends AbstractModule {
#Override
protected void configure() {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(PrintsFirstInvocation.class),
new PrintsFirstInvocationInterceptor());
}
}
public static class MyClass {
#PrintsFirstInvocation
void foo() {
bar();
}
#PrintsFirstInvocation
void bar() {
}
}
public static class PrintsFirstInvocationInterceptor extends NonReentrantMethodInterceptor {
#Override
protected Object doInvoke(MethodInvocation invocation) throws Throwable {
System.out.println(invocation.getMethod());
return invocation.proceed();
}
}
#BindingAnnotation
#Target({FIELD, PARAMETER, METHOD})
#Retention(RUNTIME)
public #interface PrintsFirstInvocation {
}
}

Related

JUnit 5 TestTemplates and Extensions: Accessing TestTemplateInvocationContext?

Use case:
A test shall be executed with different parameters.
For this test we want to use an extension doing some pre-/postprocessing. This step needs access to the current set parameter.
Initially I tried implementing this with a #ParameterizedTest. Here the extension has no chance to access the parameter (The parameter is evaluated after the beforeTestExecution call). As a matter of this I used #TemplateTest with TestTemplateInvocationContextProvider (as described in the guide). Now I could see my parameters in the extensionContext. Unfortunately there are accessor methods missing for that:
on MethodExtensionContext (resp. super class): getTestDescriptor() : TestTemplateInvocationTestDescriptor
on TestTemplateInvocationTestDescriptor: getInvocationContext()
As a hopefully temporary workaround I do some reflection to access my invocationContext.
Is there something that tells against introducing these accessor methods? Is there even a better / simpler way for doing this?
I think you can provide additional Extensions in the TestTemplateInvocationContext. The following is based on the example in the user guide:
#TestTemplate
#ExtendWith(MyTestTemplateInvocationContextProvider.class)
void testTemplate(String parameter) {
System.out.println("Test with parameter: " + parameter);
assertEquals(3, parameter.length());
}
static class MyTestTemplateInvocationContextProvider implements TestTemplateInvocationContextProvider {
#Override
public boolean supportsTestTemplate(ExtensionContext context) {
return true;
}
#Override
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
return Stream.of(invocationContext("foo"), invocationContext("bar"));
}
private TestTemplateInvocationContext invocationContext(String parameter) {
return new TestTemplateInvocationContext() {
#Override
public String getDisplayName(int invocationIndex) {
return parameter;
}
#Override
public List<Extension> getAdditionalExtensions() {
return Arrays.asList(parameterResolver(), preProcessor(), postProcessor());
}
private BeforeTestExecutionCallback preProcessor() {
return new BeforeTestExecutionCallback() {
#Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
System.out.println("Pre-process parameter: " + parameter);
}
};
}
private AfterTestExecutionCallback postProcessor() {
return new AfterTestExecutionCallback() {
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
System.out.println("Post-process parameter: " + parameter);
}
};
}
private ParameterResolver parameterResolver() {
return new ParameterResolver() {
#Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter()
.getType()
.equals(String.class);
}
#Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameter;
}
};
}
};
}
}
The console output is:
Pre-process parameter: foo
Test with parameter: foo
Post-process parameter: foo
Pre-process parameter: bar
Test with parameter: bar
Post-process parameter: bar
This would mean that I have to one extension to the other. Currently I have two extensions: One (MyProvider) implementing TestTemplateInvocationContextProvider (used for test parametrization) and one (MyCallback) implementing BeforeTestExecutionCallback for doing some preparation work.
This looks like:
#ExtendWith(MyCallback.class)
public class WebTest {
#TestTemplate
#ExtendWith(MyProvider.class)
public void showPage() throws Exception {
}
}
My goal would be getting the current parameter in the class level extension:
public class MyCallback implements BeforeAllCallback, BeforeTestExecutionCallback {
public void beforeAll(ExtensionContext ctx) {
}
public void beforeTestExecution(ExtensionContext ctx) {
// HERE I WANT CURRENT PARAMETER VALUE:
((TestTemplateInvocationTestDescriptor) ((MethodExtensionContext) ctx).testDescriptor).invocationContext;
}
If I had two public methods added (as mentioned in first edit) it would be possible but maybe it is against the concept?

How to modify/decorator an object returned from 3rd party API using javassist/CGLib

I have an 3rd party API call which returns the following object:
public class A {
protected void common() {
System.out.println("common is called in A");
}
public void test1() {
common();
System.out.println("test1 is called in A");
}
public void test2() {
common();
System.out.println("test2 is called in A");
}
}
But I'd like to modify its behavior like the following ModifiedA shows:
public class ModifiedA extends A {
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
So what I am trying to do is:
A a = 3rdPartyAPI_call();
//
// Now I'd like to get a ModifiedA which has changed common() behavior.
//
How to use javassist/CGLIB to accomplish this ?
One easy way may be to like this:
public class ModifiedA extends A {
private A a;
public ModifiedA(final A a) {
this.a = a;
}
//
// Override every public method in A
//
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
But since A's definition comes from 3rd party and is very complex and may change, so I'd like to use a proxy to do this?
Thanks for your comments in adavance.
You can use CGLib to implement a delegator pattern without having to override all the methods. There are a few different approaches to implement this depending on style but here is one similar to your example.
You can wrap the instance using a cglib Enhancer:
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallback(new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object returnValue = proxy.invoke(original, args);
if (method.getName().equals("common")) {
System.out.println("common is called");
}
return returnValue;
}
});
return (T) enhancer.create();
}
eclps post will fullfill your requirement and it works.I want to add some more code to eclps code.
Adding filter which give index zero for common method and rest all method to One. MethodInterceptor callback will intercept only common method and rest all method use NoOp intercetor(which will call super class apis).This way filtering is not happening for every method call.
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallbackFilter(new CallbackFilter() {
#Override
public int accept(Method method) {
if (method.getName().equals("common")) {
return 0;
}
return 1;
}
});
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// only common method will intercept this call back.
return proxy.invoke(this, args);
}
}, NoOp.INSTANCE});
return (T) enhancer.create();
}

Run code only on test

I would like to execute a method only on test running.
This is a completion of integration test. When I run integration test, I want to generate a json file with the state of an Object.
I think of doing something like this in my code :
if(environnement == TEST) {
// save object as json
}
Do you know other method to do this ? less crapy ?
Regards
I generally provide test 'hooks' using this pattern
public class MyObject {
public void doStuff() {
// stuff to do
onCompleteStuff();
}
protected void onCompleteStuff() {
}
}
Then in the test code you can create a subclass of MyObject that does your test-only actions:
private MyObject newMyObject() {
return new MyObject() {
#Override
protected void onCompleteStuff() {
saveObjectAsJson();
}
};
}
This has the advantage of keeping test code out of your main build. It will also work if you must use a mock in your tests. For example, using the excellent Mockito library:
MyObject foo=Mockito.spy(new MyObject());
doAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
saveObjectToJson();
return null;
}
}).when(foo).onCompleteStuff();
How about using the Polymorphism OOP feature?
abstract class MyObject {
void doSomething();
}
class MyObjectImpl {
void doSomething() {
// real implementation
}
}
class MyObjectTest {
void doSomething() {
// create your json or other test functional
}
}
class MyObjectFactory {
static getMyObject(Environment env) {
if (env == Environment.TEST) {
return new MyObjectTest();
} else {
return new MyObjectImpl();
}
}
}

Sad logic on types

Code base is littered with code like this:
BaseRecord record = // some BaseRecord
switch(record.source()) {
case FOO:
return process((FooRecord)record);
case BAR:
return process((BarRecord)record);
case QUUX:
return process((QuuxRecord)record);
.
. // ~25 more cases
.
}
and then
private SomeClass process(BarRecord record) { }
private SomeClass process(FooRecord record) { }
private SomeClass process(QuuxRecord record) { }
It makes me terribly sad. Then, every time a new class is derived from BaseRecord, we have to chase all over our code base updating these case statements and adding new process methods. This kind of logic is repeated everywhere, I think too many to add a method for each and override in the classes. How can I improve this?
First solution: good old polymorphism.
Simply add an abstract process() method to the BaseRecord class, and override it in every subclass. The code will thus become:
BaseRecord record = ...;
record.process();
If you can't add the process() method into the BaseRecord class (and its subclasses), then implement the visitor pattern. It will leave the process method outside of the BaseRecord class, but each time you add a new subclass, you'll be forced to modify the Visitor interface, and all its implementations. The compiler will thus check for you that you haven't forgotten a case somwhere in a switch.
public interface RecordVisitor<T> {
T visitFoo(FooRecord foo);
T visitBar(BarRecord foo);
...
}
public abstract class BaseRecord {
public abstract <T> T accept(RecordVisitor<T> visitor);
}
public class FooRecord extends BaseRecord {
#Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitFoo(this);
}
}
public class BarRecord extends BaseRecord {
#Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitBar(this);
}
}
Now you simply have to implement RecordVisitor for each block of logic described in the question:
RecordVisitor<Void> visitor = new ProcessRecordVisitor();
record.accept(visitor);
Both Visitor Pattern and Strategy pattern can be put in use here. http://en.wikipedia.org/wiki/Strategy_pattern and http://en.wikipedia.org/wiki/Visitor_pattern
I think this is instructive:
package classplay;
public class ClassPlay
{
public void say(String msg) { System.out.println(msg); }
public static void main(String[] args)
{
ClassPlay cp = new ClassPlay();
cp.go();
}
public void go()
{
A someClass = new C();
say("calling process with double dispatch");
someClass.dueProcess(this);
say("now calling process directly");
process(someClass);
}
public void process(A a)
{
say("processing A");
a.id();
}
public void process(B b)
{
say("processing B");
b.id();
}
public void process(C c)
{
say("processing C");
c.id();
}
abstract class A
{
abstract public void id(); // { System.out.println("Class A"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
class B extends A
{
public void id() { System.out.println("Class B"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
class C extends A
{
public void id() { System.out.println("class C"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
}

Fire event with subclass runtime type

I want to fire an event in CDI whose type I can only determine on runtime. For instance, let's say there's some interface A with implementing classes AA and AB. I have two observers:
public void observeAA(#Observes AA aa) {
}
public void observeAA(#Observes AB ab) {
}
Then some event producer:
#Inject #Any
private Event<A> event;
public A getPayload();
public void fire() {
this.event.fire(getPayload());
}
This doesn't work because A is neither a subtype of AA or AB (it's the other way around). I've noticed there's a select method that takes a subtype:
public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers);
However, it requires a correctly parameterized Class object, which (correct if I'm wrong), I can't build at runtime.
Is there any solution or will I have to use qualifiers (possibly an annotation with a Class<?> method)?
I ended up using a qualifier with a Class<?> member.
#Qualifier
#Target({TYPE, METHOD, PARAMETER, FIELD})
#Retention(RUNTIME)
public #interface EventType {
Class<?> value();
}
public class Dispatcher {
#Inject #Any
private Event<A> event;
public void fireEvent(A a) {
this.event.select(
getTypeAnnotation(
a.getClass())).fire(a);
}
public static EventType getTypeAnnotation(
final Class<?> type) {
return (EventType) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[]{EventType.class},
new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.equals(
EventType.class.getMethod("value"))) {
return type;
} else if (method.equals(Annotation.class.getMethod(
"annotationType"))) {
return EventType.class;
} else if (method.getName().equals("hashCode")) {
return 127 * "value".hashCode() ^ type.hashCode();
} else if (method.getName().equals("equals")) {
return (args[0] instanceof EventType &&
((EventType)args[0]).value()
.equals(type));
}
return null;
}
});
}
}
public class X {
public void observeA(
#Observes #EventType(AA.class) A a) {
...
EDIT
This is a simpler way of instantiating the annotation:
public abstract static class ConfigTypeAnnotation
extends AnnotationLiteral<ConfigType>
implements ConfigType { }
public static ConfigType getConfigTypeAnnotation(final Class<?> type) {
return new ConfigTypeAnnotation() {
#Override
public Class<?> value() {
return type;
}
};
}
Why don't you use
public void observeA(#Observes A a) {
}
in which you decide what to do according to "a" implementation class ?
public void observeA(#Observes A a) {
if (a instanceof AA)
{
...
}
else
...
}
I had a similar requirement and ended up injecting BeanManager to fire the event.

Categories

Resources