Thursday, September 30, 2010

Flex annoyances...Can I grabz the initialz focuz?

I've been playing a bit with ActionScript and the like lately. ActionScript and few other languages never really caught my interest. Sure, I can read and I could manage, but why? ;-).

In fact, I've been avoiding Perl, ActionScript and few others professionally for years:
Q:"So you know Java, Quartz, JMX, Unix/Linux, etc. what about Perl?"
A:"Oh my, to be honest, I'm afraid of it...".
Sometimes, you just have to suck it up and do the damn thing anyway.

It's surprising to me that Flex is used a lot for "intensive" tasks, that would/should require threads to poll data at specific intervals. What else would you use if you need a decent toolkit with advanced drawing capabilities on the browser? A beloved Java Applet? Silverlight? HTML5? Javascript?? ActiveX???

Flex has some interesting things despite being single threaded(not the flash engine itself) : function pointers, easy binding, easy drag and drop, etc. However, some simple to more complex things can become annoying, while with more code, but still simple code, the same thing would be trivial with a Desktop UI toolkit(that you're familiar with).
  • Can I be sure that a return inside a switch statement will just return, at once?
  • Can I get the initial focus on a component once the flash movie is loaded, without keyboard interaction from my part? without random errors once in a while? without upgrading to bleeding edge?
  • Can I get a simple even bare layout manager interface without plugging stuff directly inside some updateDisplayList method? Or without managing myself couple of  "drawing delegates"?
  • etc...

It looks like Flex has couple of issues with its FocusManager. All I wanted was setting the focus on a component at startup with a blinking cursor... Trivial right?

I was looking for an answer on Google as many seem to have that issue. I found a suggestion that seem to work :
ExternalInterfaceIfAvailable.call(SomeJavascript.focusFlashComponent).
callLater(mycomponent.grabTheFocus)

Lots of people seem to be ok with the fact that the Javascript that they write might not work on most browsers. Well, good enough if only a defined set of browsers will be supported by the application.
But hey man, this is 2010, most web applications are past the time where a notice would be displayed "Only supported in Internet Explorer". Unless this is the web interface of your online banking accounts, you switch to an alternative immediately."Sorry man, I do not use Windows, so how could I use I.E??".

I just grabbed the latest version of prototypejs and I'm confident that the code compatible with most modern browsers(and even maybe text based browsers that support a little subset of Javascript). Why not write it myself? Well I don't do tons of Javascript, and looking at browsers specs and compatibility with Javascript versions might not be worth the time. From prototypejs to JQuery and the like, people already did the dirty work.

Let's say that the Javascript code is working, now you're able to set the initial focus on a component once the flash movie is loaded. In my case, the component that need the focus is added/removed at runtime.

When going back to the initial screen, Flex 3.4 throws randomly errors in the FocusManager. It looks like that FocusManager bug got fixed(defaultButton issue), but my solution was to deactivate/activate the FocusManager myself :
  • Initial screen
onCreationComplete -> javascript call to set the focus -> Specific flex component requests then the focus
  • Leaving the initial screen(Avoid some null errors on the defaultButton if you use that)
component.focusmanager.deactivate()
  • Going back to the initial screen(Avoid some null errors on the defaultButton if you use that)
mycodeToGrabTheFocus
component.focusmanager.activate()

Tuesday, December 29, 2009

Default right-click in all text components of an application

First of all, Merry Christmas and Happy New Year everybody!

Many people are still surprised not to see a default right-click popup in all text components of a Java application. One way to do it, is to push a new EventQueue to the default one. One concern could be applets in general (unsigned applets, global EventQueue).
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new PopupEventQueue());
Below is the code for the event queue.

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;

import javax.swing.AbstractAction;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

import javax.swing.text.JTextComponent;

