Monday, 26 September 2016

Code generating beans - mutable and immutable

Java has long suffered from the pain of beans. To declare a simple data class takes far too much code. At JavaOne 2016, I talked about code generation options - see the slides.

Code generation of mutable and immutable beans

The Java ecosystem is massive. So many libraries releasd as open source and beyond, which naturally leads to the question as to how those libraries communicate. And it is the basic concept of beans that is the essential glue, despite the ancient specification. How do ORMs (Hibernate etc.), Serialization (Jackson etc.) and Bean Mappers (Dozer etc.) communicate? Via getters and setters.

The essential features of beans have moved beyond the JavaBeans spec, and are sometimes referred to as POJOs. The features are:

  • Mutable
  • No-args constructor
  • Getters and Setters
  • equals() / hashCode() / toString()

But writing these manually is slow, tedious and error-prone. Code generation should be able to help us here.

But should we be using mutable beans in 2016? No, no, no!

It is time to be writing immutable data structure (immutable beans). But the only practical way to do so is code generation, especially if you want to have builders.

In my talk at JavaOne 2016, I considered various code generation approaches:

IDE code generation

This is fine as far as it goes, but while the code is likely to be correct immediately after generation, there is still no guarantee that the generated code will stay correct as the class is maintained over time.

AutoValue, Immutables and VALJOGen

