Simple After And Before Method Interceptor With Byte Buddy - java

In Byte Buddy tutorial at the time of this writing, everything is explained but a simple after and before method interceptor is not there as I explained below, am I missing something or tutorial is complex. (See LoggerInterceptor example gives method but not object, ChangingLoggerInterceptor example gives object but not invoked method)
What I wanted to achieve is to call a method of an object after its setter method executions. How can I write an interceptor and use it in Java 6?
public class DirtyClass{
private String _sField;
private boolean _bDirty;
public void setField(String sField) {
_sField = sField;
//setDirty(true); to be appended after proxying
}
public String getField() {
return _sField;
}
public void setDirty(boolean bDirty){
_bDirty = bDirty;
}
public boolean isDirty(){
return _bDirty;
}
}
DirtyClass d = new ByteBuddy().subclass(DirtyClass.class)...???
d.setField("dirty now");
System.out.println(d.isDirty()); //Expecting true

You can implement such a mechanism even without a method delegation as follows:
DirtyClass d = new ByteBuddy()
.subclass(DirtyClass.class)
.method(isSetter().and(not(named("setDirty"))))
.intercept(SuperMethodCall.INSTANCE.andThen(
MethodCall.invoke(DirtyClass.class.getMethod("setDirty", boolean.class))
.with(true)
)).make()
.load(DirtyClass.class.getClassLoader())
.getLoaded()
.newInstance();
This way, every setter is overridden to first invoke its super method and then to invoke the setDirty method with true as an argument. The linked example in the comments should however work as well.
An interceptor could look like the following (given that some interface Dirtiable is implemented):
public class Interceptor {
public static void getter(#SuperCall Runnable zuper, #This Dirtiable self) {
zuper.run();
self.setDirty(true);
}
}
This assumes that the instrumented super class implements the Dirtiable interface which can be done using .implement(Dirtiable.class) where the method can be implemented to set a field using the FieldAccessor implementation.

Related

Thinking in Java 4th Edition - is it necessary to make a factory for isolating the code from implementation?

