The Source for Java Technology Collaboration
User: Password:



Michael Nascimento Santos's Blog

Open Source Archives


Desktop development made easier with genesis

Posted by mister__m on June 21, 2007 at 02:43 PM | Permalink | Comments (4)

It's been quite a while since the last time I mentioned genesis here. One of the reasons is I've been working on it a lot and there isn't much time left to blog about it. Hopefully I will be able to do so more often.

We have just released genesis 3.0 after almost two years and a half of development. genesis is all about making the development of enterprise desktop applications easier. To accomplish that, genesis provides UI-related features and also a neat way of building and integrating with the back-end of your application. For now, let's focus on the desktop itself.

genesis 3.0 comes with full support for Swing, SWT and Thinlet. It supports binding, validation, actions and conditions. Let us say that for the desktop it tries to address nearly the same problem space as JSR-295 (Beans Binding), JSR-296 (Swing Application Framework) @Actions and JSR-303 (Bean Validation), but there are enough conceptual differences between them (besides supporting SWT and Thinlet out of the box, of course). I've already explained the basic UI binding functionality last year, so here I will try to show why the genesis approach is better.

First, genesis works with an UI model, instead of plain binding. This means your JavaBean represents the UI data plus the presentation logic behind it. It makes your presentation logic UI toolkit-independent, testable and self-contained. It also doesn't require PropertyChangeListeners at all. Consider the most basic binding example in genesis docs:

@Form
public class LoginForm {
   private String user;
   private String password;

   public String getUser() {
      return user;
   }

   public void setUser(String user) {
      this.user = user;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   @Action
   public void login() {
      System.out.println(getUser());
      System.out.println(getPassword());
   }

   @Action
   public void clear() {
      setUser(null);
      setPassword(null);
   }
}

If you were to do the same with JSRs 295 and 296, you would have to create a JavaBean with PropertyChangeListener support, fire property changes on setters and also create two @Action methods in your view that access your bean. As the number of properties, beans and actions involved in a view increases, your code with genesis would still be self-contained and testable, while JSR-295 would require individual bindings to be produced and your actions would be tightly coupled with Swing, manipulating your beans as value objects.

genesis also comes with some unique features of its own, such as declarative conditions. Let's analyze the classic dependent comboboxes issue: whenever the selected country changes, the state list should be reloaded. Here is what it takes to implement this with genesis:

@Form
public class StateSelectionForm {
   private Country country;
   private State state;

   @DataProvider(widgetName="countryTable", objectField="country")
   public List populateCountries() {
      return // business logic to retrieve countries
   }

   public Country getCountry() {
      return country;
   }

   public void setCountry(Country country) {
      this.country = country;
   }

   @DataProvider(widgetName="stateTable", objectField="state")
   @CallWhen("genesis.hasChanged('form:country')")
   public List populateStates() {
      return // business logic to retrieve states
      // Notice getCountry() will return the selected country
   }

   public State getState() {
      return state;
   }

   public void setState(State state) {
      this.state = state;
   }
}

So genesis will automatically invoke the stateTable @DataProvider whenever the selected country changes.

There are many other features and things to explore and I hope I can show them here in the next few days. The Brazilian Portuguese users list is quite active these days and there is of course an English users list. Check out genesis and let me know what you think.

A public pledge to NetBeans

Posted by mister__m on May 07, 2007 at 04:55 PM | Permalink | Comments (8)

I could not be more disappointed after attending the Swing GUI Building With Matisse: Chapter II presented at NetBeans. It's not a problem with the Swing Application Framework or the NetBeans tooling; it's a problem with freedom of choice, vendor lock-in and a close-minded approach, not community-like friendly by the NetBeans guys.

I hate to make such issues public, but I've been trying to solve this in a civilized way for a year. Almost two years ago I've filed an issue about making Matisse extensible. It was ignored for a long time, but over time, I become hopeful again since the NetBeans roadmap indicated that Matisse would support binding for NB 6.

Over six months ago, I've emailed Tomas Pavek, the NetBeans Matisse lead developer (as far as I know) and Scott Violet, who was the spec lead for JSR-295, Beans Binding, to make sure Matisse implemented it as an abstraction, so it was possible to use Matisse with other binding technologies, such as JGoodies Binding or genesis. This email resulted in a thread in which I explained to Tomas what was needed in the API in order to support other frameworks (basically, abstracting how you interact with the binding "metadata"/API and providing extension points to generate the specific binding API code).

One thing that limited my analysis before was the fact there was no publicly accessible code for JSR-295 or the NetBeans support and I was told that a public preview would be available in January. Well, as most of you know, it has only been made available a couple of days ago.

Today, during the session, I mentioned that while I actually found the tooling fantastic, many folks (just for an example, read this) have all kind of issues with Beans Binding and whether NetBeans would allow its users to work with other binding frameworks, by providing a API that is extensible. While Shannon Hickey, the new JSR-295 spec lead, understood it's not like I'm bashing his work, the NetBeans guys simply said they just want to support the standard. What does it mean to you?

  • If you don't believe that beans binding as a concept is the correct way to make GUI development easier (genesis does what we call "UI binding", which is different, much simpler and straightforward), you're lost
  • If you are working with Java 1.4, sorry; NetBeans will never have a decent solution for you since JSR-295 is targeted at Java 5
  • If you want to use a solution that already works with other UI technologies, such as SWT, sorry, no donut for you
  • If you want to keep the binding logic apart from the UI logic, there is no way
  • If you have an existing project or someone pushed another binding solution in your project, you will actually have to branch Matisse and override it to support it

Obviously, the first answer would be: "hey, but about maintainance?" but no one is asking for a JGoodies or a genesis binding module to become part of NetBeans; I am just asking for the possibility of doing so if needed without branching Matisse. And, heck, I've read Matisse's code: the kind of support I'm asking for would require just a few days to extract the dependencies and create an abstraction based on interfaces and going through the API review process, that would allow people with enough knowledge about other binding solutions to validate it. That is it.

So, to sum up, what I'm complaining about here:

