How to log List interface method for existing code - java

I have existing codebase that sometimes uses ArrayList or LinkedList and I need to find a way to log whenever add or remove is called to track what has been either added or removed.
What is the best way to make sure I have logging in place?
So for example.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
and
LinkedList<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList.add(333);
Not sure if I can intercept add method to achieve this or create overriding class that implements java.util.List interface then use it instead. Either way I'm looking for a good solution that requires minimum intervention and prefrerrably without using any third party packages...

I would use the so called Decorator Pattern to wrap your lists.
This would be a simple example code just to give you an idea:
private static class LogDecorator<T> implements Collection<T> {
private final Collection<T> delegate;
private LogDecorator(Collection<T> delegate) {this.delegate = delegate;}
#Override
public int size() {
return delegate.size();
}
#Override
public boolean isEmpty() {
return delegate.isEmpty();
}
#Override
public boolean contains(Object o) {
return delegate.contains(o);
}
#Override
public Iterator<T> iterator() {
return delegate.iterator();
}
#Override
public Object[] toArray() {
return delegate.toArray();
}
#Override
public <T1> T1[] toArray(T1[] a) {
return delegate.toArray(a);
}
#Override
public boolean add(T t) {
// ADD YOUR INTERCEPTING CODE HERE
return delegate.add(t);
}
#Override
public boolean remove(Object o) {
return delegate.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
return delegate.addAll(c);
}
#Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
#Override
public void clear() {
delegate.clear();
}
}

There is not really a simple way to get there.
Those classes are part of the "standard libraries"; so you can't change their behavior. You could create your own versions of them; and use class path ordering to get them used; but this really dirty hack.
The only other option: extend those classes; #Override the methods you want to be logged; and make sure all your sources use your own versions of those classes. Or if you prefer composition over inheritance you go for the decorator pattern; as suggested by JDC's answer.
The "third" option is really different - you turn to aspect oriented programming (for example using AspectJ) and use such tools to manipulate things on a bytecode level. But that adds a whole new layer of "complexity" to your product; thus I am not counting it as real option.
EDIT on your answer: it seems that you don't understand the difference between interface and implementation?! An interface simply describes a set of method signatures; but in order to have real code behind those methods, there needs to be an implementing class. You see, when you do
List<X> things = new ArrayList<>();
the real type of things is ArrayList; but you rarely care about that real type; it is good enough to know that you can all those List methods on things. So, when you create some new implementation of the List interface ... that doesn't affect any existing
... = new ArrayList ...
declarations at all. You would have to change all assignments to
List<X> things = new YourNewListImplementation<>();

JDC has given a good way to follow.
I would like bring important precisions.
The decorator pattern allows to create a class which decorates another class by adding or removing dynamically a new responsibility to an instance.
In your case, you want to add responsibility.
Decorator is not an intrusive pattern but the decorator class have to conform to the class that it decorates.
So in your case, having a decorator which derives from the Collection interface is not conform to the decorated object since List has methods that Collection has not.
Your need is decorating List instances, so decorator should derive from the List type.
Besides, the decorator class can do, according its needs, a processing before and or after the operation of the class that it decorates but it is also responsible to call the original operation of the decorated class.
In your case, you want to know if an element was added or in or removed from the List. To achieve it, as the method result has consequences on whether you log or not the information, it is preferable to delegate first the processing to the decorated object and then your decorator can perform its processings.
Sometimes, you don't need to decorate a method, don't do it but don't forget to delegate suitably to the decorated object.
import java.util.Iterator;
import java.util.List;
public class DecoratorList<T> implements List<T> {
private static final Tracer tracer = ....;
private List<T> decorated;
private DecoratorList(List<T> decorated) {
this.decorated=decorated;
}
// no decorated methods
....
#Override
public int size() {
return this.decorated.size();
}
#Override
public boolean isEmpty() {
return this.decorated.isEmpty();
}
#Override
public boolean contains(Object o) {
return this.decorated.contains(o);
}
#Override
public Iterator<T> iterator() {
return this.decorated.iterator();
}
....
// end no decorated methods
// exemple of decorated methods
#Override
public void add(int index, T element) {
tracer.info("element " + element + " added to index " + index);
this.decorated.add(index,element);
}
#Override
public boolean remove(Object o) {
final boolean isRemoved = this.decorated.remove(o);
if (isRemoved){
tracer.info("element " + o + " removed");
}
return isRemoved;
}
}
As explained, a decorator is not intrusive for the decorated objects.
So the idea is not changing your code that works but add the decorating operation just after the list be instantiated.
If don't program by interface when you declare your list variables, that is you declare ArrayList list = new ArrayList() instead of List list = new ArrayList() , of course you should change the declared type to List but it doesn't break the code, on the contrary.
Here is your example code :
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
LinkedList<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList.add(333);
Now, you could do it :
List<Integer> list = new ArrayList<Integer>();
list = new DecoratorList<Integer>(list); // line added
list.add(123);
List<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList = new DecoratorList<Integer>(anotherNewList); // line added
anotherNewList.add(333);
To ease the task and make it safer, you could even create a util method to apply the decoration on the list :
private static <T> List<T> decorateList(List<T> list) {
list = new DecoratorList<T>(list);
return list;
}
and call it like that :
List<Integer> list = new ArrayList<Integer>();
list = decorateList(list); // line added
list.add(123);

