Wednesday 23 February 2011

Java Beans demystified

Welcome, this is my first blog post on Blogger. This article is intended for those learning Java, and those shifting to Java from a different programming ecosystem. I will try my best at providing a clear explanation of what JavaBeans are, since not even Wikipedia could explain this to me well enough. To quote Wikipedia:


Practically, [JavaBeans] are classes written in the Java programming language conforming to a particular convention. [...] A JavaBean is a Java Object that is serializable, has a nullary constructor, and allows access to properties using getter and setter methods.

Coffee metaphor

Now it's my turn to elaborate: It's called a bean to follow a certain symbolic. Java is (among other things) coffee. As Wikipedia explains: "In the United States the term "Java" by itself is, in general, slang for coffee". To make a perfect cuppa, you'll need to grind some beans. People behind Java find the term bean a good metaphor for a well-encapsulated building block of Java code. Coffee beans, when roasted, have a hardened outside that protects the goodness inside. While it could be considered witty to use the term bean to denote an encapsulated reusable piece of Java code, from my experience it's not the best term for a software component, but I guess it's a necessary evil to have such a term, as you'll see later.

JavaBeans are meant to be used by frameworks/containers/tools/etc. and not just by the code in the project you're currently working on. If you wrote an entire Java application yourself, from scratch, without using any framework, any container and did not intend your code to be used by any visual designer tools etc. then you could well not need the definition of a JavaBean. You could just go on ahead and write plain Java classes any way you choose (assuming the code works and is at least somewhat elegant) and not care the least about JavaBeans.

This is more or less what I have been doing for the last four years at Uni. I wrote code. Code that would run. Code that could be read and marked by a teacher. Not code that I would have intentions to reuse.

The important difference

If you want frameworks, containers, and code that others have written interacting with your objects, you'll want your objects to be written in a certain way. To make it easy for frameworks to instantiate objects from your classes, it makes sense to provide a constructor that takes no arguments. It also makes sense to apply a certain naming convention to your classes' properties' getters and setters, so frameworks/containers that you'll be plugging your code into can query and change the state of your objects' properties with ease.

Properties

Frameworks/containers picking up your beans will be using reflection to instantiate your classes and to determine the names of properties in your classes. What are properties? Well, in Java world, it's a little less explicit than in, say C# or Delphi. You can look at Java properties as private fields that you are exposing via a pair of accessor/mutator methods, also called getters and setters.

Here I'll make a short detour into C#:
To define a basic property in C#, with no extra logic in its getter and/or setter, one line will suffice:

public string MyProperty {get; set; }

Alas! there's no such convenient way for defining properties in Java. Properties, in both C# and Java, share the same concept - they consist of a backing field (usually with private visibility level) and an accessor/mutator method pair. C# has a predefined syntax for declaring properties and then generates the necessary getter and setter methods that are used under the hood (in CIL).

In Java, in order to have properties, developers must adhere to a naming convention and write the getXXX() and setXXX() methods for each (private) backing field they would like to expose as a property. The same MyProperty declared earlier in C# would then have to look like the following in Java:

private String myProperty;

public String getMyProperty() {
    return myProperty;
}

public void setMyProperty(String value) {
    myProperty = value;
}

For properties of a boolean type, things get even more tangled, since according to the JavaBeans naming conventions, the accessor method would be called isXXX(). Luckily this is not an absolute must, it's just considered good practice; getXXX() can still be used even for boolean properties.

Note, also, that the visibility levels of the getters and setters must be public. Is that really so? (Am I trying to confuse you or make things clear?) Of course you could have these getters and setters as private or protected or leave them with the default visibility level... but then your field would be just a field and your non-public getters and setters would be just some methods of your class and the three together (field+getter+setter) would NOT FORM A PROPERTY.

As I mentioned previously, there's nothing stopping you from not caring about the specification of JavaBeans, as long as you don't care to have your code used by other code.  Getters and setters will have to be declared public and adhere to the JavaBeans naming convention in order to be successfully discovered and used by other frameworks/containers/tools/etc.


Containers may use XML to configure your beans

You will often want to configure your objects in a declarative manner using XML. Some piece of software will then read this XML configuration and will work its magic on your classes. For example, you may want to set a particular String property of a class (e.g. lastName) to "Wolfeschlegelsteinhausenbergerdorff".

The lastName property has private visibility on purpose. All assignments to the lastName property are supposed to go through a setter method that may contain some logic, for example how to deal with names above a certain length. The code trying to configure your class instance will want to use this setter to mutate the value stored in the lastName property.

It will have to rely on JavaBeans naming conventions to figure out the name of the appropriate setter method to invoke. It will use Java Reflection API to interrogate the class's members and find the method called setLastName that will be invoked by this third-party piece of code to achieve our goal of having an instance of our class configured with the name "Wolfeschlegelsteinhausenbergerdorff" as last name.

Serialisation

Another aspect of JavaBeans is that they should be serializable - it should be possible to use the standard Java serialization mechanism to store and restore the internal state of a Java bean to/from a file (or network stream, etc.)

The following is an excerpt from sun's java.net Web site:

"When programmers assemble, configure, and connect Beans using an IDE, the JavaBeans components must be "live," dynamically created objects. The IDE must be able to save the worksheet's state at the end of the day and restore it at the start of a subsequent session. That is, a Bean's state must persist via external storage."

When your properties are of primitive or Serializable types, making a JavaBean serializable is as easy as tagging the class with a Tag Interface java.io.Serializable.

public class MyBeanClass implements java.io.Serializable { ... }

When your properties are of other types, make sure those types are Serializable. You could also provide your own custom serialization logic but that falls outside the scope of this article.

Event model

There are further restrictions on naming methods for registering and unregistering event handlers with/from a Java bean, however delving into these particulars would not add much value to this post.

I believe I said enough. I hope it is now clear what beans are in the world of Java.

No comments:

Post a Comment