  • Sun has always promised us we would have freedom of choice, but NetBeans will get us locked in beansbinding (vendor lock-in)
  • NetBeans should listen to the community and work with the community. For years, there weren't a standard approach for binding and there are tons of folks working with other frameworks right now that could benefit from having a plugin that allows them to work with their current binding solution.
  • If NetBeans wants to become supported by the community, it shouldn't bite the hand of those that helped to evangelize it. I have been actively promoting NetBeans in Brazil for a few years now, both as a consultant and as a SouJava organization member. I just want to help NetBeans to help its users, but apparently NetBeans developers want to push Sun's solution down our throats.

Here is my request: show me I am wrong. Show you can listen to the community. Show me freedom of choice is not just some marketing rubbish. Please.



It's high time: a Date and Time API for the Java SE Platform

Posted by mister__m on February 09, 2007 at 08:59 AM | Permalink | Comments (7)

A few times in the past I've considered writing a blog entry summing up all the problems with Date, Calendar, TimeZone, DST rules and other JDK related classes. If you think these APIs are simple, functional and do not cause any harm, believe me, you really haven't done anything trivial with dates. Besides the classic "days are 1-based, month are 0-based" issues and the lack of many major concepts, such as date without time, any date/time calculation fails miserably when it includes a DST start or end date. There are simply too many issues with the current API to list here.

However, the point of this entry is not to bash the current Java SE API, but rather to talk about JSR-310: Date and Time API. As stated in the JSR, it "will provide a new and improved date and time API for Java. The main goal is to build upon the lessons learned from the first two APIs (Date and Calendar) in Java SE, providing a more advanced and comprehensive model for date and time manipulation."

Our main inspiration will be Joda-Time, a great open-source library originally created by Stephen Colebourne (who will be co-leading the JSR), that you should definitely use today to deal with date and time. We won't simply rename Joda-Time and bless it with the JCP approval stamp. We actually want to learn from it, use Java SE 5 features to design an easier-to-use API, remove all deprecated, complex and not mature enough features and also consider addressing a few issues currently not solved by it.

If you want to help us, join the jsr-310 java.net project and subscribe to the mailing lists. If you think you are an expert on the matter, consider joining the expert group. We intend to run this JSR as transparently as possible though, so your voice will be heard even if you just join the java.net project.

Swing made easy with genesis

Posted by mister__m on August 25, 2006 at 10:43 AM | Permalink | Comments (13)

Swing was always known as a powerful, highly configurable UI toolkit. However, not much longer after it was born, it was also regarded as a slow, hard to learn, confusing, hard to program toolkit. Sun first started working on performance and Swing became faster and lighter - if you only knew how to code make a GUI with it. Designing some interfaces could take hours (or days) and since there are many ways of accomplishing (almost) the same thing in Swing, developers would usually get confused or pick the wrong road. Visual designers such as VEP and later Matisse came and made it simple to design the GUI. However, working with Swing still required understanding models, writing listeners and dealing with the many choices offered by the API.

An easier programming model was needed and then binding frameworks started to appear. genesis was born two years ago and it has been supporting GUI-toolkit independent binding for more than a year and a half now. At first, only Thinlet was supported and we were always asked about when it would support Swing. Well, since the beginning of the year a Swing binding has been implemented and now it has finally been released.

What makes the binding implemented by genesis unique is that it doesn't require you to use any "proprietary" components and it doesn't require you to code listeners (neither in the interface nor the JavaBean). So you can design your interface using Matisse, write your JavaBean class and just use a couple of annotations to bring it to life. Let's see how it works in practice. Let's say we would like to implement a login use case. We could code the UI handling JavaBean, called a form, like this :


@Form
public class LoginForm {
   private String user;
   private String password;

   public String getUser() {
      return user;
   }

   public void setUser(String user) {
      this.user = user;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   @Action
   public void login() {
      System.out.println(user);
      System.out.println(password);
   }

   @Action
   public void clear() {
      setUser(null);
      setPassword(null);
   }
}

And bind it to a Swing UI like this:


@ViewHandler
public class LoginSwingView extends JDialog {
   public LoginSwingView() {
      super(new JFrame(), "Login");
      initComponents();

      SwingBinder binder = new SwingBinder(this, new LoginForm());
      binder.bind();
   }
   
   private void initComponents() {
      getContentPane().setLayout(new GridLayout(2, 1));

      JPanel dataPanel = new JPanel();
      dataPanel.setLayout(new GridLayout(2, 2, 5, 5));

      JLabel labelUser = new JLabel();
      labelUser.setText("User");
      dataPanel.add(labelUser);

      JTextField user = new JTextField();
      user.setName("user");
      dataPanel.add(user);

      JLabel labelPassword = new JLabel();
      labelPassword.setText("Password");
      dataPanel.add(labelPassword);

      JPasswordField password = new JPasswordField();
      password.setName("password");
      dataPanel.add(password);

      getContentPane().add(dataPanel);

      JPanel buttonPanel = new JPanel();

      JButton login = new JButton();
      login.setText("Login");
      login.setName("login");
      buttonPanel.add(login);

      JButton clear = new JButton();
      clear.setText("Clear");
      clear.setName("clear");
      buttonPanel.add(clear);

      getContentPane().add(buttonPanel);

      pack();

      setLocationRelativeTo(null);

      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }

   public static void main(String args[]) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            new LoginSwingView().setVisible(true);
         }
      });
   }
}

So, as this example shows, genesis binds JavaBeans properties to widgets such as JLabels, JTextFields and others based on their names. This is just the default behaviour; it is possible to determine which component to bind to a property using any other technique, as well as to ignore a property. Methods annotated with @Action can be bound to JButtons and other widgets following the same logic used for properties. You can find out more about how the binding works by reading the docs.

Besides that basic binding features, genesis also makes it possible to enable/disable components based on conditions (using @EnabledWhen), making them visible/hide them (using @VisibleWhen), populate tables, combos, lists etc. with a java.util.List or an array (using @DataProvider) and much more. It is also fully compatible with Java 1.4 and has many other non-UI related features, such as transparent remoting (which I blogged almost two years ago).

To finish the big announcement day, a SWT binding is now in HEAD and should be released in the next few days. So if you are developing a desktop application that uses either Swing, SWT or Thinlet, take a look at genesis.



The language barrier

Posted by mister__m on July 27, 2006 at 11:25 AM | Permalink | Comments (34)

Have you imagined how hard it would be to learn and to program in Java if all language keywords, all docs, all things related to Java were written in Klingon? Well, for those who cannot read in English, this is called daily life (those who understand Klingon are not my target audience here).

Most of the talented, gifted young programmers I have known had no clue about English when I first met them. Once you started working with them, you would realize they had't made much progress yet not due to some technical limitation, but rather due to the language barrier. Java keywords made no sense to them, so things that should be natural were hard to learn. Class and method names didn't convey any idea about what they did; they were just hard to memorize. When it came to Javadocs, well, they were just useless. They had to rely on other people's experience and bad translation software to learn about bleeding-edge technology and frameworks. Basically, there were only two possible "happy" outcomes for their situation: either they met a smart senior developer who was able to read in English and that became their mentor or they ended up learning the language, what took several months at best and was not a viable option to all, since some of them did not have the same talent for learning "real" languages or simply couldn't afford a English course (which was needed for some of them).

All this wasted potential has just one cause: the language barrier. It is not really fair to expect people to learn another language in order to become good developers. Learning English and a programming language require very different skill sets and not everyone has both of them. However, this is actually what we expect from these young talented folks. And unfortunately, given our current reality, it is reasonable. After all, how are they supposed to evolve (and to survive) unless they can learn on their own? Hopefully, it seems this situation may change in the near future.

Although we shouldn't expect for a translated version of the Java programming language (nor we would want it, actually), more resources should be available to non-English speakers and, as far as I can tell by observing a few initiatives in the Brazilian community, both the community and Sun care about this issue and are trying to address it.

Recently Sun has provided support (including tools and legal arrangements) to allow volunteers to translate Javadocs to their native language. The Brazilian Portuguese Javadoc translation project, jdk5-api-pt-br.dev.java.net, has already made its first release available . Of course there is still a lot of work to be done in order to have a fully translated copy available and that the need to sign an agreement certainly keep some people away from the effort, but it is a start. I am not involved in this project, but I would like to congratulate everyone who has dedicated some of their time to such a noble goal.

