Sud's Blog
The Observer Pattern in Practice
I needed a way to display the current state of a long running job to the user. You'll agree that being able to see the progress bar move and having constant feedback from the application as opposed to having the application lock up for several minutes while it crunches away makes the user experience infinitely better. The Observer pattern to the rescue. If you aren't familiar with this pattern, I recommend a brief de-tour before coming back here. Also, I use Java and it's support for the Observer pattern though you should be able to implement it in C# or other similar languages.
Here is the application architecture:
UI Layer
Business Layer
Persistence Layer
Nothing special, just your traditional layered architecture. Except that the long running operation encompasses processing in the business layer and the persistence layer. So at the UI layer (ViewModel.java) I instantiate an Observable LogData object. This object must be accessible in all the layers. Consequently LogData.java needs to be located in a common package that all the other layers can depend on.
Here is the Observable LogData.java.
public class LogData extends java.util.Observable {
private List<String> messages = new ArrayList<String>();
public List<String> getMessages() {
return messages;
}
public void add(String message) {
messages.add(message);
setChanged();
notifyObservers(message);
}
public void clear() {
messages.clear();
}
}
LogData wraps a List object that tracks all logged messages. When a calling class adds a message via the add() method, the notifyObservers() method is fired.
Here is the UI model class ViewModel.java which serves as the Observer.
public final class ViewModel implements java.util.Observer {
public void processButtonClick() {
LogData logData = new LogData();
logData.addObserver(this);
Backend backend = new Backend(logData);
backend.process(); // make call to business layer
}
/*
* (non-Javadoc)
*
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void update(Observable o, Object arg) {
message = (String) arg;
System.out.println(message);
}
}
The processButtonClick() method is called upon a mouse click in the UI (not shown here). A LogData object is instantiated and the viewModel is added to it as an observer via the addObserver() method call. This hooks the Observable logData and the Observer viewModel together. Changes to the logData object will fire the update() method in viewModel.
Backend.java is the business logic code where we make use of the logData object to log the feedback.
public class Backend {
private LogData logData;
public Backend(LogData logData) {
this.logData = logData;
}
public void process() {
.....
.....
logData.add("Completed");
}
}
Tying it all together, when the process() method in Backend calls logData.add(message), the logData.add() method fires the notifyObservers(message), which in turn fires the update() method in ViewModel.
This is a simplified version of the solution and the goal was to help you see how the observer pattern can be used.
Please add comments on better or different ways to achieve the same ends.
Posted at 03:45PM Apr 15, 2008 by sudhakar in Java | Comments[0]
Pesky "Access Restriction" issue in Eclipse 3.2
If you are developing plugins using Eclipse PDE, here's an issue you might run into in Eclipse 3.2 (haven't confirmed on 3.3.x yet) when referencing classes in plugins listed in the dependencies tab of MANIFEST.MF
"Access restriction: The type XXXXXXXX is not accessible due to restriction on required project XXXXXXXXXXXXXXXXXXXX"
This is resolved by re-ordering the plugins in the dependencies tab till the compilation error disappears. I haven't been able to find much information about what causes this issue in the first place and why this solution works. But it works and sometimes that's sufficient for me!
Posted at 02:41PM Mar 31, 2008 by sudhakar in Java | Comments[0]
Day 1 at Source Allies
So today was my first day at Source Allies and I thought I'd kick of my blogging with what else but "My First Day at Work" post. My morning commute to work was probably the most focussed driving I've ever done. The first thing I probably need to do is replace my tires with all-weather tires so I can relax a little bit more on the way to work! Morning was spent getting all my login's setup and verified, which is really nice about a small company or a company that has it's employee on-boarding process down. The intranet site uses a wiki..so that was a good starting point to learn about what existing projects and initiatives etc. Haven't figured how all of it works together yet. Afternoon lunch was at the nice Italian restaurant at Biaggis (http://www.biaggis.com/) paid for! Got to meet some more of my colleagues during lunch. The ride up there gave me a better sense of the area and the highways around here. After lunch I did some research on driving in winter weather...(this is where I get some pity) and catching up a Eclipse PDE webinar. The webinar though being focused on 3.4 and level 101 was useful in that I picked a couple tips like how to automatically include a build qualifier in the version number. But that was my first day at Source Allies.
Posted at 05:03PM Jan 22, 2008 by sudhakar in General | Comments[0]