public class PopupEventQueue extends EventQueue {

private final JPopupMenu popup = new JPopupMenu();
private final TextAction[] popupActions = new TextAction[4];

public PopupEventQueue() {
popupActions[0] = new TextAction("Cut") {
private static final long serialVersionUID = -3844049016540352208L;

public void actionPerformed(ActionEvent ae) {
textComponent.cut();
}

@Override
protected void postTextComponentInitialize() {
setEnabled(textComponent.isEditable() && isTextSelected());
}
};
popupActions[1] = new TextAction("Copy") {
private static final long serialVersionUID = -3844049016540352208L;

public void actionPerformed(ActionEvent ae) {
textComponent.copy();
}

@Override
protected void postTextComponentInitialize() {
setEnabled(isTextSelected());
}
};
popupActions[2] = new TextAction("Paste") {
private static final long serialVersionUID = -3844049016540352208L;

public void actionPerformed(ActionEvent ae) {
textComponent.paste();
}

@Override
protected void postTextComponentInitialize() {
setEnabled(textComponent.isEditable());
}
};
popupActions[3] = new TextAction("Select all") {
private static final long serialVersionUID = -3844049016540352208L;

public void actionPerformed(ActionEvent ae) {
textComponent.selectAll();
}

@Override
protected void postTextComponentInitialize() {
setEnabled(!textComponent.getText().trim().equals(""));
}
};

for (TextAction action : popupActions) {
popup.add(action);
}
}

@Override
protected void dispatchEvent(AWTEvent event) {
if (event.getID() == MouseEvent.MOUSE_RELEASED) {
MouseEvent e = (MouseEvent) event;

Component c = getSource(e);

if (c instanceof JTextComponent) {
if (SwingUtilities.isRightMouseButton(e)) {
final JTextComponent txtComp = (JTextComponent) c;
for (TextAction action : popupActions) {
action.setTextComponent(txtComp);
}
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
super.dispatchEvent(event);
}

private Component getSource(MouseEvent e) {
return SwingUtilities.getDeepestComponentAt(
e.getComponent(),
e.getX(),
e.getY());
}

private static abstract class TextAction extends AbstractAction {

private static final long serialVersionUID = -7708937505251885197L;
protected JTextComponent textComponent;

public TextAction(String name) {
super(name);
}

public void setTextComponent(JTextComponent textComponent) {
this.textComponent = textComponent;
postTextComponentInitialize();
}

protected boolean isTextSelected() {
return (textComponent.getSelectionStart() != textComponent.getSelectionEnd());
}

protected abstract void postTextComponentInitialize();
}
}

Monday, August 24, 2009

The making of an OSGI based IRC Bot

I've released the source code of JerkBot, an IRC bot based on Jerklib and OSGI. JerkBot source code is a multi-module maven project. It's not some OSGI/Java blueprints as I'm no OSGI expert, plus JerkBot is basically a 24 hours effort without bug fixes.

The library itself is distributed under BSD license, but the bot provides plugins such as SVN for example using SVNKit , which is subject to other licensing terms.

The bot uses Declarative Services for OSGI and Java technologies such as :

  • Apache Lucene for Javadoc Search
  • Quartz for job scheduling(session tracking, pending registrations, etc.)
  • Javamail to send emails for user registration
  • EclipseLink for persistence
  • A subset of JAAS for security
  • JMX for administrative commands (accessible through JConsole or through the bot jmx command)
  • The usual Jakarta libraries and couple of other libraries

I didn't provide scripting languages to the bot for security reasons, there's only JMX. I would prefer to offer scripting languages in a secure way with a custom SecurityManager to prevent drama from happening :-).
Let's say scripting is enabled, and someone accidently tries one or all the following instructions in a scripting language.

  • File("/somepath").delete()
  • System.exit(0)
  • Download("http://website/hugefile.iso").saveToDisk();

JerkBot was roughly a one day effort with 4 rewrites(1 full day each), and of course bug fixes time to time:
  • The first version was using traditional OSGI, well not so traditional :-), with BundleActivators service trackers and listeners, etc.
  • The second rewrite used Declarative Services with manually written XML descriptors
  • The third rewrite was based on Felix IPOJO. I would have preferred to use IPOJO, but found some annoyances(abstract based classes, JMX flexibility, etc.).
  • The last rewrite is using Felix SCR but with annotations to generate XML descriptors for components. Simplify code, remove unnecessary abstractions, consistent logic, etc.

I'll be providing the binary distribution soon. The binary distribution contains everything necessary to run the bot : OSGI configuration files, Bot configuration, jars, a user/developer guide, etc.

What the bot doesn't provide is a logging mechanism, for IRC channel logs. To do it right, I think it would be better to create a new project. In my opinion, when a bot logs channel it should have, if possible, the following features:

  • Configurable tasks to schedule flexible timed delivery of existing logs(local filesystem, ftp, samba share, ssh, http put, etc.)
  • Configurable log format(HTML, CSV, TXT) with optional generation of html logs or text logs.
  • Database storage or any other persistence mechanism(Apache Lucene Index vs flat text files, database logs, etc.)
  • Ability to stop/start logging for every channel
  • Optional Web front-end to publish logs(Could be a static HTML pages with Javascript search, JSF, Wicket, GWT, Rest interface + Apache Lucene or a DB for search).
Providing a quick and dirty plugin for channel logs would be trivial but not flexible :-). I started implementing it, but I decided to stop there.

The first draft of the bot manual can be found in the svn repository. Please bear with me for grammar and spelling mistakes, it was a written very quickly at early AM :-)

In JerkBot plugins are provided by OSGI bundles. I learned a lot from my previous experience with JPF when writing XPontus.

For now the bot is sitting on irc.freenode.net in the ##swing channel, running on an old laptop(FreeBSD-CURRENT).


Wednesday, July 22, 2009

Which one is the best?

You've probably heard it many times, in various circumstances. What was your answer?

That trivial question may(or not) have been subject to a long answer with hopefully credible reasons. "The problem is ... Many tools provide XXX ... This tool is the best, in this case, as ...".
But you're the expert! The reasons motivating your choices should be obvious to anybody else without having a long discussion!

There is no best, there are needs and there are constraints to reach particular goals(short, medium or long term). All those variables usually fits in to a vision.

If there were a best, anyone who could afford it, would have it.

No, no why would I want to use crap seriously?? So many tools already suck and people keep providing more crap. Maybe I should suggest that they stop already, as there are many similar great tools out there.

A typical conversation about choosing a Linux distribution
Q: "What's the best Linux distribution? Ubuntu?"
A: "Wut??? Hell no, it's Debian and all the rest is crap including the derivatives."
Q: "Why?"
A: "Because Ubuntu doesn't ... and because I say so :-)"
Q: "But Ubuntu is easy and Debian is not user friendly!"
A: "Really? Not really .... Ah, I guess I just like things when they're complicated, must be the geek feeling."

A tool can meet needs but not all the constraints and vice-versa and what you'll probably be looking for is a balance.

  • Memory usage vs tons of features
  • Usability vs complexity/too much flexibility
  • Easily understood vs require 5 books + certification + hiring a consultant
  • Commercial support vs community support
  • Proven stability and acceptance vs the unknown
  • etc.

There are simple ways to decide :

  • You have a problem to address within constraints(time, budget, etc.)
  • You try looking for tools which are particularly good at solving your specific problem and that integrate perfectly in your custom infrastructure. However, no such tools seem to exist or there's that little thing that you dislike.
  • You then look for compromises and ways to solve the issues that won't get magically fixed by the tools.
  • You don't have time to look at all the existing tools and evaluate them. You'll be selecting few tools and trying them out. Hopefully software vendors will cover the tiniest details which are relevant to your business needs, in their documentation.
  • You decide and you live with it, maybe reevaluate your decision and revise your goals, but you move forward unless you really believe that you're wrong.

It's not easy to decide in the IT world. You might get it right or wrong but you may have the power to correct your mistakes. Whatever the choice, the rational move is trying to select wisely, going forward and take responsibility.

Tuesday, July 14, 2009

Playing with OSGI and JPA

I've been writing an IRC bot for fun, but it's far from being done. My goal is to experiment with JPA in an OSGI environment.

At work, I am using Hibernate, XDoclet to generate the XML and JPA isn't coming soon :-). My last JPA application was a pastebin application, with Wicket, hibernate search, Lucene, etc.

I'm using a friend's library Jerklib with Dynamic JPA. I'm still having some minor issues when deploying but I'll probably find a solution soon.