When it comes to articles and tutorials, it is great to see not only an option, but sometimes diversity. In some countries, for instance, there is already more than one magazine about the Java platform, as is the case for Brazil. Great open-source projects, once (and still, sometimes) accused of not having formal documentation, now have translation teams working on their docs. Translated Books become available faster, although quality can be low at times. However, as competent developers who are good at English are now being hired as revisors, the final result tends to improve.

Online book translations definitely take longer, but usually lead to better results. I've founded a translation effort for Bruce Eckel's famous book, Thinking in Java, several years ago (with his permission, of course), and although I am not able to contribute to it anymore, many volunteers keep working on the project, Pensando em Java.

So, what is the point of this post? Actually, there are a few:

  • If you are foreigner, change your attitude! Many folks have criticised translation efforts (especially the Javadoc one) because they think it will lead to dumber programmers. The fact is bad programmers will always exist, but good ones now take a lot longer to explore their potential due to the language barrier. As a good developer who wants to work on a great team, you should encourage these initiatives, not the opposite.
  • If you have the time, skills and desire, join the translation efforts. You will certainly learn a lot, get to know talented folks and help those who speak your language.
  • Recognize the value of original content written in your language, such as magazines and blogs. And, if you can, create original material as well.
  • Finally, if you are a developer/commiter/project owner, don't be hard on those asking questions in your lists/forums in a foreign language or even in bad English (worse than mine :-P). Rather try to find users capable of answering their questions on their native language or make specific questions that help you understand what the person wants to know.

When you support those working on making Java easy to learn, no matter what language they speak, you are just strengthening the community. And a strong community will certainly last longer, as well as your current job :-)

PS: for those who speak Portuguese, I've created a new blog at http://blog.michaelnascimento.com.br/.

Para aqueles que falam português, eu criei um novo blog em http://blog.michaelnascimento.com.br/.



Tiger and dates don't get along

Posted by mister__m on February 08, 2006 at 09:27 AM | Permalink | Comments (20)

Since Java WebStart 1.4 does not work on Linux kernel 2.6, there are many new features in a certain operating system release that are interesting to the customer I am currently working for and some applications they are willing to use require Java 5, we have started testing their main application on Tiger. However, it fails miserably due to two major bugs that have been available since the first day Java 5 was released.

First, TimeZone.setDefault(TimeZone) is severely broken. Instead of setting the JVM-wide TimeZone default instance, it now works on a thread-basis!. Ok, to be more precise, it uses a InheritableThreadLocal, which means you will have to set the TimeZone instance for all "parent" threads in your application. If you are developing a desktop application and setting the default TimeZone from the main thread before the GUI starts, all code that runs from the event dispatch thread won't see your changes! This bug has been reported and the submitter even suggested a workaround for the event dispatch thread, but the fix will only be available on Update 7!

Then, there is a binary compatibility bug since the first Java 5 release: java.sql.Timestamp.compareTo(java.util.Date) now throws a ClassCastException. If you declared all your references as Dates and used Hibernate, for instance, to initialize them, it is pretty hard to isolate these problems. It gets a lot worse if you have used Collections.sort(..) or Collections.max(..) in your code, since it gets impossible to detect this. This bug has been reported nearly one year and a half ago and has only been fixed last month. However, the fix will only be available in Update 7, whenever it is available.

So, if you deal with Date, Calendar or use Timestamp comparissons in your JDK 1.4 compatible system or even plan to do so in Tiger, hold your breath: wait for Update 7, whenever it comes around. If you have to upgrade to Java 5 by a certain date due to other reasons, you are in big trouble, just like me. Notice I didn't even mention all the daylight saving problems you will have to cope with if you are just interested in dealing with "plain" dates...

Unfortunately, the best advice I can give to anyone planning to do even some simple work with dates is to use Joda-Time, a great piece of Apache-licensed open-source software created by Stephen Colebourne.

As a JCP member, I have to ask: which companies or individuals is willing to support a JSR to add a Joda-Time based API to Dolphin and solve this mess in a proper manner?



Writing applications that can be embedded in IDEs

Posted by mister__m on July 27, 2005 at 11:21 AM | Permalink | Comments (1)

Well, every time I think I'll be able to blog more often, something happens. So, I will try not to apologize about it and get straight to the point. :-)

A cool thing I did recently was to write a set of NetBeans plugins that adds support for Thinlet in the IDE, called ThinNB. One important feature that it provides is a visual editor for Thinlet xml files. In order to implement it, instead of reinventing the wheel, I've decided to base my work on ThinG, a standalone application created by Dirk Möbius that already did that. There were a few changes I had to do it so it could be embedded in NetBeans and that probably would need to be done to most applications if they were to be converted into IDE plugins, so it is worth talking about them.

ThinG's code is actually well-written, so I didn't have to refactor it in order to expose a single class to my plugin, but this might not be true for other applications. If you are writing an application that might be used as a plugin in the future, make sure everything is properly encapsulated and that the right methods are exposed through your "main" class (which does not have to be the one with the public static void main(String[]) method).

The changes I did concerned four main areas:

  • Appearance
  • I/O System
  • Settings
  • Logging

Appearance

If you are running in embedded mode, there is already a menu bar, a status bar and a toolbar being displayed. It is important these features can be turned off in your application when running in this mode. What I did was to add a boolean parameter to the main class constructor and used it in the section that assembled the UI.

Besides that, since many useful status bar messages were generated by ThinG, I wanted those to be shown at NetBeans's status bar. I solved this problem by creating a simple StatusBar interface with a single method, setText(String) and writing two implementations: one that simples use the Thinlet widget when running as a standalone application and another one that uses NetBeans APIs to display it in the IDE.

If there were menus or toolbar buttons that needed to be made available to the end user, it would probably be necessary to write some listener interfaces so it was possible to enable/disable them as required.

I/O System

If you intend to use your application inside an IDE, it is better to think twice before using java.io, specially java.io.File. IDEs have their own I/O abstraction for some reasons, such as adding listeners to files, performing I/O "transactions" or working with virtual filesystems.

Fortunately, ThinG didn't use java.io.File a lot and I could create a simple interface, thing.spi.FileWrapper, to abstract what was actually being used from java.io.File. Again, I wrote two implementations of it, one that is part of ThinG itself and one that lives in the NetBeans plugin.

Settings

There is a decision to be made about sharing settings: do you want both the IDE and the standalone application to share the same settings or to keep them separate? If you pick option one and your application uses the Preferences API, it is quite straightforward to implement it.

If you want to follow the second path, you just need to define yet another interface for that purpose. Since I wanted to add a few settings and hide one from the end user, I ended up creating a thing.spi.Settings interface.

Logging

I am not sure this is true for other IDEs, but NetBeans has its own API for logging. In order to integrate with it, whether your application use java.util.logging or Commons Logging, you just need to provide an adapter class that "translates" between the logging APIs. Since this issue is basically NetBeans-specific, please take a look at net.java.dev.thinnbeditor.ThinletVisualEditorInstall and net.java.dev.thinnbeditor.logging.LoggerAdapter if you want to know more about it.

Conclusion