You can use Aspects - but it will log every add and remove call:
#Aspect
public class ListLoggerAspect {
#Around("execution(* java.util.List.add(..))")
public boolean aroundAdd(ProceedingJoinPoint joinPoint) throws Throwable {
boolean result = (boolean) joinPoint.proceed(joinPoint.getArgs());
// do the logging
return result;
}
}
You'll need to configure the aspect in META-INF/aop.xml :
<aspectj>
<aspects>
<aspect name="com.example.ListLoggerAspect"/>
</aspects>
</aspectj>

An easy way to accomplish this is wrapping your source list in a ObservableList and use that as base list. You can simply add an listener to this list to catch every modification (and log out if you wish)
Example:
List obs = FXCollections.observableList(myOriginalList);
obs.addListener(c -> {
for(Item it : c.getRemoved())
System.out.println(it);
for(Item it : c.getAddedSubList())
System.out.println(it);
});
See the javafx documentation on how to add a good listener

Your List is the source here. You need to keep track of the changes to the source. This is a good and natural example of the Observer pattern. You can create an Observable which is your list. Then create some Observers and register them to the Observable. When the Observable is changed, notify all the registered Observers. Inside the Observer you can log the changes using the input event. You should literally implement some ObservableCollection here. You can use Java Rx to get this work done. Please find the sample code given below.
package com.test;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
import rx.subjects.PublishSubject;
public class ObservableListDemo {
public static class ObservableList<T> {
protected final List<T> list;
protected final PublishSubject<T> onAdd;
public ObservableList() {
this.list = new ArrayList<T>();
this.onAdd = PublishSubject.create();
}
public void add(T value) {
list.add(value);
onAdd.onNext(value);
}
public Observable<T> getObservable() {
return onAdd;
}
}
public static void main(String[] args) throws InterruptedException {
ObservableList<Integer> observableList = new ObservableList<>();
observableList.getObservable().subscribe(System.out::println);
observableList.add(1);
Thread.sleep(1000);
observableList.add(2);
Thread.sleep(1000);
observableList.add(3);
}
}
Hope this helps. Happy coding !

We need a little more information to find the right solution. But I see a number of options.
You can track changes, using a decorator.
You can copy the collection and calculate the changes
You can use aspects to 'decorate' every List in the JVM
Change the existing codebase (a little bit)
1) works if you know exactly how the list is used, and once it is returned to your new code, you are the only user. So the existing code can't have any methods that add to the original list (because would invoke add/remove on the delegate instead of the decorated collection).
2) This approach is used when multiple classes can modify the list. You need to be able to get a copy of the list, before any modifications begin, and then calculate what happened afterwards. If you have access to Apache Collections library you can use CollectionUtils to calculate the intersection and disjunction.
3) This solution requires some for of weaving (compile or load time) as this will create a proxy for every List, so it can add callback code around the method calls. I would not recommend this option unless you have a good understanding of how aspects work, as this solution has a rather steep learning curve, and if something goes wrong and you need to debug you code, it can be a bit tricky.
4) You say existing codebase, which leads me to believe, that you could actually change the code if you really wanted. If this is at all possible, that is the approach I would choose. If the user of the List needs to be able to track changes, then the best possible solution is that the library returns a ChangeTrackingList (interface defining methods from tracking), which you could build using decoration.
One thing you have to be aware of when decorating, is that List has a removeAll() and a addAll(), these methods may or may not call the add() and remove(), this depends on the list implementation. If you are not aware of how these methods are invoked internally you could end up seeing an object as removed twice (unless you can use a set).