I am currently reading "Thinking in Java 4th edition". In the Chapter "Interface" and the sub-chapter "Interfaces and factories", it states the following
An interface is intended to be a gateway to multiple implementations,
and a typical way to produce objects that fit the interface is the
Factory Method design pattern. Instead of calling a constructor
directly, you call a creation method on a factory object which
produces an implementation of the interface—this way, in theory, your
code is completely isolated from the implementation of the interface,
thus making it possible to transparently swap one implementation for
another. Here’s a demonstration showing the structure of the Factory
Method:
(for easy reference, the example codes quoted after my question)
My question is that why don't we just make the "serviceConsumer" method to be like
public static void serviceConsumer(Service s) {
s.method1();
s.method2();
}
In this case, the code depends on the interface "Service" but not the implementation. (It can also "swap" transparently, isn't it?). So, I don't really get to the point of using "factory" here and what it states at start.
-----------------------------below quoted from "Thinking in Java"------------------------------
//: interfaces/Factories.java
import static net.mindview.util.Print.*;
interface Service {
void method1();
void method2();
}
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service {
Implementation1() {} // Package access
public void method1() {
print("Implementation1 method1");
}
public void method2() {
print("Implementation1 method2");
}
}
class Implementation1Factory implements ServiceFactory {
public Service getService() {
return new Implementation1();
}
}
class Implementation2 implements Service {
Implementation2() {} // Package access
public void method1() {
print("Implementation2 method1");
}
public void method2() {
print("Implementation2 method2");
}
}
class Implementation2Factory implements ServiceFactory {
public Service getService() {
return new Implementation2();
}
}
public class Factories {
public static void serviceConsumer(ServiceFactory fact) {
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(new Implementation1Factory());
// Implementations are completely interchangeable:
serviceConsumer(new Implementation2Factory());
}
}
/* Output:
Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2
*/ //:~
Well nothing prevents you from writing such method, the quoted statement is about creation of the object itself.
In this case, the code depends on the interface "Service" but not the implementation
In both cases the code depends on the interface, the difference is, that in your implementation the Service is created outside the method serviceConsumer
Maybe it will be clearer if you see a real use of Factory Method. The TIJ example is without any context.
My favorite example is Collection.iterator(), where Collection is the ServiceFactory and Iterator is the Service. You can see the calls in the serviceConsumer() but think of the following:
Collection c = new ArrayList(); // ArrayList is a Factory for its iterator
Iterator i = c.iterator(); // getService()
if (i.hasNext()) { ...}
If serviceConsumer were a method to print the collection (instead of something without context), you could see how passing an ServiceFactory (ArrayList) is better than passing the Service (Iterator). There is more encapsulation using that (the details of the Service are hidden in the method).
Here are some UML diagrams to help understand the similarities:
Factory method pattern
TIJ Example
Collection.iterator()
Note: The pink classes are actually anonymous classes that implement the Iterator interface type that corresponds to the Collection. They're not normally classes a client will instantiate any other way (hidden).

How to mock an object created via Class.newInstance(className)?

I'm trying to add unit tests to some legacy code that has a String class name passed to it and that creates an object implementing a particular handler interface using Class.newInstance(String className). I can control the class name I'm passing, I can get a pointer to the new handler object (via a getHandler() call), and I would like to observe calls to it using Mockito.
My current solution is:
Create a new test class TestHandler that implements the interface.
Have that test class contain a Mockito mock object that also implements the interface.
Manually pass through all the interface methods to the mock object.
Make the mock object accessible via a getMock() method.
Observe the object by making verify() calls to objectUnderTest.getHandler().getMock().
This works, but feels a little inelegant, especially having to manually write all the pass-thru methods.
Is there a better solution?
Fundamentally, you're running into the same problems as trying to test a newly-created instance using new; the Class.newInstance (probably properly Class.forName(foo).newInstance()) doesn't hurt you, but doesn't help you either.
As a side note, your TestHandler sounds like a general purpose delegate implementation, which sounds pretty useful anyway (particularly if you ever need to write a Handler wrapper). If it is, you might want to promote it to be adjacent to your Handler in your production code tree.
Though I recognize that you mention legacy code, this becomes very easy if you are allowed to refactor to include a testing seam. (Ignoring reflective exceptions here for ease of explanation.)
public ReturnType yourMethodUnderTest(String className) {
return yourMethodUnderTest(Class.newInstance(className));
}
/** Package private for testing. */
public ReturnType yourMethodUnderTest(Handler handler) {
return yourMethodUnderTest(Class.newInstance(className));
}
You could also extract the object creation and replace it in your test:
/** Instance field, package-private to replace in tests. */
Function<String, Handler> instanceCreator =
( x -> (Handler) Class.forName(x).newInstance());
public ReturnType yourMethodUnderTest(String className) {
Handler handler = instanceCreator.apply(className);
// ...
}
You could even just extract it to a method and replace it in your test:
public ReturnType yourMethodUnderTest(String className) {
Handler handler = createHandler(className);
// ...
}
/** Package private for testing. */
Handler createHandler(String className) {
return Class.forName(className).newInstance();
}
#Test public void yourTest() {
// Manually replace createHandler. You could also use a Mockito spy here.
ObjectUnderTest objectUnderTest = new ObjectUnderTest() {
#Override Handler createHandler(String className) {
return mock(Handler.class);
}
}
// ...
}
Side note: Even though Mockito creates a named dynamic type, you almost certainly will not be able to hack it in and allow your code to create it by name. This is because the call to mock registers the instance within Mockito's internal state.
// BAD: Unlikely to work
#Test public void yourTest() {
objectUnderTest.methodUnderTest(
mock(Handler.class).getClass().getName());
// ...
}
Create a public method where you will place the logic to fetch the newInstance of the class
ClassA objectClassA=createNewInstance(className);
likewise,and
public ClassA createInstance(String className){
return (ClassA) (Class.forName(className)).newInstance();
}
Now suppose we were creating an instance of classA inside of ClassB
then in TestClass of B, we can simply mock this createInstance method
doReturn(mockClassA).when(mockClassB).createInstance(className);

Check is instance method is called from a constructor

I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}

Using methods from a subclass on an object that is an instance of the superclass