About the application
Environment
I have a multi-project with Maven and I'm using the maven bundle plugin and I'm developing in Eclipse 3.5 on Debian testing.
I'm using openjpa , dynamic jpa and couple of other dependencies

Design overview
a) Commands implemented as plugins : The bot has a set of factoids(learn, forget, etc...). Each command gets created using a factory.

// message listener //String operation = getOperation();
CommandFactory factory = ServiceFromOSGI.getCommandFactory(operation);

// if the factory is not null, redundancy for the operation parameter
// as a factory can have multiple commands
Command command = factory.createCommand(operation);
ircChannel.say(command.render(ircMessageContext));

b) The command service listens for removal or installation of commands and updates itself.

After writing couple of "users' commands", I would need to implement some administration commands(load/unload plugins, irc specific tasks, etc.).

Problems
The dynamic discovery is failing for now, the persistence provider class is not resolved, it might just be a bundling problem for openjpa. I wrapped it myself.

Conclusion
It's strange that many open source projects still don't provide an OSGI manifest. The maven-bundle plugin is very trivial to use for maven enabled project and there's still bnd.
While OSGI is an interesting technology, I personally don't know anybody using it in the enterprise unless they are an Eclipse shop. I think that it's mostly due to
  • the lack of "OSGI enabled jars"
  • the fear that OSGI might introduce unnecessary complexity
  • the lack of step by step complete examples(if possible with screencasts)

There's plenty of documentation about OSGI and lots of successful applications(Web, Desktop) using OSGI. Hopefully my bot will be one those applications :-)

Saturday, March 21, 2009

Thoughts about JavaFX

JavaFX has the potential to become something interesting. While there are many articles written about JavaFX, I have yet to see a non trivial JavaFX application. When browsing Dzone articles, it almost looks like JavaFX is popular, while it's not.


There's no amazing UI control and I am not sure that I could code an entire JavaFX application without writing few java classes. I am not fond of applets and I haven't written any for years. JavaFX doesn't solve the "applet problem".


I don't know about any cellular phone which is officially supporting JavaFX. I am also not aware of any software vendor distributing desktop applications written with that technology.


In my opinion, JavaFX is not ready for production use. What motivated the release of JavaFX? Maybe they've been advertising it for too long and they had to release something. I'll give JavaFX probably one more year before attempting to use it.



Sunday, January 04, 2009

serialVersionUID in Netbeans

Most of the time, I use Netbeans when I have the choice. What I don't like about Eclipse and is getting me worried time to time is when the IDE freezes for a long time when you're not really doing anything.

Last week, I needed to build a simple Java project (Maven based build), about 50 000 lines of code(from sloccount). The project contains one core project and few sub projects. Eclipse took about 30 minutes to import the project and set up the classpath. That performance was achieved under a Quad Core, 2 GB of RAM, which is amazing. I had only Eclipse, Firefox and a terminal opened. I tried with both q4e and m2eclipse plugins, same results, I could hear my CPU making lots of noise. I had time to start cooking, boil water for coffee and do some other things, before the IDE was ready to use.

One of many missing features in Netbeans is the ability to generate the serial version ID for a serializable class. With Eclipse, you get the warning all the time, and you can choose between:
  • ignoring it
  • adding the annotation @SuppressWarning("serial")
  • generating the serial version id.

Available plugins for Netbeans
There are two plugins available for Netbeans, that I am aware of : UUIDGenerator and serialVersionUID generator. I only have success with UUIDGenerator (most of the time, I am running the latest development build under Linux and Windows and lately Mac OS Leopard).

Enabling Serialization warnings
Under Tools->Options->Editor->Hints->Standard Javac warnings, select Serialization. That way, you'll see a marker notifying you that you're missing the declaration of a serialVersionUID field.




Generate the serial version ID
You can generate the serialVersionUID using the shortcut Control-ALT-Z. You can copy the generated contents to the clipboard and paste it inside your class.

Tuesday, December 23, 2008

Merry Christmas

XPontus and VFSJFileChooser were released this evening. I wanted to release before Christmas! Still the same stress and anxiety before and after publishing a new version. Now, I need to start advertising in forums, etc.

