Too much work is done around Eclipse (RCP, Equinox, BIRT, Monkey) that I can't follow all the things which interests me.
However, by browsing the mailing list of the Equinox (Eclipse's OSGi implementation), I discovered a cool new project in the Equinox incubator: Resources Monitoring.
Its mission statement?
To provide a framework for monitoring resources that are contributed by bundles installed on the host machine. The term 'resources' is used to describe something as specific as a single object or something as abstract as an OSGI bundle.
It seems to use JMX to manage the resources and to provide both the server and the client code to manage the resources.
This a long post about designing JMX management on a cluster. To make a long story short: is it a good idea to replicate MBeans on a cluster of Java applications?
I'm working on a Java application which consists of a cluster of nodes, each node running in a separate JVM. Nodes communicates through a common channel through a group communication protocol. Nodes are mostly independent but they are notified when a node joins or leaves the group communication channel.
Each node exposes its managements operations through JMX and contains its own JMX Server which exposes the MBeans of the nodes An administrator can manage each MBeans of the node through JMX using either a RMI or HTTP adaptor:
But the issue is that the cluster does not provide global management. For example, if an administrator wants to manage two MBeans on different nodes to the cluster, he /she has to:
connect to the JMX server of the 1st node
invoke the management operations on a MBean
connect to the JMX server of a 2nd node
invoke the management operations on another MBean
Not very user-friendly...
There are even worse use cases: some management operations should not be performed depending on the state of resources on the other nodes of the cluster.
For example, imagine in the picture above that the MBeans X, Y, Z and T represent the same kind of resource: a Light which can be turned on or off. A mandatory requirements on the cluster is tha there must be always at least one light which is turned on in the cluster at any time.
If the administrator wants to close the light represented by MBean X, he/she has to be sure first that either lights Y, Z or T are still on. Bad news: the management operation is depending on the good will of the admin...
Of course, for our application, we can code a JMX client which does all the grunt work for the admin but putting the management workflow in the JMX client is a bad idea: we open the MBeans to the world and it's likely that some administrators will prefer use a graphical JMX console or a Web one. In that case, they would bypass parts of the management workflow...
In an ideal world, the admin should only ask the light X to switched off and it's up to the cluster to check if it's possible or not.
Of course, we could use the group communication channel to communicate between the nodes of the cluster but I'm not seduced by this proposal. I'd like to keep the management logic as much separate as possible from the business logic which already uses the group channel to exchange data.
Another point: the cluster does not have a central repository to get information or state about the cluster. So it may be interesting to replicate this information on all nodes of the cluster so that whatever node the admin is connected to (through its JMX server), he/she can see the global state of the cluster and perform management operations on any of its nodes.
How do I plan to do that? I was thinking about registering on each node proxies of MBeans whose real implementations are hosted on other nodes:
The dashed rhombus are Mbeans proxies while the plain ones are the real implementations.
In the picture above, when the node #2 joins the cluster, I create proxies of the MBeans registered on existing member of the cluster, node #1 (he received enough information to connect to their JMX servers when joining the group). I register in the JMX server of node #2 the proxies of MBean X and Y with the same ObjectName than the real Mbeans (which are on node #1). Since node #1 is also notified that a new node has joined the cluster, he also creates proxies of MBean Z and T and register them on its own JMX server (still using the same ObjectName than the real ones).
If I go that way, management operations are simplified. To continue on the lights example, the sequence is now:
the admin connect to the JMX server of node #1
it invokes the off() operation on Mbean X
the implementation of MBean X will query the JMX Server of node #1 about all the Light Mbeans and checks there is still one which is on (excluding itself)
when it checks on MBean Z, the proxy will connect to the JMX server of node #2 and invokes the method on the real implementation of MBean Z
(1) from the client, connect to the JMX Server of node #1
(2) get the MBean X and invoke one of its method
(3) get the MBean Z and invoke one of its method
(3') the proxy of MBean Z will connect to the JMX Server of node #2
(3'') the real implementation of MBean Z method will be invoked
The cool thing about this design is that the admin does not even need to be connected to the JMX Server of node #1 to manage MBean X:
(1) from the client, connect to the JMX Server of node #2
(2) get the MBean X and invoke one of its method
(2') the proxy of MBean X will connect to the JMX Server of node #1
(2'') the real implementation of MBean X method will be invoked
(3) get the MBean Z and invoke one of its method
The code is the same regardless of the node the administrator is connected (since the proxies and the real implementations share the same ObjectName on all the JMX Servers of the nodes of the cluster). And the whole design is quite dynamic since each JMX Server can also be notified when MBeans are registered or unregistered on other JMX Servers of the cluster
However I already see some issues with that approach:
what about security credentials when forwarding an invokation from one JMX Server to another?
what about the scalablity if the number of nodes or MBeans increases?
what about event notifications? I'm interested to be notified of events emitted by the real MBeans, not the proxies. How do I make the difference when registering NotificationListener based only on the ObjectNames wich are identical?
and the first question I asked you at the beginning of this post: is it a good idea to replicate MBeans on a cluster of Java applications?
Are theses issues showstoppers either architecturally or technically?
I did some searches on the web about this kind of approach with regards to JMX but I did not find anything conclusive so far so I plan to code a prototype to handle this stuff and see where it leads me. [Update: Coherence seems to provide this feature.]
Wow! Still with me after this long post? In that case, I'd be happy to talk about this design with you. Please do not hesitate to post a comment or send me a mail.
While cleaning up my workpace, I (re) discovered a small application I wrote to familiarize myself with Eclipse editors development.
It is a simple outliner which reads and writes OPML files. Each OPML file is opened in an Eclipse Editor. You can navigate the outliner, indent/outdent the outlines, create new outlines and edit them. To toggle between the edition and the navigation modes, you can use the ESC key (like in vi).
The code is pre-pre alpha (hence the 0.1.1 version) and a lot of essential features are missing:
no copy/paste
The OPML parser is home-made and parses only a subset of OPML 2.0 (but at least, I can read some OPML 2.0 examples such as states.opml)
I pretty sure that the generated OPML is not valid
The fun part of the application is the OutlinerEditor. Each OutlinerEditor is composed of a TreeViewer which displays the outline. The TreeViewer is not editable but each cell of the tree can be edited in place (a la SWT snippet #111).
I released this project on Google Code's project hosting under the Apache License 2.0 and created a corresponding web site to complement the project home. You can check it out using Subversion but to make it simpler to check out, you can import in your workspace the Outliner Team Project Set (provided you have a Subversion plug-in like Subclipse). I don't plan to work extensively on this application but I thought it could be of some interest for new Eclipse RCP developers.
I developped the application on Mac OS X and had the bad surprise to see that the application is not working properly on Linux because I can't navigate the tree with the arrow keys (see issue #3). It seems to be a "bug" in SWT since I can't navigate with the arrow keys in SWT snippet #111 either. Though I'm not sure this is a SWT bug or a platform specific behavior...
I just found a new Interface in Eclipse which I found quite handy.
Let's say that you have an action which creates a new resource and you want to notify views that they have to show this resource.
The key interface is ISetSelectionTarget. If your views respond to this interface (by implementation or adaptation), they can then receive a selectReveal(ISelection selection) message.
For example, one of my view implements ISetSelectionTarget and defines the method:
public void selectReveal(ISelection selection) {
StructuredSelection ssel = convertSelection(selection);
if (!ssel.isEmpty()) {
viewer.getControl().setRedraw(false);
viewer.setSelection(ssel, true);
viewer.getControl().setRedraw(true);
}
}
How do you send this selectReveal() message from your action? An example is found in the JDT, in the org.eclipse.ui.wizards.newresource.BasicNewResourceWizard class:
public static void selectAndReveal(IResource resource, IWorkbenchWindow window) {
// validate the input
if (window == null || resource == null)
return;
IWorkbenchPage page = window.getActivePage();
if (page == null)
return;
// get all the view and editor parts
List parts = new ArrayList();
IWorkbenchPartReference refs[] = page.getViewReferences();
for (int i = 0; i < refs.length; i++) {
IWorkbenchPart part = refs[i].getPart(false);
if (part != null)
parts.add(part);
}
refs = page.getEditorReferences();
for (int i = 0; i < refs.length; i++) {
if (refs[i].getPart(false) != null)
parts.add(refs[i].getPart(false));
}
final ISelection selection = new StructuredSelection(resource);
Iterator itr = parts.iterator();
while (itr.hasNext()) {
IWorkbenchPart part = (IWorkbenchPart) itr.next();
// get the part's ISetSelectionTarget implementation
ISetSelectionTarget target = null;
if (part instanceof ISetSelectionTarget)
target = (ISetSelectionTarget) part;
else
target = (ISetSelectionTarget) part.getAdapter(ISetSelectionTarget.class);
if (target != null) {
// select and reveal resource
final ISetSelectionTarget finalTarget = target;
window.getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
finalTarget.selectReveal(selection);
}
});
}
}
}
However, your code does not need to be that generic. If you already know which view may be interested to be notified, you can use
IViewPart part = page.findView(viewId):
to retrieve the interested IViewPart and after checking that it will respond to ISetSelectionTarget (either by implementation or adaptation), you can send it a selectReveal() message directly.
However, the default Welcome page I had on my Ubuntu desktop is quite broken
it is ugly
the links to the workbench are broken (links like http://org.eclipse.ui.intro/showPage?id=overview open in Firefox)
when I close it, it asks me to save a file
After a little search on eclipe.org SWT FAQ, it appears that by default, Ubuntu is missing the MOZILLA_FIVE_HOME which is required by SWT to use the web browser internally.
I just added this variable before starting Eclipse:
Great new album from Pearl Jam. It's been a long wait for this one but it's worth it. If you need to be convinced, a clip of "Life Wasted" can be watched on Amazon.
It is quite simple but I stumble upon it before finding how in Eclipse you can stop the traversal of SWT Control from a TraverseListener implementation.
In your listener, handle the TraverseEvent event and then just
event.doit = false;
and the system will stop traversing the Controls.
Everything is well explained in TraverseEvent javadoc (but I'm guilty of not reading javadoc until I need it...). The explanation is worth a read and shows how powerful traversal can be in eclipse using both TraverseEventdetail and doit fields.
Apache central to Open Source work but Eclipse is also gravitating to the center
The license trend is going to the bottom
Proprietary
|
v
Restricted
|
v
Copyleft (GPL, EPL)
|
v
Non-copyleft (APL, BSD)
I found it quite interesting to see how Apache is organized and how Eclipse compares to it.
For now, there is few overlaps between Apache and Eclipse communities but it has already started. For example, both communities now offer an OSGi implementation:
Scripting Eclipse means a lot of different things to different people. My own interest is to provide scripting ability to a RCP application so that its users can customize it for their needs and create their own workflow.
For example, imagine that the RCP application is used to manage remote resources. Each resources can be manage individually through a set of methods. But what if you want to provide a workflow for advanced operations?
One way to do this is through wizards. But with that solution, users lose control like Joel Spolksy explained in his presentation. Besides it is very difficult to provide wizards which makes simple things simple and complex things possible. They tend to become uncluttered and undecipherable.
Another way is to provide cheatsheets. However, interaction between the cheatsheets and the user interface remains basic. And users are still not in control: they must follow the steps dictated by the cheatsheets.
Now, imagine that we expose a DOM of the managed resources and we let users script their processes. They are in control and they manage the workflow of their resources. They win because they are in control and we (the RCP developpers) win because we can keep our RCP application simple. We just have to expose the simplest useful DOMs to our users to let them handle themselves their more complex and specific processes.
I wrote a simple DOM to write message to Eclipse console from a Monkey Script.
I have not yet created an update site for it so you have do download it and install it in your plugins directory manually. It provides a out variable that you can use to write to a console.
Here is the mandatory "Hello, World" example:
--- Came wiffling through the eclipsey wood ---
/*
* Menu: Console > Hello
* Kudos: Jeff Mesnil
* License: EPL 1.0
* DOM: http://jmesnil.net/eclipse/updates/net.jmesnil.doms
*/
function main() {
out.print("Hello, ").println("World");
}
--- And burbled as it ran! ---