Let's say there's a class that I use extensively and is returned by a method.
CommonClass obj = getCommonObject();
Now I want to extend this class to create some utility method to avoid repeating myself.
public CommonClassPlus extends CommonClass {
public String dontRepeatYourself() {
// the reason I'm creating a subclass
}
}
Of course I would like to use my improved class for the method above, however, downcasting isn't allowed.
CommonClassPlus obj = getCommonObject();
//Cannot cast to CommonClassPlus
How can I use the method dontRepeatYourself() if I can only work with the object that is an instance of the superclass?
CommonClass and getCommonObject() are from an external library and I cannot change them.
You cannot add behavior to an existing instance in Java (like you could in JavaScript, for example).
The closest you can get in Java is the Decorator pattern:
CommonClassPlus obj = decorate(getCommonObject());
where decorate() is
public CommonClassPlus decorate(CommonClass x) {
return new CommonClassPlus(x);
}
This approach creates a potentially huge amount of boilerplate because it must delegate each method call to the wrapped instance. If a method in CommonClass is final and there is no interface you can reimplement, then this approach fails altogether.
In most cases you will be able to get along with a simple static helper method:
public static String dontRepeatYourself(CommonClass x) {
...
}
If CommonClass is from an external library, you probably want to wrap it in an Adapter Pattern anyway, using the principle of Composition over Inheritance.
This gives you complete control if you want to, say, change the library you're using, and allows you to add functionality like dontRepeatYourself().
public class CommonClassAdapter implements MyAdapter {
private final CommonClass common;
private final String cachedResult;
// Note that I'm doing dependency injection here
public CommonClassAdapter(CommonClass common) {
this.common = common;
// Don't expose these because they shouldn't be called more than once
common.methodIOnlyCallOnce();
cachedResult = common.anotherMethodIOnlyCallOnce();
}
#Override
public void someMethod() {
common.someMethodWithDifferentName();
}
#Override
public String dontRepeatYourself() {
return cachedResult;
}
}
Note also that most modern IDEs have things like Eclipse's Source -> Generate Delegate Methods to make this process faster.

#Override on method in subclass "appears" ignored at runtime

I really hope I am just missing something simple, but I am reading the following: http://docs.oracle.com/javase/tutorial/java/IandI/override.html .
I have two classes and one interface. Literally the "use case" shown in this Oracle documentation page. However, when I run a JUnit test - only the method in the superclass gets called and that method has the simple default that I don't want called:
The interface contains this method signature:
public interface RecordServiceInterface {
List<String> searchRecords(String id) throws ServiceException;
}
The superclass which implements the interface contains this method with a default - Eclipse IDE inserts this when it finds a missing method not implemented by the implementing class.
public class RecordService implements RecordServiceInterface {
public List<String> searchRecords(String id) throws ServiceException {
// TODO Auto-generated method stub
return null;
}
}
At runtime, only the above is called as I step through the debugger... every time.
The subclass then extends the superclass and has the real implementation that one wants to override:
public class MyRecordService extends RecordService {
#Override
public List<String> searchRecords(String id) throws ServiceException {
List<String> myList = new ArrayList<String>();
// ...
return myList;
}
}
I must be completely missing the point of #Override. During execution, it repeatedly fails to ever get into the method with the #Override annotation.
All that the #Override annotation does is make the compiler generate an error if there is no corresponding method anywhere in the class inheritance that could be overridden. So it is meant to make sure that your overridden method actually overrides something.
If your method from MyRecordService is not called, but the one from the RecordService class, then I would guess that the wrong object is instanciated. So what you have in front of you is an object of type RecordService, not of type MyRecordService.
Since you have not provided that part of the code, this is just a guess, based on the fact that your inheritance looks fine.
#Override is a compile-time annotation and is used to verify that the annotated method actually overrides something from a superclass / interface. It does not influence runtime behavior.
Post the code for your test so we can get a clearer idea of what you're trying to do.
As you can see in #Override's javadoc, the retention policy of #Override is SOURCE. In other words: it used in compile time but does not make it to the generated binary code (class file).
In particular, the SOURCE retention policy is defined as:
Annotations are to be discarded by the compiler.
#Override is effectively just a way to catch typos when attempting to override a super class' or instance's method, as well as the occasional attempt to override final methods (by design not overridable).
The act of overriding enables a fall-thru approach to overriding method when given a choice of what to call.
For example:
RecordServiceInterface service = new RecordService();
RecordService service2 = new RecordService();
With both service and service2, the implementation from RecordService will be called. Now consider:
RecordServiceInterface service3 = new MyRecordService();
RecordService service4 = new MyRecordService();
MyRecordService service5 = new MyRecordService();
With service3, service4, and service5, the implementation from MyRecordService will be called.
Overriding does not replace methods for parent types unless it is part of the chain (e.g., all three of the instances created in the last block, 3 through 5). If the instance of your Object does is not the type (MyRecordService in this case), then the method is not overridden for that instance with its behavior. service and service2 will still call RecordService's implementation.
It may be more clear with another example:
public interface Runnable {
void run();
}
public class RunnableA implements Runnable {
#Override
public void run() { System.out.println("A"); }
}
public class RunnableB extends RunnableA {
#Override
public void run() { System.out.println("B"); }
}
public class RunnableC implements Runnable {
#Override
public void run() { System.out.println("C"); }
}
You can only have an instance of any one of them, so it will only output one line per call of instance.run(). It depends on the implementation of the instance, and not what exists on the classpath.

Categories