Related

Nice validation if the list is null

I have an object with several lists
public class Contribution<T extends MovieRequest> {
private Set<T> elementsToAdd;
private Set<T> elementsToUpdate;
private Set<Integer> numbersToDelete;
}
This object is sent to the method. There I operate on these lists.
public void correctOtherTitle(
final Contribution<OtherTitle> contribution
) throws ResourceNotFoundException {
contribution.getElementsToAdd().forEach(otherTitle -> {
...
});
contribution.getNumbersToDelete().forEach(number -> {
...
});
contribution.getElementsToUpdate().forEach(otherTitleToUpdate -> {
...
});
}
The problem is that there is no need to complete all the lists and some of them may be null. And then throws a NullPointerException exception.
Of course, it is possible to make a condition if, but it does not look aesthetically.
if(contribution.getElementsToAdd() !- null) {
contribution.getElementsToAdd().forEach(otherTitle -> {
...
});
}
It looks fatal. Do you have an idea how to do it better?
To avoid not null check with explicit if , you could change the types of the Contribution class fields to Optional that wrap the actual data :
public class Contribution<T extends MovieRequest> {
private Optional<Set<T>> elementsToAdd;
private Optional<Set<T>> elementsToUpdate;
private Optional<Set<Integer>> numbersToDelete;
}
and adapt getters consequently.
In this way, you could use Optional.ifPresent(Consumer<? super T> consumer) that spares an explicit not null check :
contribution.getElementsToAdd().ifPresent(otherTitle -> {
otherTitle.forEach(m -> ...);
});
It is not necessary very elegant either. However, it reduces code duplication without introducing intermediary variables (that may create side effect).
Getter methods are indeed invoked once.
The problem is that there is no need to complete all the lists and some of them may be null.
I'd argue that you should fix the root problem, rather than work around it. Why can these sets be null? You already have a "safe" way to indicate that there's nothing to add/delete/update - an empty set. So if these sets are under your control (the fact that they are private and you have getters implies this), then you should enforce that invariant.
For example, maybe your Contribution class could look like this:
public class Contribution<T extends MovieRequest> {
private Set<T> elementsToAdd = new HashSet<>();
// ... same for elementsToUpdate / numbersToDelete ...
public Set<T> getElementsToAdd() {
return Collections.ummodifiableSet(elementsToAdd);
}
public void addElementToAdd(T element) {
elementsToAdd.add(element);
}
}
This pattern involves a fair amount of boilerplate. But code generators such as Immutables help a great deal with that.
There is no shortcut to check for not null, but you could implement a constructor on the Contribution class and initialize the sets to empty sets.
Also, if the code matters to you, I may suggest you to invest your efforts in trying to push the logic of the correctOtherTitle function into the Contribution class, because passing and object to a method that manipulates the object smells like an anemic domain.

How do I make a variable that can store a queue or a stack?

I have an object that has a variable that I want to be able to hold either a queue or a stack. Anything that has an add and a remove with the appropriate logics. I think this can be done with an interface but the two in java.util doesn't have the same interface or even the same name for the two operations.
My plan right now is to create a wrapper to make them fit what I want, but this seems inelegant. Is there a better way?
I want something like:
Something<E> steps;
So that I can call step.pop() and step.push() or whatever method names without having to know if steps implements queue logic or stack logic.
You might want either ArrayDeque or LinkedList depending on your needs.
Both implement Deque (double ended queue).
From the Javadoc on ArrayDeque: "This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue."
Elements can be added or removed from either end of a Deque.
A Deque can be used as a queue by calling addLast and removeFirst, and can also be used by a stack by using addLast and removeLast.
If you really want it to behave like either one, you can keep a boolean flag and write helper methods, or you can write a class:
public class QueueOrStack<E> implements Iterable<E> {
private Deque<E> container = new ArrayDeque<E>();
private boolean isQueue;
public QueueOrStack(boolean isQueue) {
this.isQueue = isQueue;
}
public E pop() {
return isQueue ? container.removeFirst() : container.removeLast();
}
public void push(E element) {
container.addLast(element);
}
public void pushAll(E... element) {
for (E e : element)
container.addLast(e);
}
public boolean isQueue() {
return isQueue;
}
public void setQueue(boolean isQueue) {
this.isQueue = isQueue;
}
public boolean toggleQueue() {
return isQueue = !isQueue;
}
#Override
public Iterator<E> iterator() {
return container.iterator();
}
}
Here's the test:
QueueOrStack<String> strings = new QueueOrStack<>(true);
strings.pushAll("hello", ", " , "world\n");
for(String s : strings)
System.out.print(s); //"hello, world"
System.out.println(strings.pop()); //"hello"
strings.toggleQueue();
System.out.println(strings.pop()); //"world"