ThinG is now both a standalone and an embeddable application after a few changes. It shouldn't be hard to use it as a plugin for Eclipse, IDEA or JDeveloper now, for example. I hope the principles I've explained here can help other people out there as well.



Thinlet plugins for NetBeans

Posted by mister__m on June 06, 2005 at 10:47 AM | Permalink | Comments (0)

Module development for NetBeans is something I've always been interested in, but never had the time to do. This time, however, I was able to; the ThinNB project at java.net adds Thinlet support for the NetBeans IDE.

From the ThinNB project home page, "ThinNB is actually two things: an umbrella project for the ThinNB family of NetBeans modules and also the module responsible for installing the ThinNB Update Center in the IDE." It recognizes Thinlet xml files, adds a new template for a xml file with a panel as it root node, allow files to be previewed inside the IDE, adds support to an embedded visual editor - a modified version of ThinG - and also installs an Update Center in the IDE so it is possible to obtain new releases of the modules in a more natural way.

You can go to the home page to see some screenshots, get information about its features and also read the download and installation instructions. Enjoy it!



Supporting script languages in your application

Posted by mister__m on April 24, 2005 at 01:13 PM | Permalink | Comments (2)

It's been over a month since we added generic script support to genesis, but it was such an interesting experience I've actually considered writing this entry part of my TODO list. I've finally managed to do it, so let's go to the main point before you all fall asleep.

Since its inception, genesis has been using JXPath in order to allow users to express conditions that controlls when fields are made visible or not, enabled/disabled, cleared, when a method should be called by the framework etc. JXPath is not exactly a script language, but rather a XPath implementation that works on JavaBeans as well. However, since I was particularly familiar with it, expressions written in it were clear and concise, it is possible to invoke arbritary Java methods from expressions and to export custom function libraries, it was very easy to use in our internal framework code, quite performant and had support for compiling expressions it was picked up as the way to express conditions.

Although we did like JXPath a lot, there were some reasons we thought it was worth supporting other options:

  • XPath is tricky. For example, testing a boolean property using code such as value simply tests for the existence of a property named value, but not if it is actually true. You have to do value = true() for this, which is usually not what developers will try at first unless they really know these XPath specifics. It was never our intention that developers had to know this kind of things.
  • People shouldn't be forced to learn JXPath to use genesis.
  • People already know other script languages, such as JavaScript or EL, for example. It would be good if they could apply this knowledge while using genesis.

Since we decided we wanted to support new script languages, we had to come up with a design for that. Basically, instead of using an available abstraction as is, we wanted to make sure there was no performance degradation for our JXPath users and we were already aware of standardization efforts on this area - JSR 223 to be precise - that were not (and still are not) available for use. This motivated us to come up with a more generic design, in package net.java.dev.genesis.script. The general-purpose classes in this package are:

  • Script: the main abstraction of the package, represents a script language implementation. It has methods that allows one to obtain an instance of ScriptContext (explained below) and to compile expressions.
  • ScriptFactory: responsible for creating concrete implementations of Script
  • ScriptContext: this interface allows one to perform context, script language specific tasks, such as obtaining the value of a variable, declaring variables, registering custom function libraries and evaluate expressions
  • ScriptExpression: represents a compiled expression that can be evaluated in a context

The reason I said these are general-purpose classes is because there are other classes in this package that are more specific to genesis "business" itself, such as abstract support for genesis functions, but I won't explain these here though.

Now, back to the main plot, the next step was to add a JXPath implementation and that is what package net.java.dev.genesis.script.jxpath does. It wasn't hard at all since most concepts we abstracted are directly supported by JXPath in a quite direct way (such as generating a compiled expression for example).

The next step was to add support for two popular script languages: BeanShell and JavaScript. Although we could use our own infrastructure to build that, we were looking for a more general way of abstracting the usage of such languages and decided to use an already existing solution for that. BSF, the Bean Scripting Framework, an Apache Jakarta Project, proved to be a good way of plugging these languages into our infrastructure with minimum effort. Our general adapter package for BSF is net.java.dev.genesis.script.bsf and BeanShell simply worked perfectly with just that adapter. JavaScript required a minor tweak to work - class net.java.dev.genesis.script.bsf.javascript.BSFJavaScriptEngine - since it had problems with evaluating expressions in "child" threads (basically, its context is thread-specific, but genesis calls methods in a Script implementation in different threads, for several reasons) and boolean expressions do not return a java.lang.Boolean instance, but rather some bizarre org.mozilla.javascript.NativeBoolean object. Since this adapter class ended up being rather small anyway (71-line long, counting all blank lines and with the LGPL header taking up 18 lines), it was certainly worth it.

After we had support for at least 3 languages - we are still not sure how many BSF supported languages will simply work out of the box -, we still wanted to support another language web developers were familiar with. EL, the Expression Language first introduced by JSTL and later adopted by JSP, was chosen. Since EL as defined in package javax.servlet.jsp.el is just a SPI, we needed an implementation of it in order to support EL in genesis. The Apache Jakarta project provides an implementation of EL called Commons EL which we used in our solution.

As we started working in an implementation, we were amazed to find out most things we needed were defined in the SPI and not in the implementation itself. It is really rare for "young" specifications to have this level of support at the "standard" level, so I must congratulate the EL folks on that. Implementing package net.java.dev.genesis.script.el was mainly a simple task, except for the fact the SPI does not allow expressions to be pre-compiled without a FunctionMapper instance - which is not available when we do it - and it does not allow instance methods to be exported as functions. We got around the first limitation by using a specific method in Commons EL (as shown in ELExpression), but the second one would require EL specification changes and is a limitation our users will have to face for now.

So, it turns out supporting script languages in an application or framework is not a very hard task and it took us a few days to walk through the whole process, which included selecting the languages to support, study their documentation, look for an existing abstraction, modify our build process and a bunch of other tasks. In the future, when JSR-223 becomes final and an open-source implementation becomes available, it will be even easier to support script languages.



More about Practical AOP and Transparent Remoting

Posted by mister__m on January 04, 2005 at 10:53 AM | Permalink | Comments (1)

I am glad my original post about Practical AOP and Transparent Remoting has received polite and smart comments against it. This is definitely a nice way to get the discussion about AOP going! Here are my answers to these comments.

First of all, cajo said that "this is a perfect example of why I fall into what you call your third AOP viewpoint. As you said, magic happens; but it is also totally invisible from the actual source code. I can't imagine how one would debug a complex application." I am sure this is a reason why many developers are concerned about AOP adoption. But let's address this question to see if this point should prevent us from using AOP.

First, how do you debug such application? If you simply use your IDE "Step Into" debugging functionality and you happen to have genesis sources available, your debugger will stop at the advice's first line. And then, everything will be simple to understand. But maybe the real question is: how would I guess I should step into at that line? To answer this question, we just need to think about how we decide to use step into when debugging our OO applications.

If you have a snippet like:


public void aMethod(SomeClass o) {
   o.someMethod();
}

