For a school project, I need to write a simple Server in Java that continuously listens on an incoming directory and moves files from this directory to some place else. The server needs to log info and error messages, so I thought I could use the Proxy pattern for this. Thus, I created the following ServerInterface:
public interface ServerInterface extends Runnable {
public void initialize(String repPath, ExecutorInterface executor, File propertiesFile) throws ServerInitException;
public void run();
public void terminate();
public void updateHTML();
public File[] scanIncomingDir();
public List<DatasetAttributes> moveIncomingFilesIfComplete(File[] incomingFiles);
}
Then I've created an implementation Server
representing the real object and a class ProxyServer
representing the proxy. The Server
furthermore has a factory method that creates a ProxyServer
object but returns it as a ServerInterface
.
The run
-method on the proxy-object looks like this:
@Override
public void run(){
log(LogLevels.INFO, "server is running ...");
while( !stopped ){
try {
File[] incomingContent = scanIncomingDir();
moveIncomingFilesIfComplete(incomingContent);
updateHTML();
pause();
} catch (Exception e) {
logger.logException(e, new Timestamp(timestampProvider.getTimestamp()));
pause();
}
}
log(LogLevels.INFO, "server stopped");
}
The functions that are called within the try
statement simply log something and then propagate the call to the real object. So far, so good. But now that I've implemented the run
-method this way in the proxy object, the run
-method in the real object becomes obsolete and thus, is just empty (same goes for the terminate
-method).
So I ask my-self: is that ok? Is that the way the proxy pattern should be implemented?
The way I see it, I'm mixing up "real" and "proxy"-behaviour ... Normally, the real-server should be "stuck" in the while-loop and not the proxy-server, right? I tried to avoid mixing this up, but neither approaches were satisfying:
I could implement the
run
-method in the real object and then hand over the proxy object to the real object in order to still be able to log during the while-loop. But then the real object would do some logging, which is I tried to avoid by writing a proxy in the first place.I could say, only Proxy-Server is
Runnable
, thus deletingrun
andterminate
from the Interface, but this would break up the Proxy pattern.
Should I may be use another design? Or I am seeing a problem where there is none?
You're definitely thinking in the right way. You've hit upon an interesting notion.
Features like logging, as you've described, are an example of what we call cross-cutting concerns in Aspect Oriented programming.
. . therefore, they have the tendency to break object oriented programming. What does this mean?
Enter Aspect Oriented Programming
This is the reason we have AOP - it exists to modularize and encapsulate these cross-cutting concerns. It works as follows:
Ways we can "weave" in a requirement with AOP
The latter two options are supported in AspectJ.
In Conclusion:
It sounds as though you're moving towards Aspect Oriented Programming (AOP), so please check this out. Note also that the Spring Framework has a lot of features to simplify the application of AOP, though in your case, given this is a school assignment, its probably better to delve into the core concepts behind AOP itself.
NB: If you're building a production-grade server, logging may be a full-blown feature, and thus worth using AOP. . in other cases its probably simple enough to just in-line.