Understanding best use of Java Generics in this example case

Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)

Extending a non-generic class to a generic class

The Java class CircularFifoBuffer in the package org.apache.commons.collections.buffer is non-generic, and can store objects of any class.
I would like to create a generified version of this, that can only hold objects of class T. My first thought was to extend CircularFifoBuffer and simply write a new 'add' method:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
public boolean add(T data) {
return super.add(data);
}
}
However, this leaves the old 'add' method in place, allowing for objects of arbitrary class to be added. Is there a way around this that uses inheritance rather than composition (so that I don't have to re-implement all of CircularFifoBuffer's methods) but prevents users of the class from adding non-T objects?
One idea is t implement your own buffer that just wraps the original one:
public class CircularFifoQueue<T> {
private CircularFifoBuffer buffer = new CircularFifoBuffer();
public boolean add(T data) {
return buffer.add(data);
}
// implement all other methods that are needed
}
So the internal buffer takes everything but the wrapper makes sure that only T type objects can be added. Problem: right now the buffer does not implement any interface. So it's usage is a bit limited right now (you can't use it if you need to send a Buffer for example)
No, you can't.
The simple reason why this isn't possible is polymorphism. If you could remove the add(Object) method, you would break polymorphism for the CircularFifoBuffer class.
Here is a simple example. For this to work correctly, your CircularFifoQueue class needs to have a add(Object) method.
CircularFifoBuffer buffer = new CircularFifoQueue<String>();
buffer.add(new Object());
#Vivien's answer already explains why it doesn't really make sense to do this (for more information, read about the Liskov substitution principle).
However, you could hack around this by defining a custom override of add(Object) that simply throws an exception at run-time. It's not a very elegant solution, but if you want a quick fix, then this might be it.
You can try the following approach. It is not very elegant, but it should do the job:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
private Class<T> klass;
public CircularFifoQueue(Class<T> klass) {
this.klass = klass;
}
#Override
public boolean add(Object data) {
T typedData = klass.cast(data);
return super.add(typedData);
}
public boolean add(T data) {
return super.add(data);
}
}
...
CircularFifoQueue<String> queue = new CircularFifoQueue<String>(String.class);
queue.add("hello"); // should work
queue.add(123L); // should throw ClassCastException
Anyway, implementing a class that delegates its method calls is not very hard. Any decent IDE will autogenerate that for you.

What's the most practical way to have "functions in a dictionary" in Java?

When programming with C/C++ or Python I sometimes used to have a dictionary with references to functions according to the specified keys. However, I don't really know how to have the same -- or at the very least similar -- behavior in Java allowing me dynamic key-function (or method, in Java slang) association.
Also, I did find the HashMap technique somebody suggested, but is that seriously the best and most elegant way? I mean, it seems like a lot to create a new class for every method I want to use.
I'd really appreciate every input on this.
You don't need to create a full, name class for each action. You can use anonymous inner classes:
public interface Action<T>
{
void execute(T item);
}
private static Map<String, Action<Foo>> getActions()
{
Action<Foo> firstAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Action<Foo> secondAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Action<Foo> thirdAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Map<String, Action<Foo>> actions = new HashMap<String, Action<Foo>>();
actions.put("first", firstAction);
actions.put("second", secondAction);
actions.put("third", thirdAction);
return actions;
}
(Then store it in a static variable.)
Okay, so it's not nearly as convenient as a lambda expression, but it's not too bad.
The short answer is you need to wrap each method in a class - called a functor.

Categories

Resources