You already cannot assume you should look for someMethod() implementation in SomeClass in this simple example. Why? Because you might be dealing with a subclass or maybe a proxy. And if SomeClass is an interface and the instance you received is a dynamic proxy, it becomes even harder to debug. So, if there's any chance you're dealing with a polymorphic call today, you already have to guess whether the code being executed belongs to SomeClass or is defined on another class. "Hey, but I don't have to guess; I can use Step Into today", someone might say. And that's just what I said a few lines above. You should use Step Into in these cases to be sure what code is actually being executed. The only new thing with AOP is that it may happen with any method, but it is not different from today.

Besides that, either your aspects should affect well-defined points in your code or you should use a tool. AspectWerkz provides an Eclipse plugin that helps you to see which methods are affected by advices, for example.

Then, cajo proceeds:

Consider operator overloading: Many argued against its inclusion in Java, because it could make the source look less obvious. To me, this source looks far less obvious.

Well, except for String concatenation tricks - which shouldn't exist for consistency, anyway -, I agree about operator overloading because it already has just one meaning. But as I showed above, a method call is already "trickier".

Another interesting response came from jhook. He begins:

I can't necessarily argue with what Michael is trying to accomplish, just in how it's being accomplished. The problem with many of these AOP implementations is that you are modifying the behavior of an object for everyone. The behavior of RemoteClass is intrinsic, adding a client's ability to remote 'helloWorld' is extrinsic to RemoteClass and IMHO shouldn't be applied for all clients of RemoteClass (at compile time).

Some of that's true, indeed. For this specific case, my intent was that every RemoteClass client had to access it through the aspect. But it only affects clients that have access to the weaved version of the class. So, in the server side, we keep a "regular" version of it and no remoting is necessary. This is one approach to actually do what jhook suggested: use the class version you want.

Another approach is to change your pointcut to intercept calls to the method and not changing its execution as the default aop.xml that comes with genesis empty-project does. That's the beauty of AOP: this behaviour is actually extrinsic to the class, since your configuration will determine whether method execution, call or none will be affected by which advices you choose.

The last comment I would like to reply to have been made by ablperez. It says:

A cleaner example of AOP's power would have been taking a POJO and making it transactional. Objects that are remotable should clearly relflect that. This example commits the fallacy "The network is reliable" from the eight distributed computing fallacies. A well defined remotable object should declare to throw a remote exception. IMHO remoting is not something you want to hide.

Well, that's debatable. How would you handle the RemoteException? Rethrow it in every method that calls this class? Write tons of try/catch blocks spread throughout your codebase? A cleaner approach would be to handle it once, in one single place. Since Thinlet - and therefore genesis - already defines a single point for handling exceptions, you can do it once in a base class. However, if you do think it's nice to be more explicit, just add a throws java.rmi.RemoteException to the method's signature and handle it as you wish. The exception will be thrown as you would expect.

It's important to mention that genesis default project structure is targeted to intranet environments, where bandwidth shouldn't be a problem most of the time. Besides that, a timeout aspect is applied to every remote call to make sure it either completes timely or a timeout exception is thrown. So it actually expects delays to happen. The default aspect doesn't do any fancy stuff, such as displaying a wait dialog or something like that. This should be customized on a project basis.

I hope we can keep this healthy discussion going, since I think it just helps the community as a whole. By the way, a new genesis release, 0.2-beta2, is now available. Its documentation is available if you are interested. I'll be saying more about AOP soon. Stay tuned ;-)



Practical AOP (Part 1): Transparent remoting with AOP and EJBs

Posted by mister__m on December 17, 2004 at 01:44 PM | Permalink | Comments (4)

There are basically four views about AOP nowadays (ok, it's more or less the same for any technology): those who think it's the golden hammer and everything is a nail, those who think it has some applicability, those who are strongly against it or have deep concerns about its wild adoption and those who simply couldn't care less about it. :-) I hope this kind of posts I intend to write help all the four groups in some way.

Let's start with an example most people are familiar with: remoting. Many technologies try to address remoting with different approaches - RMI, CORBA, EJB, webservices etc. - and each one has its own applicability, since most of them (are intended to) do more than just remoting. Also, these technologies can be implemented in several ways - consider the way EJB implementations in application servers has evolved, as an example. So, let's narrow our requirements for this case of study:

  • Remoting should be transparent to the user. So, this means not even lookup or interfaces should be necessary for a user to call a remote component.
  • We want to keep the benefits provided by EJB technology - security, transactionality, etc. - but without any complicated constraint on our code. We don't want to write tons of rules for a Hello World.

In a simple way, we want EJB benefits without any of its limitations. How could we implement this?

Using genesis this should be as hard as:

public class RemoteClass implements java.io.Serializable {
   /**
    * @Remotable
    */
   public void helloWorld() {
      System.out.println("Hello world");
   }
}

public class Client {
   public static void main(String[] args) {
      RemoteClass remote = new RemoteClass();
      remote.helloWorld();
   }
}

If you run this example using a genesis empty-project based structure, putting RemoteClass in your shared sources dir and Client in your client sources dir you will see that "Hello World" actually gets printed in your application server console. How this magic happens?

genesis' aspect named net.java.dev.genesis.aspect.EJBCommandExecutionAspect intercepts execution of methods annotated as @Remotable as defined in aop.xml and executes the method call inside a Stateless Session Bean in the server side. Since you have a simple POJO, you are not constrained and can take advantage from any OO feature you want, including instantiating a remote object with new if that's what you want, and you still get all the benefits from EJB technology. It's a much cleaner approach to remoting than other ones currently available and it's certainly going to be expanded on future releases to support full Session Beans semantics with plain POJOs - as well as the current model.

For further information about how this actually is implemented by genesis, refer to the documentation pages for genesis aspects and genesis business component model.



Announcing genesis

Posted by mister__m on December 13, 2004 at 10:27 AM | Permalink | Comments (1)

A few weeks ago, we've silently released the first public beta version of genesis. But what is genesis about?

genesis is open-source software (LGPL) and its main objective is to allow you to build powerful, scalable applications in a simple, productive and testable way. Although its long term goals are much more ambitious, right now it focuses on two main areas:

  • UI programming: your form is just an annotated POJO and... that is it; no further requirements. Annotations will allow you to automatically populate comboboxes and tables, to enable/disable widgets, make them visible or not, clear fields based on conditions etc., in a declarative way. Programming a complex UI becomes a very simple task, which is one of the main reasons some people still avoid using Java on the desktop. The current implementation uses Thinlet as the view technology, but other APIs, such as Swing, will be supported soon.
  • Business components: many "modern" frameworks support a POJO model for business components, but there are still several limitations - a business object cannot be directly instantiated, but rather injected or looked up using a factory, for example, or you have to expose your POJO using an interface or otherwise you won't be able to take advantage of most facilities offered by these frameworks. genesis takes a different road: you can use new to instantiate your components and they don't have to implement or be exposed by any interface in order to take advantage of genesis' facilities. In runtime, depending on your configuration, genesis may use EJB technology to execute your POJOs as if they were Stateless Session Beans or you can work in local mode (which is cool for some desktop applications). You don't have to change a single line of code to switch execution modes, but just use a different target to build your application. Current genesis features include transparent remoting, transactional support and DI (dependency injection) for Hibernate. General DI will be supported soon.

genesis does not try to reinvent the wheel, but rather builds on top of several other open-source projects to deliver its functionalities. Besides Thinlet, this release relies heavily on AspectWerkz and AOP to implement a flexible core so that new ways to do remoting or to configure a form - using xml, for example - are easy to write and don't require any changes to existent genesis code. So, if you are looking for practical ways of using AOP, check out genesis sources.

genesis is already running on production environments and, in one of them, the server-side application is capable of handling more than 1.125 million transactions per day with a single box. You can access genesis docs and download it at https://genesis.dev.java.net

UPDATE: genesis was the 2nd largest java.net project by commits last month according to this report, so it is really worth a quick look. ;-)