The last few days, well more nights than days, have been mostly about testing XPontus installers, fixing bugs, reviewing as much code as I could.

Merry Christmas everybody and happy new year!

Tuesday, November 25, 2008

Handling database changes without complete migration

The ORM market
ORM tools are great. Products like Hibernate, JDO, JPA, IBATIS, Torque, and others made life easier for developing database enabled applications.
Using JDBC when your application is database intensive with lots of table can be lots of work especially if lots of your existing code base doesn't provide some DAO classes.
Usually in ORM tools, you map a set of fields to some columns, using XML or annotations, and you're done.

Most J2EE and core Java developers have faced database changes and migration issues at least once. The problem is pretty crucial when your database model is shared by other applications which can't be upgraded(for many reasons).

The concern
  • How to handle database changes which keep happening?
  • Should/Could you stop providing backward compatibility?
  • Is upgrading the database model your only solution?
The application history
  • You have an existing application with a model which has been designed carefully and everything is going well.
  • You have a server side application with a database model and client applications with the same database model as the "main server".
  • A month or a year later, you need to make lots of changes in couple of tables, replace some primary keys, introduce some non null foreign keys, etc.
  • You were using raw JDBC mostly and plain SQL. Now, you would like to use that brand new bleeding edge technology(Hibernate, JPA, Ibatis, name it).
  • Here and there, you might have been using a very old ORM tool which was convenient at the time and is still getting the job done.
Constraints
  • You need to be able to support simultaneously clients(applications) running older and newer versions of the database schema.
  • You cannot force the customer to upgrade for many reasons(hardware dependencies, partner application compatibility, the customer doesn't want to, etc.)
  • You need to keep adding new features which might involve altering again the existing schema
  • Your table contents are now messed up, invalid or irrelevant values here and there because the database column has a "NOT NULL" property.
Possible solutions
  • One might be tempted to maintain different versions of the same database, but let's say I have 100 versions since 1994.
  • Ok, let's use JCR to provide another abstraction level, maybe checking a node property before deciding which class to map, overkill in most cases?
  • "Dear customer, please, upgrade and buy the new pack to be able to use that version which also provide bug fixes and new features"
  • Hum... last resort "Dear customer, you should upgrade because that X, Y, W feature fixes lots of serious security holes which will affect your network"
  • Ok, from now on, every table will be like a key-pair, probably not very wise most of the time, especially if it will involve rewriting most parts of a huge application.
The problem is here, a fix must be delivered!
What I would probably do is :
  • Stick with raw SQL and migrate ORM mappings to JDBC, as needed(if the ORM tools cannot ommit fields), to ignore some properties depending on the client database version. I can insert some dummy values when I have no choice when dealing with "old software clients".
  • Use native SQL queries and JDBC only
  • Use named SQL queries with binding and anything tool that supports it Hibernate, Ibatis, a resultset handler from JdbcTemplate or DbUtils, etc. Some dummy data will need to be inserted when not available(new non null columns).
  • If the problem gets out of hand, way too many changes, I'll probably want to use a non relational database and handle relationships myself(An object or XML database might do, but might not scale)
  • Another solution, would be JCR. I messed with JackRabbit once, and the pain was brought. Performance, concurrency and the API probably improved since then.
I would definintely try to avoid running multiple database versions at the same time. You can easily go from 1, 2 versions and then reach 100.

What would you developers do in such a situation?

Sunday, November 16, 2008

JDK7 changes

I had a surprise this morning while playing with System.getProperties. I am using JDK7 and displaying the system properties in a Swing JTable.
When I don't specify the number of columns I get a null pointer exception. It happens when populating the array contents, not at initialization.
This will throw a NPE:

data = new Object[NB_ROWS][];

This will not

data = new Object[NB_ROWS][NB_COLUMNS];

Code excerpt

public JavaEnvironmentModel()
{
Properties envProperties = System.getProperties();
NB_ROWS = envProperties.size();
data = new Object[NB_ROWS][NB_COLUMNS];

// for google blogger parser, no generics(Entry)
Iterator it = envProperties.entrySet().iterator();

for (int i = 0; it.hasNext(); i++)
{
Entry entry = (Entry)it.next();
data[i][PROPERTY_COLUMN] = entry.getKey();
data[i][VALUE_COLUMN] = entry.getValue();
}
}

Monday, September 01, 2008

Drinking a huge cup of Java

I am working again on XPontus XML Editor. I believe that I'm ready to go for another round.

I am happy to see that there are so many people using the software. Since the intial XPontus release, there are about 10 000 official downloads from Sourceforge and probably 12 000 from other sites grabbing the files directly by HTTP. I didn't expect such a thing at all and it gives me energy to work again on the application.

Here are the main things that I learned since the XPontus inception:
  • Provide a project roadmap even if it's ambiguous or you won't do anything listed :-)
  • Don't use build tools such as Maven if you expect lots of people to contribute to a project, use a simpler but powerful tool such as Ant.
  • If the component is has a public API, finish writing all the documentation before releasing: 20 bugs+good documentation is better than 5 bugs + no documentation, there will be bugs anyway.
  • Advertise a project enough but not too much, people will expect the application to be at the best commercial level even if there are only 2 or 3 people working on the project.
  • Don't assume you know what you're writing because you do code similar things often, read books or articles about the subject whenever you can.
  • Don't try to make a big application without taking time to do it well, or as well as possible
  • Try to think more like a user or a client of an API, rather than a programmer. The application is for users at the moment you distribute it.
  • Make it look good and then make it work : you love what you see and then you love what's inside.
  • Don't necessarily provide many features, few working features are better than a zillion of unstable features.
