First of all, I'd like to thank whoever stole my Blackberry that I left on the Helsinki to Kuopio train (my camera that my stepson left on the way back was returned). That dang thing never actually worked. That made me get off my butt and buy a new phone. My crackberry never worked. It crashed on the way home on the day I bought it, but I figured that was an update or something (which crashed my previous phone on its first startup without fail), but that dang thing crashed randomly all the time and often times without switching to the JVM error screen so that I didn't know it had crashed.
I thought about buying an iPhone, but I just don't want to be associated with those suckers, besides I was mad at Apple for disabling my MacBookPro from running Linux (this I fixed). Frankly Apple's advertising annoys me. I'm beyond caring about being cool. I leave being cool to emaciated 20 year olds that shop at the GAP. If I want to be that cool I'll buy my own 20 year old to do it for me, sheesh....two if I want to be doublekool. I also resent locked phones. Like I want to pay some ridiculous amount to use my phone abroad. No way dude, I'm buying a pay as I go GSM card so bite me! There is also my theory that the reason my MBP runs so hot is that Steve Jobs wants to solidify his position as Alpha male...
I didn't really think about another Blackberry. As much as I wanted to get Meldware working with it, I had enough time getting the freaking Internet to work with it. No cool telnet or ssh or whatever! All the dreams I had about checking server logs from the train never came true. So that was out. (if you don't have a dud then it should work with IMAP)
Instead I walked into the Palm store while I was in the Atlanta airport with time to kill and saw a bunch of phones that weren't locked for relatively little. With a 30 day no-risk return policy, I was doing that. The only problem was that Versa Mail was a piece of crap. It insisted on loading THE ENTIRE MAILBOX INTO RAM and thus threw an OOME since my mailbox is a few gigs over the 8mb. Today while waiting for Billy (12) to get a turn at the soccer ball, I downloaded another app and it worked with Meldware right off. I was pleased. It even let me decide not to download my whole mailbox but stick to newer mails (essential cause it couldn't hold it). The only problem is that a certain open source diva sends email in embedded apple-encoded mime format which it doesn't seem to like much.
Now I just have to find a better calendar app for it.
A few months ago I was at LugRadio Live where I attended a talk by Michael Sparks from the Kamaelia project. Kamaelia is a python-based component framework for building concurrent applications. The core of the Kamaelia system is called Axon. The main concept of Axon is the Microprocess. A Microprocess is simply a class that implements a generator method. For those unfamiliar with Python, generators are Coroutines, i.e. a method where instead of executing and returning a value when called, it returns an object that can generate values. For example the following code will print 3 integers 1, 2 then 3.
def generate_ints(N):
for i in range(N):
yield i
gen = generate_ints(3)
print(gen.next())
print(gen.next())
print(gen.next())
The interesting part of this is that each time the next method is called control is returned back to just after where the last yield was called, restoring the state of all of the local variables. It is this feature that Axon exploits to implement its concurrent behaviour. In some ways its reminiscent of Java's green threads or SEDA
One thing that really stood out about Axon, is the getting started tutorial doesn't go through contrived use cases for the framework. Instead it starts with a tutorial that walks you through building cut down implementation of the framework. By implementing the system from the ground up (albeit a very cut down one), you get a much better understanding of the system when it comes to using it. It also demonstrates that the system is built on simple clear concepts.
One of the goals for Kamaelia was to support scalable network servers (although it is much more broadly applicable), which is interesting for implementing a mail server. I decided to run through the Mini-Axon tutorial but implementing it in Java rather than Python. The first issue is that Java does not support Coroutines. It is possible to simulate the behaviour by using an inner class that stores all state as fields rather than local variables. This was the basis for my initial implementation, but the implementation was clunky and intelligent. I then stumbled upon a library called Yielder. Yielder provides Coroutines through byte code manipulation of class files. To implement the above Python example in Java:
Iterable<Integer> gen = new Yielder<Integer>() {
public void yieldNextCore() {
for (int i = 1; i <= 3; i++) {
yieldReturn(i);
}
}
}
Iterator<Integer> i = gen.iterator();
i.next();
i.next();
i.next();
To allow this behaviour the '-javaagent=lib/yielder.jar' is required so that subclasses of the Yielder class can be identified and modified. To implement Mini-Axon using Yielder a Microprocess is a direct subclass of the Yielder. The next most important class in the Axon framework is the Component. Functional areas of an application extend the Component class. In order to support safe concurrent applications Components behave according to a specific pattern, where each Component will have only a single reader or writer at one time. Each Component is initialised with a number of boxes (or queues, or buffers, or whichever term you prefer to use). In a typical situation, within the main method (yieldNextCore), the Component loops reading requests from its Inbox, processing them and writing responses to its Outbox. The Component should yield processing at an appropriate point during its execution. Components are not restricted to single inbox/outbox combinations. It is possible to implement aggregation or multicast by reading or writing from multiple boxes. Communication between Components is handled by wiring their boxes together. This can be done in a number of ways, a simple example is the a Postman which copies items from the outbox of one component into the inbox of another. It is also necessary to have a mechanism to actually run the components. This is handled by yet another Microprocess which can schedule the running of other Microprocesses.
Because everything in Axon is a Microprocess including scheduling components, there are all sorts of ways that Components can be wired together. It shows that the model that Axon uses is very flexible. I will probably do some experimentation with using Axon in Meldware. I am currently envisaging a solution using Apache MINA or Grizzly to generate events that would drive an Axon scheduler. The incoming data would be partitioned, either into commands (single text lines) or parts of a larger message request (e.g. the message part of an SMTP DATA command) and passed as messages between Components. Components would handle activities such as command parsing, retrieving mail data from the folders and the streaming the bodies of messages from the store. One of the trickier aspects of moving to an event based approach to building a system like Meldware is how transactions should be handled. Declarative transactions (such as those using in JBoss AOP) generally rely on a single thread processing the entire transaction. However if we want to move away from blocking I/O and use an event based approach, it will be necessary to have transactions that span multiple threads. To handle this case it looks like I will need to suspend and resume transactions manually via the JTA API. It should be possible to implement some sort of transactional Component that handles the suspension and resumption of transactions around the yield call. This class could be extended by Components that need transaction behaviour. How this would work with multiple components sharing the same transaction is something I still need to work through.
This is all still speculative. I am yet to implement any useful behaviour with my implementation of Axon, so I will see how it goes. There are still some bugs in the Yielder library (doesn't work with ecj and requires debug to be enabled), which I am working with the author of Yielder to resolve. If you are interested in the Java implementation of Axon it is available here.
Evolution + Freebusy is working in the HEAD. You just need to grab the JESCS plugin. There are various differences in functionality between Evolution's WCAP support and Thunderbird's. The biggest difference is that Evolution stores things offline and gets the deltas where TBird+Lightning re-gets the data every time you start it. Unfortunately, it comes at a stability cost for some reason and Evolution+JESCS is kinda buggy. For instance it only asks for "BUSY" data but if no busy data is returned (you're completely free) then it displays the same bar of "no data" as if you had no calendar or there was an error of some sort (this . We should have an early M9 build shortly but the webmail is temporarily non-functional while we make some changes (Flex build in controls suck for auto-complete and the one on the Adobe exchange blows as well) so I'd rather hold off till its working. In the meantime if you don't care about webmail you can build from the HEAD. You can probably also use the webmail.swf from M8 with a build off of HEAD and it will probably work. Happy huntings!
Screenshot of evolution running against a Meldware backend (build of the HEAD of CVS -- soon to be in first build for M9)
I'll definitely be demoing this in Philadelphia, PA tomorrow, so head to your nearest airport and drop by!
We're pleased to announce the release of Meldware Communication Suite 1.0-M8. Meldware is a multi-platform enterprise groupware package including: email (IMAP/POP/TLS/SSL), Calendaring (web/ical/wcap), graphical installation and administration. You can download it here including a webstart installation (click from your browser). This release includes numerous bug and feature changes among the highlights:
This release is really late and long festering mainly because we've been working hard on the M9 release and hadn't gotten off our duffs to make the M8 release happen :-). That was certainly a mistake on our part. With this release IMAP has really matured. Calendaring and Webmail (based on Adobe's Flex technology) are gaining fast. Progress on the graphical administration piece has been slow but deliberate.
There is a new End User Guide which administrators can point users to. The Installation Guide and an Administration Guide will be available soon. Please feel free to join us in the forums and/or on the Mail List. There is also an IRC channel on irc.freenode.net called #buni. Don't forget to come see us at the Next Generation Datacenter conference colocated with Linuxworld. I understand from various folks that "open source groupware" was completely missing from O'Reilly's OSCON last week. This is your chance to get to see stuff that is too hot for O'Reilly, especiallyNat Torkington! A complete stack of multi-platform open source email and calendaring is a reality, MS Exchange is ball and chain, free yourself and your company. Let's work together to make things better and open source look good!
We're gearing up for an encore presentation at the Philadelphia area Linux Users' Group next week and the Meldware session at the Next Generation Data Center conference in San Francisco, CA which is co-located with Linuxworld. Meanwhile a lot is happening. The first big event takes place outside of Buni.org entirely: Mozilla has released Lightning 0.5. You'll recall that Lightning provides calendar services to Mozilla's Thunderbird email client. You can grab the latest WCAP version of the Lightning 0.5 plugin here. You'll hopefully recall that WCAP is the protocol that we use to expose calendar functionality to email clients. So guys, I'm really excited about this release. Not only is it WAY prettier but it fixes some nasty little six-legged features from 0.3 (don't ask what happened to 0.4...there is no 4...why do you ask such questions?). I was so excited I had to immediately patch MCS to work with the latest version (the incompatibilities they introduced where very minor).
Then we can pop into TBird and create a new event:
And we can invite some other folks (I secretly created another user buniluni1@localhost while you weren't looking):
Who says open source GUIs can't be sexy!!! Okay the info is kind of boring because we're both free all day. Here is what it would look like if we tried to schedule another meeting (after we save this one):
One of the things I really like is that you cn move the shaded part graphically and it changes the time. Another thing I like
is that it dropped the red/green scheme. I dunno who does usability for these guys but umm... Red Green color blindess affects 7-10% of men (virtually no women). Not only that, but I'd tend to bet that the proportions are higher in those that work a lot with computers. Anyhow I thought the lightning 0.3 screen was ugly and, as a result of the color-blindness really, kind of mean (yes I can see it fine). see:
The Weekly view is also more attractive/usable:
The montly view is nicer, you can really see the 3d effect of the blue :-)
And the day view:
Okay so I try and be ecumenical to Linux vendors (but love of Ubuntu comes out) and clients...but TBird+Lightning are my favorite and the new TBird 2.0 is much faster with the IMAP. However, Evolution tends to bug me. While its WCAP implementation is more sophisticated and does smarter things with offline views...Evolution is HORRID to develop for because if you get something wrong it crashes. Worse....it hangs. Not only that but sometimes when you kill it....it kills GNOME or at least your task bar. (No KDE-wankers bother me, I've never been sold on KDE from the QT-license fun to now...push your evildoer UI on some other unsuspecting open source villan). Not only that but they just caught the buffer underflow error in their IMAP that we found while developing Meldware...but they only got 1 and haven't found the corresponding overflow! Great example of why we chose the technologies we did for Meldware :-) -- we CAN'T code underflow/overflows :-). Yes, I'm sure Outlook is even worse and Apple's Mail.app has the worst IMAP ever. That rant aside, I've code in HEAD that integrates with Evolution:
weekly
monthly
monthly
While the calendar screens are nice, the setup is akward and the create event is kind of ugly (and the screens are not child windows of the application which is REALLY annoying):
I should have the freebusy support for Evolution fixed in the head shortly, but it is less attractive as well:
Note all the extra events are because Evolution caches them offline (a good thing) and just checks for recently modified/deleted (also good) but offers no easy way to resynch if you like drop the DB during development (pain for me, likely irrelevant to you).
Anyhow, my personal preferences aside, the complete open source groupware stack is a reality today with TBird/Lightning and Meldware (albiet you need to build HEAD if you want to use 0.5 ;-) ) and wait till you see what we're cooking up next!
BTW thanks to Sun for writing the plugins to connect Meldware Calendar to Evolution and Thunderbird. We might have done it without you but boy it would have taken a lot longer!
Some of the guys at SUN have been working on performance testing with Glassfish and PostgreSQL. Some of the results are pushing towards those achieved with an Oracle database. Postgres is currently the recommended database for use with Meldware, mainly due to its excellent BLOB support. BLOB support is something that very few database do well. Oracle is one of the few that implement BLOB locators properly (Postgres uses a paging mechanism). Unfortunately this is an area where MySQL does very badly. In MySQL the driver will either load all of the data into memory and do a single DB write (not particular useful for a system that needs to be scalable w.r.t memory) or it provides "emulated blobs" which use a series or prepared statements that use concat to add the data into the blob. Unfortunately this shifts the memory problem to the database and runs into some O(n^2) performance issues. In fact to support MySQL in Meldware we had to implement our own paging algorithm.
Its great to see Postgres general DB performance look so good. Lets hope it continues to improve.
I going to speaking at LugRadio Live 2007. If you are in the UK head over to Wolverhampton this weekend (7th-8th of July). There are load of great speakers and its only £5. See you there!
You may have noticed that contacts have been removed in the M8 build series. I didn't really care for how the state of the present "Contacts" code worked. For one, it was only available via the web client and for two it was kind of klunky anyhow. Moreover, in Calendar it was intermixed with the concept of "account". So I've been learning LDAP (a feat unto itself) and integrating OpenDS. Initially, I was planning in integrating Apache Directory (mainly because I know Alex Karasulu, the founder), but a number of things about OpenDS recommended it. First off, their setup was a lot more refined than Apache Directory server. Second off, out of the box at least it is noticeably faster. Lastly, the documentation is clearer and the code really easy to work with. Not that ApacheDS didn't have its better points. OpenDS has a very quiet list of mostly sun employees, so its open source in license only really. They need to make more of an effort to make design decisions in the open. The IRC channel is completely dead. ApacheDS has a very active and helpful community, but the configuration and setup is relatively primitive. I love the ApacheDS tools for Eclipse, which I'm continuing to use with OpenDS.
The thing I love most about OpenDS is how they handle configuration. They have a bootstrap which is an LDIF file. The file is editable by humans. This is loaded at startup and becomes a set of LDAP entries, that can be modified (and are written by the server back out to the same file). I intend for this to be a future direction for Meldware. 1.0's administration DumDOM tool is a bit of a kludge and will be difficult for us to maintain in future releases and is entirely dependent on JBossAS. For a post 1.0 release, I'm thinking we can use OpenDS and store the configuration tree in LDAP, possibly using Mike's beloved Guice. Presumably we can also abstract this to allow other LDAP servers to be used as well. I've left us a lot of room so that at any point we can switch default LDAP servers or include both or whatever. Mainly I guess it will depend on how OpenDS and ApacheDS continue.
Ahh the future, always a favorite...but for the present, check out the fixes Hoshi has been making for the Web client. Also check out how it now supports both calendaring with the new Timepicker and Scheduling (aka freebusy). IMAP is faster than ever and with spam protection. The addressbook will be back in M9 only it will be replicated to both the web client and Thunderbird. I'm also working on making sure that WCAP works as well in Evolution and Outlook as it already does in TBird. Freedom is good and it starts here. Let's get it started!
The majority of my time on Meldware these days seems to be spent on our IMAP implementation. IMAP is a funny spec, every time I think I have a handle on it I discover another interesting quirk. Recently I have been trying to understand how to handle multi-accessed mailboxes. I.e. mailboxes that can be access by multiple clients at the same time. The behaviour in this situation is defined in a different rfc to the main IMAP4 spec.
The trickiest part of this is how to handle mailbox expunges. An IMAP server is supposed send updates of changes to a mailbox to any client that has that mailbox selected, except expunges. Expunges must not be sent unsolicited nor when a FETCH, STORE or SEARCH is executing. RFC 2180 specifies 4 different approaches to supporting expunge. Of the 4 approaches only 2 are worth considering.
Prevent EXPUNGEs when more than 1 client has a mailbox selected
Wait until appropriate time before showing other clients that the messages have been removed
Initially I intended implementing the first option. In order to do this I needed a locking mechanism that supported shared locks and upgrading of locks from shared to exclusive. Quite easy with the new Java concurrency API, well that is until we want to support clustering. Two quite obvious approaches jump out. Firstly do something in the database, which is okay until you need to deal with nodes that may die without cleanly removing their locks. We can work around this by applying timeouts to locks. Another option would be use JGroups and do implement some form of clustered locking manager. I rejected this, after trying to bend my mind round all of the possible race conditions that could occur in such an implementation.
After considering this for some time, finally the penny dropped. What I should do is implement the second behaviour using a "version" number to determine which messages are currently visible. In the latest implementation, the Folder (our entity representing an IMAP mailbox) holds an expunge version number. We also maintain an expunge version value on the FolderEntry. A FolderEntry represents a many-many relationship between Messages and Folders. Unlike other mail servers, we don't duplicate emails when sending to multiple receivers on the same server. On initial delivery the FolderEntry's expunge version is set to Long.MAX_VALUE (2^63 - 1). When a client selects a mailbox it uses the expunge version to determine which messages are visible SELECT * FROM folderentry where expungeversion > :folder_expunge_version. When a client decides to expunge a folder it increments the Folder's expunge version and sets the expunge version of all of the deleted FolderEntries to that value. Other clients will not see the messages that have been deleted, until they decide to refresh their instance of the Folder entity.
The only side effect of this solution is that we can't immediately delete the actual rows from the database. When a message is expunged we set an expunge date on the FolderEntry. With both IMAP and POP we set a timeout value for the connection, thereby ensuring that POP and IMAP clients are never more that about 30 minutes out of date with the current mailbox state. We will need to have some periodic mechanism for clearing down expunged messages. Probably after they have been expunged for more than 24 hours.
I have made available a 0.4 version of Panto, Buni's fast mime parser. The jar file in only 30K in size and has no other dependencies. It makes use of the Simple Boyer-Moore string matching algorithm. Compared to the lastest version of Apache Mime4J it is 40 times faster on large messages (~2MB).
Today you'll find a new build of Meldware Communication Suite. This build unifies security/profile within Meldware and gives the Web Calendaring the ability to do scheduling. The build may very well be marked M8 proper.
This is the first time advanced scheduling (aka Freebusy) has been available to all free and open source software user enterprise and small whether they use webmail (above) or Thunderbird + Lightning/wcap plugin below.
Meldware is now on track with its advanced mailbox features (including an alpha of distributed IMAPIDLE support) and scheduling features to replace entrenched proprietary solutions.
We do love our friends at MySQL, but frankly their BLOB problem (search on ByteArrayStream, yes the problem persists and no it isn't just the driver) and somewhat unfortunate locking policy does makes the elephant roast the dolphin.
While we've gone out of our way to make this perform as well as MySQL is able, PostgreSQL is certainly the more powerful and performance choice. Therefore it is Meldware Communication Suite, Thunderbird+Lightning, Linux (or say OpenSolaris) and PostgreSQL that forms your open source power-stack that frees both your Inbox and calendar (even if it remains very busy).
This Saturday (19th May) I am heading over to Manchester University to give a talk at ManLUG on Meldware. This will be the first of my contributions to our LUG Tour. I have also had a talk accepted for LugRadio Live 2007.
I am scheduled to speak at 3pm on Sunday afternoon. I expect I will be addressing lots of people on the tail end of some nasty hangovers.
Like any half-way decent mail server, Meldware needs a SPAM filtering solution. There are a number of good Free and proprietary solutions for managing SPAM floating about. For Meldware I wanted something that was Java-based and embeddable, i.e. a library rather than some external system. That lead me to jASEN, which appeared to meet most of our requirements. After getting a few unit tests working and writing some transformation code from our email structures to those used by jASEN, I proceeded to deploy it to JBoss. That is where I ran into problems. The jASEN library has an interesting configuration mechanism. There is a central XML file that declares the configuration for system and specifies the plug-ins. Each plug-in class has its own properties file which is loaded within its init method. The property files would be loading by getting the resource's location from the classloader as a URL, and transforming that into a file name. This caused the following problems.
JBoss was unable to locate the file due to the URL -> file name transformation.
The configuration files could not be placed inside of a jar file, even though they were mostly boiler-plate.
It would be difficult to integrate this configuration mechanism into our administration tool
Despite all of the this jASEN contained a collection of useful scanning algorithms. Rather than throw the baby out with the bath water it set about modifying jASEN so that its configuration could be externalised. The code appeared to be crying out for some form of dependency injection. To implement this I decided to have a whack at using the new Google Guice dependency injection tool.
This proved to be the way to go. The majority of the configuration information was simply binding interfaces to their implementation. Guice takes the approach that most dependency injection configuration is boiler plate, therefore the majority of the work is done in Java rather than XML (or some other configuration format). Thereby adding an element of type safety to the binding. To inject a value into a class using Guice the @Inject annotation is used. Guice then uses the type of the value being injected and any annotation that is applied to that value (constructor/method parameter or field). To specify the bindings, I had to create a Module implementation. Assuming I had a class that required access to a probability calculator.
First I have a probability calculator interface and implementation.
public interface ProbabilityCalculator {
double calculate(double[] probabilities, int start, int end);
}
public class CompoundCalculator implements ProbabilityCalculator {
...
}
And a class that uses the calculator.
public class AnomalousCharacterScanner implements JasenPlugin {
private final ProbabilityCalculator calculator;
public AnomalousCharacterScanner(ProbabilityCalculator calculator) {
this.calculator = calculator;
}
}
Then I can write the configuration module to bind the implementation of the ProbabilityCalculator.
public class JasenModule extends AbstractModule {
public void configure() {
bind(ProbabilityCalculator.class).to(CompoundCalculator.class).in(SINGLETON);
}
}
Then I can create an injector which gives me an entry point into my application.
Injector i = Guice.createInjector(new JasenModule());
AnomalousCharacterScanner acs = i.getInstance(AnomalousCharacterScanner.class);
I have used the SINGLETON specifier, because I know that the CompundCalculator is stateless and a single instance can happily be shared among many classes. Note that this is not a singleton in the GOF-style pattern, but a single instance within the scope of the injector that I created.
Guice also has the concept of providers, which are like factories and can be used to create instances. I have a JasenMap object that holds a mapping of all of the spam and non-spam text tokens. This is created using a loader class, however I can isolate the loading of the map using a provider.
First I need to write a provider for a JasenMap, which assumes that the JasenMap is just a serialized Java object
public class InputStreamMapProvider implements Provider {
private final JasenMap map;
public InputStreamMapProvider(InputStream in) {
ObjectInputStream oin = new ObjectInputStream(in);
map = (JasenMap) oin.readObject();
}
public JasenMap get() {
return map;
}
}
I have a class that needs the JasenMap to be injected.
public class RobinsonScanner implements JasenPlugin {
private final JasenMap map;
@Inject
public RobinsonScanner(JasenMap map) {
this.map = map;
}
}
And I bind the provider in my JasenModule implementation
FileInputStream f = new FileInputStream("/path/to/map/file");
Provider p = new InputStreamMapProvider(f);
bind(JasenMap.class).to(p);
The type safety and simple binding strategy the Guice is useful, however some configuration information simply has to be specified at runtime. The simplest way to implement this is using the @Named annotation provided by Guice. The mechanism is quite simple. Specify the Named annotation and a string to identify the a value that needs to be externally configurable. The optional = true means that this configuration value can be excluded. I have specified a default value for the field.
public class AnomalousCharacterScanner {
@Inject(optional=true)
@Named("AnomalousCharacterScanner.max")
private float max = 0.9f;
}
Specify the value in a properties file.
AnomalousCharacterScanner.max=0.75
Bind a properties object using the Guice Names interface, from within the JasenModule.
InputStream in = new FileInputStream("/path/to/config/file");
Properties props = new Properties();
p.load(f);
Names.bindProperties(binder(), config);
Guice will coerce the string into a class, enum or primitive value for you, but it will not coerce into any other types. I needed a way to convert some comma delimited strings into string arrays. To do this I need my own implementation of the Named annotation and a custom provider.
private class MyNamedImpl implements Named {
public Class extends Annotation> annotationType() {
return Named.class;
}
final String value;
public MyNamedImpl(String value) {
this.value = Objects.nonNull(value, "name");
}
public String value() {
return this.value;
}
public int hashCode() {
// This is specified in java.lang.Annotation.
return 127 * "value".hashCode() ^ value.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof Named)) {
return false;
}
Named other = (Named) o;
return value.equals(other.value());
}
}
private static class ArrayProvider implements Provider {
String value;
public ArrayProvider(String value) {
this.value = value;
}
public String[] get() {
System.out.printf("Converting %s\n", value);
if (value != null) {
return value.split(",");
} else {
return new String[0];
}
}
}
I can then bind my properties.
Properties props = new Properties();
props.load(f);
for (Map.Entry
It is a little bit hacky in that it will create and bind providers for some fields that aren't actually string arrays, but this doesn't cause any problems for Guice. It will only use the provider for values that are actually are typed as string arrays. It will suck a few unnecessary CPU cycles, but it is unlikely to cause a performance hit.
All told I am a big fan of Guice. I like its type safe binding, speed and simplicity. There are a load of other features I haven't touched on. E.g. method interception to do transactions, etc. The only feature I would like to see added at this point is a way to add custom coercions from strings into other objects, e.g. arrays, URLs, etc.
We now have SPAM filtering built into Meldware using our own forked, Guice-ified implementation of jASEN. It integrates with Thunderbird quite nicely. It will be a feature of our M8 release