Welcome to the JSR community

Posted by mister__m on June 28, 2004 at 12:14 PM | Permalink | Comments (0)

Welcome to our newest community, the JSR community. The java.net JSR community has been created to support the goals of JCP version 2.6 to make the process more transparent. File sharing, news groups, mailing lists and other services are among the services offered to help to achieve these objectives.

Each JSR willing to join this community will start a new sub-project here. There, you will be able to subscribe to public mailing lists that will allow you to know and comment about what topics are currently being discussed by the Expert Group, get updated information about the spec status and know when drafts are available. Besides that, if the reference implementation and/or the TCK are open-source software, you will be able to access them here.

Expert Group Members will be able to take advantage of many valuable resources, such as version control and private mailing lists for internal discussion. By using java.net resources, they'll get feedback earlier and the end results will be better.

This community will also provide you news about the JCP, JSRs and related subjects, as well as support discussions about JSRs and the process in general. We hope you can be an active participant of our community and help the whole Java community as a result. Join us and help to shape the future of Java!

PS: many thanks to the whole java.net crew that has made it possible, specially to Sarah Breen, who has been like an angel to all community leaders.



EJB 3.0 - Is it going to solve our problems?

Posted by mister__m on May 19, 2004 at 01:01 PM | Permalink | Comments (1)

UPDATE: Brazilian Portuguese translation / tradução para o português do Brasil no JavaFree

To begin with, I must congratulate the JSR-220 EG for their braveness. I can't think of any spec in the JCP that has been changed in such a dramatic way as this one. Linda said during the last JavaOne she intended to kill deployment descriptors and to simplify the programming model as much as possible. However, I never thought the EG would take that words so seriously and would drop the current model - ok, "drop" may sound too strong, but, even though they are going to support it, anyone writing code will prefer the new API unless there is some political/business objection for not doing so - for a POJO-based one.

So, now it's time to explain why I think we can simplify EJB 3.0 even more and give tremendous flexibility for the hardcore developer without making any EJB look cluttered or ugly (some people said Linda stated it still will be necessary to use the "old model" for some hard stuff; this sounds extremely unpleasant to me, I must say). The new programming model for EJB 3.0 seems to rely heavily on annotations. This certainly is a good thing compared to the deployment descriptor hell, but there are two things missing that would make turn this idea into something really powerful:

  • Annotation processors: what do you do when the security capabilities of your app server are insufficient or inadequate for your needs? Change vendors? But what if the first vendor has a feature you need, but that the second one doesn't offer something similar? That's one of the flaws we're still keeping: vendors will implement the spec in some way that may not be what you need/want. And what can you do about it? Almost nothing, besides throwing your app server away or relying on a non-standard solution - sometimes, it means not using EJBs for a part of your project they'd be the perfect fit if only that feature had been implemented in a better way by your app server vendor. What if you could write implementations for the services an EJB container should offer? You may now say: "hey, but that's exactly what I've paid for", but it's often needed. Vendors are not capable of foreseeing every need you'll have. It'd be even better if we had a standard spi for all the services an EJB container is supposed to provide. In that way, you could swap small components or, even better, write a decorator around a app server specific implementation so that you could only provide the one missing functionality you need - instance-based security for entity beans, for example - and delegating the other features to your app server default implementation. Imagine how many problems you would be able to solve if you could change or augment the functionality provided by an application server in a standard way! I can tell you it would solve around 80% of my issues with EJB. The other 20% would be solved as shown below:
  • Support for custom, user-defined annotations: frequently, we need to add services to our components that are not part of the EJB spec. If this feature is not so domain-specific, chances are some vendor has provided support for it. And then, welcome to vendor lock-in! You are left with two choices: go for vendor lock-in or write terrible code just in order to have a portable application. Wouldn't it be nice if you could solve it in a elegant, portable way? Custom annotations and custom annotation processors could be the answer. Imagine if you could write an small session in an deployment descriptor declaring a custom annotation and an implementation of an interface, AnnotationProcessor, that's capable of handling it. You could define your own implementation or simply delegate the processing of your custom annotation to a class provided by your container of choice. You could get portability and still benefit from non-standard features your vendor offers you. Annotations without properly-configured processors would be simply logged at deployment time, since they could be there for a nice reason - for example, you might want to "tag" your methods for some functionality first and implement it after; or maybe that annotations are meant to provide enhancements during runtime and don't represent essential services, like caching, for example.

I am pretty sure some people will say: "Spring (put your favourite lightweight? container here) can do that" or "this is a case for an AOP-based container". I totally agree with the first and I think an AOP-based container would be a good implementation, but the real point is: these are not standards. There is only one Spring - some people might be writing a few implementations for its interfaces, but they are just some people, not major vendors with hundreds or thousands of experienced employees working full-time on that - and AOP frameworks I know are completely different from each other. If we could come to agreement on what basic services an EJB container should provide, a SPI for them and a way to plug custom annotations and to process them, we could get ease of use with maximum flexibility and ability to choose without limiting you to rely on a single vendor for the rest of your life. Vendors would have to provide amazing implementations for each EJB container service and offer a lot of high-quality custom services if they wanted to keep up. A new market of service providers would arise and we'd see a constant increase in the quality of each comercial container out there.

Besides that, there's another idea that annoys me: who said an interface is always a good thing? Even if the container generates it, I am sure I'd be glad to write:

OrderService os = new OrderService();
os.processOrders(orders);

instead of using a container-generated interface for my sesion bean. Plain Java code is great! If I don't need to use some javax.ejb.SessionBeanFactory or to have use a DI container in order to provide interface implementations to my client components, I can hire almost any person who knows basic Java to work with me in my enterprise projects and knowing I won't have to teach them a thing! That is easy of use. Interfaces are needed for a lot of reasons but, as I stated above, they are not always wanted.

Several techniques would be necessary to make these ideas work inside the container - a post-compiling phase, CGLIBed classes, etc. - but that's not my concern at the moment. If I am able to have a similar architecture right now using AspectWerkz - one of the greatest pieces of software I've ever came accross, with incredible support -, why can't enterprise vendors provide something similar?

I am sure that some people would still object saying this would be best addressed by an AOP JSR and a lightweight container JSR, but let's face it: EJB 3.0 started one year ago and it's expected to be finished next year; if we start these other JSRs now, when are we going to see a compliant implementation of them? Besides that, I am not asking for full AOP support; I just want annotation processors and maybe vendors would need to use AOP, CGLIB and/or custom class loaders for achieving my plain Java model. It may not be perfect, but it's better than what we have now in my opinion. What vendors would have to do to support the features doesn't concern me; all I want is a standard solution, with competing implementations, that offers me simplicity, total flexibility and portability.