My goals are simple for the next release:
  • The application will probably be lighter and faster (java reflection abuses, bad programming, race conditions, etc.)
  • Partial rewrite and more use of design patterns(without trying to recognize them everywhere though! ).
  • Fix the current bugs, usability/stability issues. No new features except maybe XPath2, XQuery. VFSJFileChooser will be introduced in the release as an optional plugin.
  • New, simple but powerful API : If you explain the components relationships and the logic of the application, it should almost sounds like common sense, not magic or absurd.
  • One should be able to reassemble, disassemble or extend XPontus without much effort. It looks difficult though, how can someone integrate very easily an application that uses a plugin system?? Last time I integrated parts of JEdit into an application I won't say it was too tough but it wasn't that simple even if I believe that JEdit modules are well written most of the time.

Friday, August 15, 2008

VFSJFileChooser 0.0.3 released

VFSJFileChooser was released today after some additional tests. Nothing much to say, I guess I'll wait for comments.

Tuesday, August 12, 2008

About VFSJFileChooser 0.0.3

I guess I'm ready for the third release of VFSJFileChooser thanks to Stephan Schuster. He helped a lot for that release(bug reports, patches, suggestions). I'll probably release tomorrow after few tests.

Here is the changelog:
  • One noticeable feature is speed :-). VFSJFileChooser was too slow I.M.H.O.
  • Navigation icons are "always" visible now. They didn't show when the java look and feel set, didn't derive from MetalLookAndFeel. I borrowed some icons from Tango and famfamfam which are now the default icons used.
  • Bug fixes for directory selection among other things
  • The VFSUtils class supports the methods setFileSystemManager and setFileSystemOptions. You can set those values at anytime. when the VFSJFileChooser class is instanciated, it checks if VFSUtils has a filesystemmanager set, if not it creates one. Files are always resolved with the FileSystemOptions object in VFSUtils.
  • Upgrade to webdavclient4j (http://webdavclient4j.sf.net) as Jakarta Slide is dead.
  • Cleaner but incompatible API (Enums instead of int fields) : I started to refractor code here and there. I am making full use of JDK5 as VFSJFileChooser is not compatible with jdk14 and older releases. Enums are introduced for few classes which breaks the API. The method setFileselectionMode of VFSJFileChooser now accepts an Enum as parameter. The methods "showOpenDialog" and "showSaveDialog" return an Enum too.
  • Sorting support : The details table has now sorting support again in the jdk5 branch. The jdk5 branch is the most up to date(patches, general improvements, etc.). The jdk5 will become the default branch. I now develop on jdk5 to ensure code compatibility.
The Windows look is still not supported. I'll look at it and see what can be done. For now, I only have my old laptop running Linux so I can't really work on it. Any help in that regard would be appreciated.

Thursday, July 31, 2008

About XPontus and VFSJFileChooser

Lately, I keep receiving questions about VFSJFileChooser and XPontus. Even if I didn't answer, I did read all the emails. I thank you all for your interest and your comments.

I have started to relocate to Toronto and I am still looking for a new job which is my primary focus right now. I am still looking at XPontus and VFSJFileChooser APIs time to time(the good, the bad and the ugly).

I intend to work again on those projects as soon as I'll become professionaly stable again.

Thank you for understanding that.

Thursday, June 05, 2008

Upcoming VFSJFileChooser release

I've been trying to make VFSJFileChooser compatible with jdk 1.5 lately. Know bugs have been fixed. There's no sorting for now in the details view, but the rest is working well.

SwingUtilities.getWindowAncestor seems buggy in jdk5 SwingUtilities.getWindowAncestor(Component ComponentThatCouldBeAFrame) seems have issues. Trying to open the file dialog was throwing null pointer exceptions in jdk5. I needed to make another check to see if the component is a frame before creating and displaying the file chooser dialog with jdk5.


Window window = SwingUtilities.getWindowAncestor(parent);

if (window == null)
{
if (parent instanceof Window)
{
window = (Window) parent;
}
else
{
window = new Frame();
}
dialog = new JDialog((Frame) window, title, true);
}

else if (window instanceof Frame)
{
dialog = new JDialog((Frame) window, title, true);
}
else
{
dialog = new JDialog((Dialog) window, title, true);
}

I would like to avoid maintaining 2 branches if possible. There are lots of things that are easily done with jdk6 whereas in jdk5 additional classes are necessary.

Monday, May 19, 2008

OSGI bundles packaging and deployment

I created my first non trivial swing application based on OSGI. I deployed it on Apache Felix and Knopflerfish for testing purposes.

The swing application has about 130 classes, not huge classes. I tried to make a good design using couple of interfaces with some abstractions(docking framework abstraction, file system abstraction, gui components abstraction, plugin manager abstraction, etc.). After few days, I was satisfied with the design and started coding few concrete classes. I made sure that most of the code could be reused quickly in a non-OSGI environment.

In 4 days, I finished programming the core of the application. The only thing left was the gui main window. I wanted to use a docking framework(LGPL, BSD or Apache License).

Using docking frameworks such as MyDoggy or Flexdock in an OSGI environment looks complicated. Most of those libs make some static calls while trying to resolve images or configuration files. Sometimes some properties or other resources are stored in the META-INF folder of the jar files.

MyDoggy
I was surprised to see that, as the library wasn't finding its default configuration file(from the classloader), it was looking for it in my home folder. There's no way to set the default properties using a static method without messing with the source code of MyDoggy (or maybe I didn't see a way).
With Apache Felix I couldn't import sun.awt package used in MyDoggy but I was able to do it with knopflerfish.

Flexdock
With Flexdock, I had an infinite loop, an exception which was thrown all the time, preventing the program to run. It was complaining about not being able to create an instance of the persistencemanager or something like that. Must have been some class loading issues using reflection calls.

I decided to use few JSplitPane at last and I could see the main window of the application, after few hours spent looking into those docking frameworks source code.

To test quickly I was using Apache Felix(embedded) in the application. I had my activators written but no OSGI manifests yet. Later I saw the bundles issues. I didn't want to embed some dependencies directly in my bundles. So I started browsing the web for "osgi bundles" and chatting on IRC. Some guys told me to look at Eclipse Orbit.

Eclipse Orbit is a community effort to create OSGI bundles for common third party librairies. It's a lot of work. I packaged few libraries and it took a bit to import and export the right packages.

The last thing left before going on with that swing application, is to add some listeners so that when a bundle is removed/updated, the GUI and some non visual parts are notified to update themselves.

Wednesday, May 14, 2008

What makes an API great?

After few years of Java programming, I improved slower than I expected but still... When designing complex software which needs to be reused, I still find it difficult to make quick and "good" choices without adding too much complexity.

In the last branch of XPontus XML Editor(major refractoring), I had a dilemma:
  • Release soon : couple of patches and dirty classes which do the job
  • Wait 4 or 5 months to be ready : clean up the code, perform thorough testing, remove unused classes, add or redesign interfaces, etc.
I choose to release early and fix what I could see or had time to fix. One month after the release, I was like "why did I do it that way? what is that useless piece of code doing over here, etc."

IMHO, an API is great when it's
  • simple
  • useful
  • flexible(without adding too much complexity when it's unnecessary).

I tend to prefer APIs which expose few interfaces, abstract classes and some concrete classes. Complex applications APIs without/with few interfaces, are somehow difficult to maintain, refractor, make evolve.

Monday, May 05, 2008

Playing with Apache Felix

I'm trying to learn more about OSGI and become proefficient with it quickly. Neil Bartlett is writing a book about OSGI. It's available for free but it's not completed yet.

I looked at IPOJO from Apache Felix and managed to create a simple application with it. I think I'll start with plain OSGI programming first. Once I get it right, it will be easier to know what IPOJO or other tools can do for me and when it's better not to use them.

For example to build a simple GUI with plugins support using OSGI, the only thing I need to do if I understand, is :
  • Create few services, one can think about them as extension points
  • Create BundleActivators for each plugin
  • Register couple of services and use some ServiceTrackers
  • Layout and display your GUI application when all the bundles are activated
  • Launch background services if their startup needed to be delayed
I downloaded the SIP communicator's code. It's an audio/video Internet phone and instant messenger using Apache Felix. The graphical interface is nice and the code is "clean enough", quite good IMHO. I found a little bit strange/unconventional the way they package bundles. It seems that they build bundles from some packages/classes using an Ant build script, in a single project. I believe in an IDE it would look like a project with multiple source folders and a jar target for each source folder.

In XPontus XML Editor I have about 18 plugins which could become bundles. I started cleaning up some code. One shall never hurry too much to release, patch code here and there, leave too many unused packages, because the pain comes soon enough when you need to do some refractorings... .

In XPontus, I have 1 master project and about 30 sub-projects. Well it can be difficult to manage too, but I don't have to create many ant targets/tasks to build specific jars.

Project structure overview
  • xpontus_core
  • etc.
  • indentation_plugin(dummy maven pom project)
-> xml_indentation_plugin(sub-project, maven jar project)
-> html_indentation_plugin (sub-project, maven jar project)

The annoyance with a plugin architecture is about the deployment, but mostly the packaging. Most of the time the plugin framework or OSGI framework you'll find has a console or a main class from where you can launch the bundles/plugins. Usually in a big application, you want total control and a customized behaviour which means a custom launcher to embed the plugin framework or the OSGI framework.

Let's say I have a bundle called bundle0. I created it in Eclipse, I have few jars as dependencies, etc. How do you auto-package all that with minimal effort(zip file with the bundle0.jar, a lib directory holding the dependencies)?

In XPontus XML Editor the plugins have an "Eclipse like" folder structure
- com.mycompany.plugin
* plugin.xml
* lib(folder containing the jars)

Every time I want to deploy a plugin:
  • I create a plugin folder with a unique id
  • I add the plugin descriptor
  • Create a lib folder with all the jars needed by the plugin
  • I zip the folder and it could be ready to be deployed.

Thursday, May 01, 2008

VFSJFileChooser is out

I uploaded the new release of VFSJFileChooser this evening. It will be available on all Sourceforge mirrors probably tomorrow.

Tuesday, April 29, 2008

Preparing the new VFSJFileChooser release

VFSJFileChooser will be out soon.

Here is the changelog :
  • Sort file by names : Some patches were submitted to sort file by names.
  • The "home" button will not bring you back anymore to your local home folder if you're browsing a remote directory.
  • A details view is being added as a complement to the existing list view
There are still some issues when you choose the native look and feel with : UImanager.setlookandfeel