These three projects - AutoValue, Immutables, VALJOGen - use annotation processors to generate code during compilation. The idea is simple - the developer writes an abstract class or interface, and the tool code generates the implementation at compile time. However, these tool all focus on immutable beans, not mutable (Immutables can generate a modifiable bean, but it doesn't match the JavaBeans spec, so many tools will reject it).

On the up side, there is no chance to mess up the equals / hashCode / toString. While the tools all allow the methods to be manually written if necessary, most of the time, the default is what you want. It is also great not to have to implement the immutable builder class manually.

On the down side, you as the developer have to write abstract methods, not fields. A method is a few more keystrokes than a field, and the Javadoc requires an @return line too. With AutoValue, this is particularly painful, as you have to write the outline of the builder class. With Immutables, there is no need for this.

Of the three projects, AutoValue provides a straightforward simple tool that works, and where the implementation class is hidden (package scoped). Immutables provides a full-featured tool, with many options and ways to generate. By default, the implementation class is publicly visible and used by callers, but there are ways to make it package-scoped (with more code written by you). VALJOGen allows full customisation of the generation template. There is no doubt that Immutables is the most comprehensive of the three projects.

All three annotation processing tools must be setup before use. In general, adding the tool to Maven will do most of the work (Maven support is good). For Eclipse and IntelliJ, these instructions are comprehensive.

Lombok

The Lombok project also uses annotations to control code generation. However, instead of acting as an annotation processor, it hacks into the internal APIs of Eclipse and the Java compiler.

This approach allows code to be generated within the same class, avoiding the need for developers to work with an abstract class or interface. This means that instead of writing abstract methods, the developer writes fields, which is a more natural thing to do.

The key question with Lombok is not what it generates, but the way it generates it. If you are willing to accept the hacky approach, IDE limitations, and the inability to debug into the generated code, then it is a neat enough solution.

For Eclipse, Lombok must be installed, which is fairly painless as there is a GUI. Other tools require other installation approaches, see this page.

Joda-Beans

The Joda-Beans project takes a third approach to code generation. It is a source code regenerator, creating code within the same source file, identified by "autogenerated start/end" comments.

Developers write fields, not abstract methods which is simpler and less code. They also generate code into the same class, which can be final if desired.

One key benefit of generating all the code to the same class is that the code is entirely valid when checked out. There is no need to install a plugin or configure your IDE in any way.

Unlike the other choices, Joda-Beans also provides functionality at runtime. It aims to add C# style properties to Java. What this means in practice is that you can easily treat a bean as a set of properties, loop over the properties and create instances using a standardized builder. These features are the ideal building block for serialization frameworks, and Joda-Beans provides XML, JSON and binary serialization that operates using the properties, generally without reflection. The trade off here is that Joda-Beans is a runtime dependency, so it is only the best option if you use the additional properties feature.

The Joda-Beans regenerator can be run from Maven using a plugin. If you use the standard Eclipse Maven support, then simply saving the file in Eclipse will regenerate it. There is also a Gradle plugin.

Comparing

Most of the projects have some appeal.

  • AutoValue is a simple annotation processor that hides the implementation class, but requires more code to trigger it.
  • Immutables is a flexible and comprehensive annotation processor that can be used in many ways.
  • Lombok requires the least coding by the developer, but the trade-off is the implementation via internal APIs.
  • Joda-Beans is different in that it has a runtime dependency adding C# style properties to Java, allowing code to reliably loop over beans.

My preference is Joda-Beans (which I wrote), because I like the fact that the generated code is in the same source file, so callers see a normal final class, not an interface or abstract class. It also means that it compiles immediately in an IDE that has not been configured when checked out from source control. But Joda-Beans should really only be used if you understand the value of the properties support it provides.

If I was to pick another tool, I would use Immutables. It is comprehensive, and providing you invest the time to choose the best way to generate beans for your needs, it should have everything you need.

Finally, it is important that readers have a chance to look at the code written and the code generated. To do this, I have created the compare-beangen GitHub project. This project contains source code for all the tools above and more, demonstrating what you have to write.

To make best use of the project, check it out and import it into your IDE. That way, you will experience what code generation means, and how practical it is to work with it. (For example, see what happens when you rename a field/method/class. Does the code generator cope?)

Summary

It is time to start writing and using immutable beans instead of mutable ones. The Strata open source market risk project (my day job) has no mutable beans, so it is perfectly possible to do. But to use immutable beans, you are going to need a code generator, as they are too painful to use otherwise.

This blog has summarised five code generators, and provided a nice GitHub project for you to do you own comparisons.

Tuesday, 20 September 2016

Private methods in interfaces in Java 9

Java SE 9 is slowly moving towards the finishing line. One new feature is private methods on interfaces.

Private methods on interfaces in Java 9

In Java 7 and all earlier versions, interfaces were simple. They could only contain public abstract methods.

Java 8 changed this. From Java 8, you can have public static methods and public default methods.

public interface HolidayCalendar {
  // static method, to get the calendar by identifier
  public static HolidayCalendar of(String id) {
    return Util.holidayCalendar(id);
  }
  
  // abstract method, to find if the date is a holiday
  public abstract boolean isHoliday(LocalDate date);
  
  // default method, using isHoliday()
  public default boolean isBusinessDay(LocalDate date) {
    return !isHoliday(date);
  }
}

Note that I have chosen to use the full declaration, with "public" on all three methods even though it is not required. I have argued that this is best practice for Java SE 8, because it makes the code clearer (now there are three types of method) and prepares for a time when there will be non-public methods.

And that time is very soon, as Java 9 is adding private methods on interfaces.

public interface HolidayCalendar {
  // example of a private interface method
  private void validateDate(LocalDate date) {
    if (date.isBefore(LocalDate.of(1970, 1, 1))) {
   throw new IllegalArgumentException();
 }
  }
}

Thus, methods can be public or private (with the default being public if not specified). Private methods can be static or instance. In both cases, the private method is not inherited by sub-interfaces or implementations. The valid combinations of modifiers in Java 9 will be as follow:

  • public static - supported
  • public abstract - supported
  • public default - supported
  • private static - supported
  • private abstract - compile error
  • private default - compile error
  • private - supported

Private methods on interfaces will be very useful in rounding out the functionality added in Java 8.

Saturday, 26 March 2016

Var and val in Java?

Should local variable type inference be added to Java? This is the question being pondered right now by the Java language team.

Local Variable Type Inference

JEP-286 proposes to add inference to local variables using a new psuedo-keyword (treated as a "reserved type name").

We seek to improve the developer experience by reducing the ceremony associated with writing Java code, while maintaining Java's commitment to static type safety, by allowing developers to elide the often-unnecessary manifest declaration of local variable types.

A number of possible keywords have been suggested:

  • var - for mutable local variables
  • val - for final (immutable) local variables
  • let - for final (immutable) local variables
  • auto - well lets ignore that one shall we...

Given the implementation strategy, it appears that the current final keyword will still be accepted in front of all of the options, and thus all of these would be final (immutable) variables:

  • final var - changes the mutable local variable to be final
  • final val - redundant additional modifier
  • final let - redundant additional modifier

Thus, the choice appears to be to add one of these combinations to Java:

  • var and final var
  • var and val - but final var and final val also valid
  • var and let - but final var and final let also valid

In broad terms, I am unexcited by this feature and unconvinced it actually makes Java better. While IDEs can mitigate the loss of type information when coding, I expect some code reviews to be significantly harder (as they are done outside IDEs). It should also be noted that the C# coding standards warn against excessive use of this feature:

Do not use var when the type is not apparent from the right side of the assignment.
Do not rely on the variable name to specify the type of the variable. It might not be correct.

Having said the above, I suspect there is very little chance of stopping this feature. The rest of this blog post focuses on choosing the right option for Java

Best option for Java

When this feature was announced, aficionados of Scala and Kotlin naturally started arguing for var and val. However, while precedence in other languages is good to examine, it does not necessarily apply that it is the best option for Java.

The primary reason why the best option for Java might be different is history. Scala and Kotlin had this feature from the start, Java has not. I'd like to show why I think val or let is wrong for Java, because of that history.

Consider the following code:

 public double parSpread(SwapLeg leg) {
   Currency ccyLeg = leg.getCurrency();
   Money convertedPv = presentValue(swap, ccyLeg);
   double pvbp = legPricer.pvbp(leg, provider);
   return -convertedPv.getAmount() / pvbp;
 }

Local variable type inference would apply fine to it. But lets say that the type on one line was unclear, so we choose to keep it to add clarity (as per the C# guidelines):

 public double parSpread(SwapLeg leg) {
   val ccyLeg = leg.getCurrency();
   Money convertedPv = presentValue(swap, ccyLeg);
   val pvbp = legPricer.pvbp(leg, provider);
   return -convertedPv.getAmount() / pvbp;
 }

Fine, you might say. But what if the code is written in a team that insists on marking every local variable as final.

 public double parSpread(final SwapLeg leg) {
   val ccyLeg = leg.getCurrency();
   final Money convertedPv = presentValue(swap, ccyLeg);
   val pvbp = legPricer.pvbp(leg, provider);
   return -convertedPv.getAmount() / pvbp;
 }

Suddenly, we have a mess. Some parts of the code use final to indicate a "final" (immutable) local variable. Whereas other parts of the code use val. It is the mixture that is all wrong, and it is that mixture that you do not get in Scala or Kotlin.

(Perhaps you don't code using final on every local variable? I know I don't. But I do know that it is a reasonably common coding standard, designed to add safety to the code and reduce bugs.)

Contrast the above to the alternative:

 public double parSpread(final SwapLeg leg) {
   final var ccyLeg = leg.getCurrency();
   final Money convertedPv = presentValue(swap, ccyLeg);
   final var pvbp = legPricer.pvbp(leg, provider);
   return -convertedPv.getAmount() / pvbp;
 }

This is a lot more consistent within Java. final continues to be the mechanism used everywhere to get a final (immutable) variable. And if you, like me, don't worry about the final keyword, it reduces to this:

 public double parSpread(final SwapLeg leg) {
   var ccyLeg = leg.getCurrency();
   Money convertedPv = presentValue(swap, ccyLeg);
   var pvbp = legPricer.pvbp(leg, provider);
   return -convertedPv.getAmount() / pvbp;
 }

I understand the objections many readers will be having right now - that there should be two new "keywords", one for mutable and one for immutable local variables and that both should be of the same length/weight (or that the mutable one should be longer) to push people to use the immutable form more widely.

But in Java it really isn't that simple. We've had the final keyword for many years. Ignoring it results in an unpleasant and inconsistent mess.

Summary

I don't personally like local variable type inference at all. But if we are to have it, we have to make it fit well within the existing language.

I argue that val or let simply does not fit Java, because final already exists and has a clear meaning in that space. While not ideal, I must argue for var and final var, as the only combination on offer that meets the key criteria of fitting the existing language.

Tuesday, 22 December 2015

Explicit receiver parameters

I discovered that Java 8 has a language feature I'd never heard of before today!

Explicit receiver parameters

Consider a simple method in Java 7:

 public class Currency {
   public String getCode() { ... }
 }

In Java 8, it turns out there is a second way to write the method:

 public class Currency {
   public String getCode(Currency this) { ... }
 }

The same trick also works for methods with arguments:

 public class Currency {
   public int compareTo(Currency this, Currency other) { ... }
 }

So, what is going on here?

The relevant part of the Java Language Specification is here.

The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable, it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.

The new feature is entirely optional, and exists to allow the type to be annotated at the point it is used:

 public class Currency {
   public int compareTo(@AnnotatedUsage Currency this, Currency other) { ... }
 }
 @Target(ElementType.TYPE_USE)
 public @interface AnnotatedUsage {}

The annotation is made available in reflection using Method::getAnnotatedReceiverType().

Looking to the future

I discovered this feature in the context of Project Valhalla, the effort to add value types to Java. One possible syntax being considered to allow different methods on List<int> from List<String> is to use receiver types:

 public class List<any T> {
   public int sum(List<int> this) { ... }
 }

This syntax would be used to define a sum() method that only applies when List is parameterized by int, and not when parameterized by anything else, such as String.

For more information, see this email to the Valhalla experts mailing list. But please note that the list is read-only, cannot be signed up to and is for pre-selected experts only. In addition, everything discussed there is very, very early in the process, and liable to change greatly before being released in a real version of Java (such as Java 10).

Summary

Java 8 has a new language feature which you've probably never heard of and will probably never use. But at least you now have some knowledge that you can use to prove you are a Java Guru!

Tuesday, 1 September 2015

Naming Optional query methods

In the last article I outlined a pragmatic approach to Java 8's Optional class. In this one I'm looking at how we should name query methods that might return Optional.

Convenience method naming

Consider a requirement to produce a tree data structure, perhaps something like XML DOM. The basic data structure might look something like this:

 public XmlElement {
   private final String name;
   private final String content;
   private final Map<String, String> attributes;
   private final List<XmlElement> children;
 }

(This article uses this as an example, but many other data structures or domain objects face similar issues, so don't get too caught up in the "XML"-ness of the example, and it's inability to represent every last subtlety of XML.)

The key question for this article is about the convenience methods this class exposes. Using standard best practices, an element with no children should return an empty list, and an element with no attributes should return an empty map. Similarly, we can use the empty string, "", when there is no content.

 public XmlElement {
   public String getName() {...}
   public String getContent() {...}
   public Map<String, String> getName() {...}
   public List<XmlElement> getChildren() {...}
 }

This approach is fine, and allows us to fully query this immutable data structure. But it would be nice to have some additional convenience methods. The main one to consider is a method to return the value of an attribute by name. The naive implementation would be:

 public XmlElement {
   public String getAttribute(String name) {
     return attributes.get(name);
   }
 }

But, this method can return null which the last article recommended against. The not so naive implementation would be:

 public XmlElement {
   public Optional<String> getAttribute(String name) {
     return Optional.ofNullable(attributes.get(name));
   }
 }

This is better, as null is no longer returned and it is now clear that there is a failure case to consider. However, what if the calling code knows that the data it is asking for is expected to be there, and is going to throw an exception if it isn't?

The "standard" approach in that case is to use the method Optional.orElseThrow() on the result of the last method. And that is good advice. But, equally, if the same call to orElseThrow() follows lots of calls to the new helper method, it may be a sign that the convenience method isn't helping as much as it should! As such, perhaps it is worthy of a helper method itself:

 public XmlElement {
   public String getAttribute(String name) {
     String value = attributes.get(name);
     if (value == null) {
       throw new IllegalArgumentException(
           "Unknown attribute '" + name + "' on element '" + this.name + "'"));
     }
     return value;
   }
 }

(Note that this follows the last article's recommendation to use null, not Optional, within the methods of a class.)

So, this is better for the many use cases where it is a failure case anyway if the attribute is missing. ie. where the caller knows that the attribute is defined to be mandatory, and it is necessarily an exception if it is missing.

In reality though, some attributes are going to be mandatory and some are optional. Which brings us to the point of this article, and design approach for a case like this, and the ensuing naming problem. My suggestion is to have two methods:

 public XmlElement {

   // throw exception if no attribute
   public String getAttribute(String name) { ... }

   // return empty optional if no attribute
   public Optional<String> findAttribute(String name) { ... }
 }

In this approach, there are two methods, and the caller can choose one method if they want the exception when the name is not found, and the other method if they want to handle the missing case.

The need for this approach is relatively rare - it needs to be a method that can be used in both ways, mandatory and optional. It also needs to be an API that will be called enough for the value of the two helper methods to outweigh the extra cost. But when it does crop up, it needs a good naming convention as the two methods cannot be overloads. And that is what I'm proposing here.

  • Name the method that throws an exception when not found getXxx(String)
  • Name the method that returns an optional findXxx(String)

With this approach, both methods are available, and have reasonable names. It seems to me, that when this kind of situation arises, the mandatory case is typically most common, and thus it gets the "get" name.

There are other possible naming approaches to this "near overload". But I've settled on this one as the right balance for my APIs.

Note however, that this is not a suggestion to name all methods returning an Optional something like findXxx(String). Only use it when appropriate, such as when paired with an exception throwing version do I think this makes sense.

Summary

This article outlines a naming approach for when you need overloaded convenience methods on an API, typically for accessing a collection, such as a map or list. It proposes adding one method, getXxx(String), that throws an exception when the key cannot be found, and a second method findXxx(String), that returns an empty optional when the key is not found.

Update 2015-10-15

The original version of this article proposed the name "getXxxOptional()". I've changed that to "findXxx()" based on the comments and experimentation with both options. Its clear to me now that "findXxx()" is a way better method name than "getXxxOptional()" for a situation like this.

Thursday, 13 August 2015

Java SE 8 Optional, a pragmatic approach

The Optional classs in Java 8 is a useful tool to help developers manage data. But advice on how to use it varies. This is my take on one good approach to using Optional in Java 8.

Note that this article assumes you know what Optional is and how it works. See my previous article and other tutorials for more info. Also, be aware that Optional is a heavily argued topic, with some commentators liable to get rather too excited about its importance.

A pragmatic approach to Optional in Java 8

What follows is a specific approach to using Optional in Java 8 that I have found very useful. It should be considered that the approach has been developed in terms of writing a new application, rather than maintaining an existing one. There are five basic points:

  1. Do not declare any instance variable of type Optional.
  2. Use null to indicate optional data within the private scope of a class.
  3. Use Optional for getters that access the optional field.
  4. Do not use Optional in setters or constructors.
  5. Use Optional as a return type for any other business logic methods that have an optional result.

For example:

  public class Address {
    private final String addressLine;  // never null
    private final String city;         // never null
    private final String postcode;     // optional, thus may be null

    // constructor ensures non-null fields really are non-null
    // optional field can just be stored directly, as null means optional
    public Address(String addressLine, String city, String postcode) {
      this.addressLine = Preconditions.chckNotNull(addressLine);
      this.city = Preconditions.chckNotNull(city);
      this.postcode = postcode;
    }

    // normal getters
    public String getAddressLine() { return addressLine; }
    public String getCity() { return city; }

    // special getter for optional field
    public Optional<String> getPostcode() {
      return Optional.ofNullable(postcode);
    }

    // return optional instead of null for business logic methods that may not find a result
    public static Optional<Address> findAddress(String userInput) {
      return ... // find the address, returning Optional.empty() if not found
    }
  }

The first thing to notice about this users of our address API are protected from receiving null. Calling getAddressLine() or getCity() will always return a non-null value, as the address object cannot hold null in those fields. Calling getPostcode() will return an Optional<String> instance that forces callers to at least think about the potential for missing data. Finally, findPostcode() also returns an Optional. None of these methods can return null.

Within the object, the developer is still forced to think about null and manage it using != null checks. This is reasonable, as the problem of null is constrained. The code will all be written and tested as a unit (you do write tests don't you?), so nulls will not cause many issues.

In essence, what this approach does is to focus on using Optional in return types at API boundaries, rather than within a class or on input. Compared to using it as a field, optional is now created on-the-fly. The key difference here is the lifetime of the Optional instance.

It is often the case that domain objects hang about in memory for a fair while, as processing in the application occurs, making each optional instance rather long-lived (tied to the lifetime of the domain object). By contrast, the Optional instance returned from the getter is likely to be very short-lived. The caller will call the getter, interpret the result, and then move on. If you know anything about garbage collection you'll know that the JVM handles these short-lived objects well. In addition, there is more potential for hotspot to remove the costs of the Optional instance when it is short lived. While it is easy to claim this is "premature optimization", as engineers it is our responsibility to know the limits and capabilities of the system we work with and to choose carefully the point where it should be stressed.

While it is a minor point, it should be noted that the class could be Serializable, something that is not possible if any field is Optional (as Optional does not implement Serializable).

The approach above does not use Optional for inputs, such as setters or constructors. While accepting Optional would work, it is my experience that having Optional on a setter or constructor is annoying for the caller, as they typically have the actual object. Forcing the caller to wrap the parameter in Optional is an annoyance I'd prefer not to inflict on users. (ie. convenience trumps strictness on input)

On the downside, this approach results in objects that are not beans. The return type of the getter does not match the type of the field, which can cause issues for some tools. Before adopting this approach, check that any tool you use can handle it, such as by directly accessing the field.

If adopted widely in an application, the problem of null tends to disappear without a big fight. Since each domain object refuses to return null, the application tends to never have null passed about. In my experience, adopting this approach tends to result in code where null is never used outside the private scope of a class. And importantly, this happens naturally, without it being a painful transition. Over time, you start to write less defensive code, because you are more confident that no variable will actually contain null.

The key to making this approach work beyond the basics is to learn the various methods on Optional. If you simply call Optional.get() you've missed the whole point of the class.

For example, here is some code that handles an XML parse where either "effectiveDate" or "relativeEffectiveDate" is present:

 AdjustableDate startDate = tradeEl.getChildOptional("effectiveDate")
   .map(el -> parseKnownDate(el))
   .orElseGet(() -> parseRelativeDate(tradeEl.getChildSingle("relativeEffectiveDate")));

Breaking this down, tradeEl.getChildOptional("effectiveDate") returns an Optional<XmlElement>. If the element was found, the map() function is invoked to parse the date. If the element was not found, the orElseGet() function is invoked to parse the relative date.

For a large enterprise-style codebase that uses this approach to Optional, see OpenGamma Strata, a modern open source toolkit for the finance industry.

See also Joda-Beans code generation, which can generate this pattern (and much more).

Finally, it should be noted that some future Java version, beyond Java 9, will probably support value types. In this future world, the costs associated with Optional will disappear, and using it far more widely will make sense. I simply argue that now is not the time for an "optional everywhere" approach.

Summary

This article outlines a pragmatic approach to using Optional in Java 8. If followed consistently on a new application, the problem of null tends to just fade away.

Any comments?

Monday, 8 December 2014

What might a Beans v2.0 spec contain?

What features should be in scope and out of scope for a Beans specification v2.0?

Note: I am an independent blogger, not an Oracle employee, and as such this blog is my opinion. Oracle owns the JavaBeans trademark and controls what actually happens to the specification.

Update 2015-01-03: New home page for the Beans v2.0 effort now available!

JavaBeans v1.0

My last blog examined the contents of the current JavaBeans (TM) specification. The key feature elements can be summarized as follows:

  • Properties - accessed using getter and setter methods
  • Events - change events for properties
  • Methods - all public methods
  • BeanInfo - permits customization of properties, events and methods
  • Beans - a utility class to access the features
  • Property editor - a mechanism to edit properties, including conversion to and from a string format
  • GUI support - allows a bean to be manipulated visually

These features were a good fit for 1997, given that the original goal was to be a component system, interoperating with other similar systems like COM/DCOM. These features are no longer what we need, so any Beans v2.0 is naturally going to look a lot different.

Beans v2.0 - Data abstraction

The key goal of a Beans v2.0 spec is to define an abstraction over the data in an object.

When such an abstraction exists, frameworks and libraries become far simpler to write and interact with. For example, a serialization framework at its most basic level simply needs to iterate over all the beans and properties in an object graph in order to perform its task.

In addition to frameworks, many ad-hoc coding tasks become simpler because it is much easier to walk over the object graph of beans and properties. For example, to find all instances of a particular type within an object graph starting from an arbitrary bean.

The data abstraction needs to be fully round-trip. The spec must allow for data to be read from a bean into another format. But it must also provide the tools to allow the original bean to be recreated from the data previously read.

Beans v2.0 - Mutable vs Immutable

The JavaBean v1.0 specification implicitly defines mutable objects. It requires all beans to have a no-args constructor, thus the only way for the properties to get populated is through the use of setters. This mutability is one of the key complaints that people have about JavaBeans, and often Java itself by association.

Any Beans v2.0 specification must support immutable objects.

Immutable classes are now a common design approach to systems and are increasingly popular. Supporting them is thus vital to encompass the range of data objects in use today.

Any Beans v2.0 specification must also still support mutable objects. While there are those that turn their nose up at any mutability, it is still a perfectly valid choice for an application. The decision between mutable and immutable data objects is a trade-off. The Beans v2.0 spec needs to support both options.

The implications of supporting immutable is that an alternative to a no-args constructor and public setters will be needed to support construction. This is likely to be a "bean builder" of some kind.

Beans v2.0 - Beans and Properties

The term "bean" is often associated with a specific Java class, such as Person. The term "property" is often associated with a single field on the class, such as surname or forename.

Any Beans v2.0 spec must not have a reflection-based view of beans and properties.

Firstly, a property is not the same as a field (instance variable). Fields hold the state of an object, but not necessarily in the form that the object wishes to expose (it might be stored in an optimised format for example). As such, it must be possible for a bean to control the set of properties that it publishes.

Secondly, it can be desirable to a bean with a dynamic set of properties. This might consist of a bean with a fixed set of base properties and an extensible map of additional ones, or a bean which is entirely dynamic, much closer to the data model of many dynamic languages.

The implications of this is that there is not a one-to-one mapping between a bean and a Class, nor is there a one-to-one mapping between a property and a java.lang.reflect.Field.

The JavaBeans v1.0 spec treats indexed properties in a special way. I can see no reason to do that in Beans v2.0, particularly given the range of collection types now in use.

Beans v2.0 - Getters and Setters

The current JavaBeans v1.0 spec requires there to be a physical java.lang.reflect.Method instance for both the getter and setter. What Beans v2.0 needs to provide is an abstraction away from this, as it provides many more options.

Any Beans v2.0 spec must not require data access via a java.lang.reflect.Method.

Moving away from direct exposure of reflection raises the level of abstraction. It permits alternative object designs to be exposed as beans.

For example, consider a bean that has no public getters and setters. With the Beans v2.0 abstraction, this could still expose its data as properties, providing interoperation with frameworks, but encapsulating the data for most programmatic uses. This tackles another big criticism of JavaBeans, which is that they cause state to be exposed rather than hidden.

Another example is the HashMap based bean. In this case a Method does not exist for each property, just a single get by name. Being able to expose this as a bean provides the desired dynamic behaviour.

The implications of this are simply that the Beans v2.0 spec abstraction will simply be long the lines of the Map interface get and put.

Beans v2.0 - Annotations

The current JavaBeans v1.0 spec predates annotations in Java. But annotations are now key to many programming practices in Java.

Any Beans v2.0 spec must provide access to property and bean annotations.

Annotations are represented by implementations of the Annotation interface. It so happens that the Annotation interface is not part of reflection. It is possible to implement an annotation yourself (apart from a compiler warning).

What is needed is for the Beans v2.0 spec abstraction to provide access to the set of annotations on the bean, and the set of annotations on each property without going via reflection. With this step, and the ones above, many direct uses of reflection will completely disappear, with the Beans v2.0 abstraction being good enough.

Beans v2.0 - Events

The current JavaBeans v1.0 spec considers events to be first class parts of the abstraction.

There is no good reason to include events in the Beans v2.0 spec.

The current JavaBeans v1.0 spec is GUI focussed, and as such events were an essential element. But the Beans v2.0 spec outlined here focuses on a different goal, abstracting over the data in the object. Round-tripping data from a bean to another format and back to a bean does not require events or a GUI.

There will be those reaching for the comments box right now, demanding that events must be included. But think carefully and you should realise that you don't need to.

None of what is proposed here for Beans v2.0 takes away what works today with JavaBeans v1.0. GUI developers can still carry on using the same getters, setters and events that they do today, including bound and constrained properties. The java.beans package will continue to exist and continue to be available. In addition, JavaFX is the way forward for Java GUIs, and it has its own approach to properties.

Beans v2.0 - Conversion to/from String

The current JavaBeans v1.0 spec includes PropertyEditor. One of the use cases of the class, notably in Spring framework, is to convert a simple object (typically a VALJO) to and from a String. For example, this includes Integer, Enum, Class and Currency.

Any Beans v2.0 spec must tackle conversion to/from a String for simple types.

The most common use case for the Beans v2.0 spec will be to iterate over the object graph and process it in some way, such as to write out a JSON or XML message. In order for this to be practical, all objects in the object graph need to be either a bean, or a simple type convertible to a string. As such, simple type string conversion is very much needed to round out the spec.

The Joda-Convert project contains a simple set of interfaces and classes to tackle this problem, and I imagine any Beans v2.0 spec solution would be similar.

Beans v2.0 - But what does a bean actually look like?

Part of the goal of Beans v2.0 is to allow for different kinds of bean. Immutable as well as mutable. Private getters and setters as well as public. Dynamic map-based structures as well as field-based ones.

Any Beans v2.0 spec should not overly restrict how beans are implemented.

We know that Oracle has no current plans for properties at the language level. As such, it also makes little sense for Beans v2.0 spec to specify a single approach for how classes should be designed. Instead, the spec aims to allow classes that are designed in different ways to all agree on a common way to interact with frameworks and libraries that does not require getters, setters and a no-args constructor.

The Joda-Beans, Lombok, Immutables and Auto projects (and many others) all provide different ways to create beans without writing manual code. All could be adapted to work with the proposed Beans v2.0 spec, as could frameworks like Jackson, Hibernate, Dozer and Groovy (to name but a few).

The simple answer is that the bean could look just like it does today with getters and setters. The real answer is that the bean may look any way it likes so long as it can expose its data via the Beans v2.0 API.

Summary

The current JavaBeans v1.0 spec is very old and not that useful for the kinds of applications we build today. This blog has outlined my opinion on what direction a Beans v2.0 spec should take:

  • Focussed on data abstraction
  • Support for Mutable and Immutable beans
  • Fully abstracted from reflection
  • No requirement for getters and setters
  • No requirement for a no-args constructor
  • Support for dynamically extensible properties
  • Access to bean and property annotations
  • Conversion of simple types to and from a String
  • No support for events

Feel free to comment on the high-level scope outlined above. In particular, if you develop a project that uses the JavaBeans spec (directly or indirectly), please comment to say whether the proposed spec is likely to be sufficient to cover your use cases.

I've also started work on a prototype of the code necessary to support the spec. So also feel free to raise pull requests or join the mailing list / group.