I do hope someone from the JSR-220 EG reads this blog and post some comments about these ideas.

PS: I really think the JSR-220 EG members are doing great things and think their work must be acknowlegded and praised. They are doing the right thing, although it's hard to do. I just want more :-D. Don't get me wrong: Spring rocks, as well as Pico/NanoContainer. And AspectWerkz will be part of all my future projects unless my client objects, you can be sure. :-D

PS2: This post is inspired by the fact that, several months ago, I posted here some suggestions on how to improve the spec. They were not as drastic as the ideas presented during the last TSSS, but they addressed the most annoying issues I had to face with EJB at that time. Ease of use was, at that time, in my mind, very important for wide adoption, but my post reflected things that even XDoclet and my own frameworks couldn't solve in a decent, clean, non-application-server-dependant way. What amazes me now is that apparently most of those issues aren't going to be addressed by the new spec. Since I wrote that entry, I've been involved in lots of projects and got to know the now popular lightweight frameworks, besides getting my hands dirty with AOP. And I must say that, after playing with these ideas for a while, I got to understand things really must be simpler for the regular work - 95% of it -, but that I still do need a lot of flexibility. And I don't want this flexibility to make my code look harder when I use fancy, obscure, powerful features; I want my business code to always look as simple as the rest of my codebase. The only complexity I want to face is the inherent complexity of my business problem.



Branching open-source software: a bad thing?

Posted by mister__m on March 19, 2004 at 06:49 PM | Permalink | Comments (4)

It's been a while since I last blogged. Besides being busy in my regular job, I got sick and also had to finish this article about Reflection on Tiger. Well, I must say I am enjoying the new project I am working on, since I am being able to have almost full control about everything - except the deadline, but that's acceptable :-D Since the customer is really interested in achieving a quality product its employees can evolve, we have chosen technologies that would allow them to write their business code with minimum effort, but in a elegant way, resulting in a robust, performant application. So far, it looks like things are going fine in that sense.

However, I must say I am worried about something we started doing a few weeks ago. We are not using any technology in this project we haven't used before, so we already knew the limitations each technology had from day one and, even though, thought they'd be the most appropriate ones for this scenario. Many limitations were just bugs we had fixed before, posted to the code maintainers months ago, but that just hadn't been aplied. Others were lack of points of extension - interfaces, factories, protected methods and abstract classes, to name a few - that would allow us to adapt a framework or a tool to suit our needs. That's why the problem began. If you tell the project owner and the committers about bugs, provide them with patches, mention a few methods that need to be changed from private to protected, changes that would benefit most users and no one cares, what are you supposed to do?

We got our answer: we've branched those projects in our customer's local CVS. I have done it a few times in the past, but it always was just one branch for one project, not for nearly all of them! All the limitations we are facing are the ones we cannot simply workaround without making our daily code smell; generally speaking, there is no way to fix most of them in a single point and, when there is one, it would impose other limitations to our code that would make it even worse.

The problem with those branches is that they are really hard to manage. One thing is creating a CVS branch in a project your company owns; it's just a matter of communication and some work to manually resolve any conflicts when merging versions. Unfortunately, most open-source projects today tend to change frequently in incompatible ways, especially when you are not talking about classes most people use. Some developers will say: you just have to learn about what has been changed. But, sometimes, I don't want to!!! I just want to get a bug fixed, but if I've branched their code, it can become something too hard to do!

The real question is: why did I have to create a branch in the first case? Is it because the original code author assumed no one would need more flexibility or thought "I won't add it until someone needs it" and now is just too busy to take a look at the patch and get it fixed? Sadly, the answer most times is: yes, that's it. Nothing can be more frustating to a developer than writing code to fix a bug, write thorough instructions - and most of the times, code - to prove the bug exists and that your patch works and then noticing no one in the open-source project seems to care. It's a sad reality we have to face everyday when we push technologies a little bit. I just wish project leaders could learn to think ahead and to react quickly. And, no, it's not about having free time themselves to get it fixed; it's about managing a project. And it's something really, really harder to do than just coding.



Playing with the Tiger: Measuring nanos

Posted by mister__m on February 05, 2004 at 06:41 PM | Permalink | Comments (10)

Ok, sorry for not blogging for so long, but I have to work, date etc. :-D

I hope this is the start of a series of small, but informative blog entries about new features available in Tiger, especially the ones a hundred people haven't mentioned before me :-D

To begin with, I'll show you how to use the new nanoTime() method in System. An important thing to notice is that nanoTime()'s return and currentTimeMillis's are not necessarily related to each other - meaning they don't have to use the same reference to zero. This example also uses the new static import feature. I am not saying I like it or not. That's what I expect you to say.

Here's the code:

import static java.lang.System.*;

public class Nano {
   public static void main(String[] args) {
      long time = 0;
      long newTime;
      long smaller = 9999999999999L;

      for (int i = 0; i < 100000; i++) {
         time = nanoTime();
         newTime = nanoTime();

         smaller = Math.min(smaller, newTime - time);
      }

      out.println("Smallest nano interval measured: " + smaller);
      out.println("Current time millis: " + currentTimeMillis());
      out.println("Nano time: " + nanoTime());
   }
}

Save it in Nano.java and compile it with:

javac -source 1.5 Nano.java

Then run it normally with:

java -cp . Nano

My results (P4, 1GB RAM, Windows 2000 Pro) are:

Smallest nano interval measured: 1116
Current time millis: 1076038988125
Nano time: 8736336585045

This method is intended to be used as a way to measure performance, for instance. Here, I just tried to get its precision in my current box configuration.

Please let me know if you get smallest nano intervals in your platform/configuration. See you soon ;-)



JXPath to rescue!

Posted by mister__m on December 31, 2003 at 07:36 AM | Permalink | Comments (6)

Querying a database is no big deal. SQL has been around for a long time and has become the de facto standard for doing that. So has JDBC, even though nowadays it is being used more as the foundation of other solutions and frameworks. But what you do when you have to query objects? Most people wouldn't be able to answer it, really. Three more common ways of querying your objects in Java are custom indexing, OQL and JXPath. This entry is specifically about JXPath.

Jakarta Commons JXPath basically defines a simple XPath interpreter that can be applied to general object graphs: POJOs, Maps, Servlet contexts, DOMs and more. XPath is a W3C standard originally conceived for navigating XML nodes, but can be easily applied to Java.

Let's see it in action. To ilustrate its use and advantages, we will work with the classical Order problem (Order, LineItem and Product). Let's assume all Orders are stored in a Collection which is a property of our OrderHistory object. What if we wanted to get all the Orders which contained more than 5 CDs? In plain Java:

Collection selectedOrders = new ArrayList();
Order order;
LineItem item;

for (Iterator orders = orderHistory.getOrders().iterator(); orders.hasNext(); ) {
    order = (Order)orders.next();

    for (final Iterator items = order.getLineItems().iterator(); items.hasNext(); ) {
      item = (LineItem)items.next();

      if (item.getQuantity() > 5 && item.getProduct().getType().getName().equals("CD")) {
         selectedOrders.add(order);
      }
    }
}

return selectedOrders.iterator();

