The Source for Java Technology Collaboration
User: Password:



Michael Nascimento Santos's Blog

Community: Java Enterprise Archives


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.



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. ;-)





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