To avoid being unfair, using 1.5 sintax:

Collection selectedOrders = new ArrayList();

for (Order order : orderHistory.getOrders()) {
    for (LineItem item : order.getLineItems()) {
      if (item.getQuantity() > 5 && item.getProduct().getType().getName().equals("CD")) {
         selectedOrders.add(order);
      }
    }
}

return selectedOrders.iterator();

With JXPath:

JXPathContext history = JXPathContext.newContext(orderHistory);

return history.iterate("/orders[lineItems[quantity = 5 and product/type/name = 'CD']]");

That is it. As simple as that. JXPath becomes more valuable as your queries become more complex, but I am not going to show an example here.

Someone might ask: hey, but when I would like to manipulate objects in memory? There are a lot of occasions, actually. One very common is when you have a small application that needs to persist a small amount of data. If you combine Prevayler - an option to databases, as it keeps everything in memory and performs persistence through serialization and guarantees data integrity - and JXPath, you have a very fast solution with fewer lines of code. Consider using it when you have the chance.

As a final note, JXPath has many powerful features, as compiled expressions and variables - similar to PreparedStatements -, pointer, and many more, but you can find more about these by yourself. Go to the above link, download and start using it. The User Manual in the docs is probably the best one for a Apache Project and is highly recommended reading. Try it as soon as you can: you may become addicted to it...



Achieving better compression with Deflater

Posted by mister__m on December 26, 2003 at 10:48 AM | Permalink | Comments (4)

I've recently been playing more intensively with CVS - I've always used either IDE support for it or any nice GUI client for CVS available - and found out more about GZIP compression than I knew before. That's my main motivation for this post.

It's been quite a while - since JDK 1.1, according to javadocs - Java has been providing support for working with ZLIB compression through its API. The package java.util.zip contains classes for manipulating GZIP and ZIP formats, as well as for coding to compression utilities directly by using the Inflater and Deflater classes.

So, getting straight to code, if you want to compress an object you are writing to a stream:

   public void writeCompressed(OutputStream os, Object toWrite) throws IOException {
      ObjectOutputStream oos = null;

      try {
         oos = new ObjectOutputStream(new GZIPOutputStream(os));
         oos.writeObject(toWrite);
      } finally {
         if (oos != null) {
            try {
                oos.close();
            } catch (IOException ioe) {
                /*
                 * The day someone gives me a sensible explanation why this method 
                 * throws an exception (as if there was something I could do about it or 
                 * if I cared!), I will be sooooo grateful :-D
                 */
                ioe.printStackTrace();
            }
         }
      }

Besides the ugly try inside the finally block - that deserves a whole post to itself, called "API design we don't get", probably better posted by Hani -, it's pretty simple. I've been working a lot with Prevayler- in a simple way, a very good open-source substitute for databases, faster by far - and as it works with serialization, I thought it would be a good idea to compress the serialized stream it generates. I've written a class you can use with Prevayler that does just that, as part of my open-source project, reusable-components, and it'd been a while since I last modified it. However, after some time manually dealing with CVS, I've noticed GZIP streams can have different compression levels and started wondering if java.util.zip provided support for playing with these.

Indeed, Deflater supports compression levels through a method named setLevel(int). The argument this method takes is yet-another-magical-int-constant-in-the-world, an int argument whose value ranges from 1, a.k.a. BEST_SPEED, to 9, a.k.a. BEST_COMPRESSION. Deflater is used internally by DeflaterOutputStream, which is the superclass of GZIPOutputStream, used in the above example. So if there is a method for setting the compression level, it means it's pretty simple to do it, right? Hum, it's easy, but it could be easier, though.

The problem is that DeflaterOutputStream mantains a reference to its Deflater instance via a protected property named def. It means it is not possible to simply get the Deflater instance and set its compression level. As it is a protected property, though, subclassing GZIPOutputStream will make it accessible. A simple way - in terms of a practical solution, not a very readable one - to do it is using an anonymous inner class with the so-called "anonymous constructor" as shown below:

   public void writeCompressed(OutputStream os, Object toWrite) throws IOException {
      ObjectOutputStream oos = null;

      try {
         oos = new ObjectOutputStream(new GZIPOutputStream(os) {
               {
                   def.setLevel(Deflater.BEST_COMPRESSION);
               }
         });
         oos.writeObject(toWrite);
      } finally {
         if (oos != null) {
            try {
                oos.close();
            } catch (IOException ioe) {
                /*
                 * The day someone gives me a sensible explanation why this method 
                 * throws an exception (as if there was something I could do about it or 
                 * if I cared!), I will be sooooo grateful :-D
                 */
                ioe.printStackTrace();
            }
         }
      }

Using Deflater.BEST_COMPRESSION instead of the default compression level decreases a reasonable (more than 20kb) stream total size by around 10%, according to my tests. GZIP compression makes my serialized objects 80% smaller, which is good, at least for me. This method may be used to fine-tuning the compression level so less CPU cycles are used to transmit something through the network, for example. After some experiencing, you may be able to figure out an ideal value in your specific case and use it as the compression level for your own GZIPOutputStream. Yet another obscure, hidden feature inside the API, recently found out. :-D

If you happen to be using Prevayler and would like to get smaller snapshots, take a look at reusable-components and download the latest version from here. Also, the Enum class has been enhanced to support anonymous subclasses and minor javadoc clarifications have been made, thanks to Jonathan O'Connor suggestions. If you want to join, I'd also be glad.



Why is everyone talking about grid computing? And what are you doing about it?

Posted by mister__m on November 26, 2003 at 07:11 PM | Permalink | Comments (4)

"Grid computing" - though it was quite an unknown concept till a few years ago, now everyone is talking about it. Some are saying it is everything we were missing, the next big thing. Others, as some java.net bloggers, are simply skeptical and uncertain about its practical use. But the fact is many huge companies, such as Oracle and IBM, are investing a lot of money on that - and that's a good reason to take a closer look at it.

To begin with, what is grid computing? Grid computing is about spliting your work in small pieces - or jobs, as you prefer - and assigning those pieces to different computer on the network. After they have been processed, you get them together and your main task is done. But what is the big advantage of applying grid computing?

Have you ever thought about reducing the time your Ant builds take to run? What if you could use other developers' machines to run it in parallel while they are having coffee or are out in a meeting? Wouldn't that be great? And what if you could perform parts of a specific transaction in some machines available in a cluster instead of loading one box for a minute when the user could get the response in a few seconds? Those are the kind of things that may be accomplished with grid computing in an easier way.

So, what is the Java standard for grid computing? None. Soon, there will be one and then we will have to accept it, whether we agree with the way it will be or not. If you are among the ones who hate EJBs - I don't, just gave my own suggestions previously here -, or that think that JSPs are a big mistake, stop complaining! Get involved. Talk to the ones who are defining the standard. Go to grid forums, talk to the guys at Sun One Grid Engine, move! Download one of the many implementations available, such as Globus or Sun One Grid Engine, use them, share your thoughts about it! Tell the community what you like and what you don't and why.

Grid computing will be very useful to many people in the future, but if it is not useful for you tomorrow, well, maybe that's why you didn't try to shape its future when you had the chance...





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds