Java Properties BeanUtopia
Yardena MeymannFebruary 2008
What is a property?
Property is an element of data type description. For example, name of objects of type Person.
It consists of a symbolic token “name” associated with a certain (owner) data type and another (value) data type.
Property are used to describe and manipulate data of various kinds (databases, UI, …)
Property in modern Object Oriented languages
Java, C++, C#, Delphi
(Also known as field) Properties defined by owner classes Property values are stored in and accessed
via the owner object instance Inheritance of properties Override of properties Access methods defined in the owner class
(getter/setter) Property references are not part of the core
language, can be accessed via reflection on owner classes
Property in databases and SQL
(Usually called columns) Can be referenced via owner type (table),
regardless of owner instance; used to construct expressions
Can be manipulated (added, removed, changed) via operations on owner type
Can have constraints and triggers Can be computed or stored Storage method is abstracted from the user
(can be row-based or column-based)
Property anatomy
Propertytype
Ownertype
Ownerinstance
Valuetype
Propertyinstance
Valueinstance
Properties in Java: JavaBeans
Actual fields are usually private for encapsulation purposes
Most common way of exposing properties in Java is JavaBeans naming convention, essentially a pair of methods with get and set prefixes.
java.beans.* package (aimed mainly for UI components) adds more abstraction layers over basic beans, but does not solve the problems discussed in the next slides
Properties in Java: Maps
HashMap, HashTable, etc. are different implementations that store properties by generic key:value pairs
Maps allow “dynamic” properties – unless the key is an enum type, set of keys is not restricted by the compiler
To store multi-type values the Map is defined to accept the most specific common value type or a some canonic (e.g. String) representation of the value – not type-safe
JEEJEETierTier
Typical JEE Application Example
ServletServlet
BrowserBrowser
BusinessBusinessLogicLogic
DataDataAccessAccess
DatabaseDatabase
Transform HttpRequest Strings map or XML to
object
Map object to relational
representation: templates or
ORM
JSP/JSF/…JSP/JSF/…
BrowserBrowser
BusinessBusinessLogicLogic
DataDataAccessAccess
Transform map-like ResultSet
entries to objects: DAO or ORM
Template around object properties, transform to view
representation
Pass objects through set of rules and
policies
Post-process results
Single user operation processing round-trip
Typical JSE Application
Swing: Beans Binding JSR 295
Conclusion: Java needs proper support for properties.
Flaws of Java Properties
JavaBean properties are verbose a lot of manual boiler plate coding
Reference to properties by String only error prone
No way to add properties to beansredefinition only by means of bytecode manipulation and
aspects No property declaration
Cannot associate meta-data, aspects No abstraction over different implementations:
beans and maps (BeanUtils) Maps – not type safe
requires casts and translations to/from Strings
Flaws of Java Properties - Verbosity
In order to create a single mutable property the programmer needs a minimum of 7 lines of code. Indexed property requires at least 13.
When one starts adding property change listeners etc. the boiler-plate code bloats and bloats.
Flaws of Java Properties – Reference by String
Error prone: lack of or typo in property reference property access method
isn’t detected until runtime and the error is not predictable.
Flaws of Java Properties – Scattered definitions No single property declaration – the references are
associated with the getter, setter, field, embedded in various Strings – practically no way to track.
No way to associate meta-data (e.g .annotations), constraints, conversions, aspects, mappings etc. with a property declaration.
Example: default value is initially referenced by all instances of the object, instead of being an attribute of the property declaration itself. Same goes for constraints (not null, etc.), supported conversions and notifications. These definitions associated with property declarations are supported in DDLs.
Flaws of Java Properties – no abstraction
The object is either a bean or a map, core Java requires that property is used this way or the other, while it shouldn’t matter to the user
BeanUtils solve this, but rely on Strings to express properties
Flaws of Java Properties – no dynamicity It is not possible to add new JavaBean
property or modify aspects associated with existing JavaBean properties at run-time
This is a problem: systems that require reliability and need to be up 99.9999… % of the time, but also need to be upgraded and require data schema update without restart.
Just for the programming purposes it is convenient to define new “temporary” fields for existing objects or make type-safe maps (ala tuples) without creating new classes
BeanUtils
Project of Apache Commons, several useful features: Abstraction over beans and maps,
DynaBean “Safe” map wrappers Type converters Support for “path” – composition of
properties Support for ServletRequest and ResultSet
BeanUtils quick overview
DynaClass, DynaBean, MutableDynaClass, DynaPropertyLets access maps or beans as if they
were mapsLets access beans content via
expressions PropertyUtils.getProperty(person, “address.street”)
Supports locales and conversions
BeanUtils - problems
Everything is based on Strings
Not “modernized” – stuck in Java 4, no support or use of generics, annotations, enums etc.
commons.Collections google.Collections, wishing to do the same for BeanUtils
Property – new generation
We’d like to take “best of both worlds” while avoiding contradicting qualities. Is it possible?
Abstraction is the way.
Instead of focusing on a Bean object, focus on the Property itself.
Introducing BeanUtopia
While most of the developed solutions require changing Java syntax or modifying the compiler, BeanUtopia is a library.
Non-intrusive: try to avoid source-generations and avoid or minimize the use of on-the-fly byte-code generation, in case it will be required (to improve performance for example), use built-in tools such as APT, javax.tools, java.lang.instrumentation
More BeanUtopia
Placing Property object in the center of the picture: Property<Owner,Value>
Several built-in implementation and ability to extend or provide new ones
Property is not bound to object instance Read-only and read-write properties Properties are inheritted Property extends Function Function chaining Dynamic, predicate-based redefinition
BeanUtopia Property
AbstractProperty<B,V>String nameV valueTypeB beanTypeClass namespaceClass<? extends
AbstractProperty<B,V>> idAnnotation[] annotations
AbstractProperty
Property
UpdatableProperty
Function
Value
BeanUtopia Property
Property<B,V> V defaultValue() V of(B bean)
UpdatableProperty<B,V> List<Constraint<? super V>> constraints() assign(B bean, V value) Value value(V value) Host host(B bean) ???
class Rectangle extends IntraMap { //definitionstatic final UpdatableProperty<Rectangle, Integer> length = new UpdatableProperty<Rectangle, Integer>(0, notNull()) {};
static final UpdatableProperty<Rectangle, Integer> width = new UpdatableProperty<Rectangle, Integer>(0, notNull(), nonNegativeInteger()) {};
Rectangle(UpdatableProperty<? super Rectangle, ?>.Value... args) { PropertyUtils.populate(this, args)
}
}
class RectangleTest { //usagepublic static void main(String[] args) {
Rectangle r = new Rectangle(length.value(10), width.value(5));assert(width.of(r) == 5);
}
}
Example 1-1
default
constraints
class Box extends Rectangle { //definitionstatic final UpdatableProperty<Rectangle, Integer> height = new UpdatableProperty<Rectangle, Integer>(0, notNull()) {};
Box(UpdatableProperty<? super Box, ?>.Value... args) { PropertyUtils.populate(this, args)
}}
class BoxTest { //usagepublic static void main(String[] args) {
Box b = new Box(length.value(10), width.value(5), height.value(4));assert(height.of(b) == 4);
}}
Example 1-2
class Apple {
private String _color = null;
public Apple() {}
public Apple(String color) { this._color = color; }
public String getColor() { return _color; }
public void setColor(String color) { _color = color; }
}
Example 2
class AppleTest { static final UpdatableProperty<Apple,String> color =
new UpdatableProperty<Apple,String>() {};
public static void main(String[] args) { Apple a = new Apple(“red”); assert(color.of(a).equals("red"));
color.assign(a, “yellow”);
assert(a.getColor().equals(“yellow”)); }}
reflection
reflection
Example 3
static final UpdatableProperty<Object,String> descripion = new UpdatableProperty<Object,String>("description") {};
{
Object x = new Object();
descripion.assign(x, "Hello World");
assert(descripion.of(x).equals("Hello World"));
}
MAGIC
Property Definition
This is how property is actually implemented: given property and object what is the
value? (Projection = Function)given updatable property, object and a
new value, make the association (Injection)
Example 4
static final Property<Object,String> toString =
new Property<Object,String>("n.a.") {};
{
toString.define(
new Function<Object,String>() {
public String apply(Object object) {
return object.toString();
}
});
}
Property definition types
Reflected Mapped by property name (String) Intra-Mapped
HasProperties interfaceIntraMap class
Extra-Mapped Imported can be extended…
Intra-Mapped properties
Base bean holds a container for propertiesNow implemented with MapFuture: array
Extra-Mapped properties
Person1 Integer: ageString: nameLong: id
Person2 Integer: ageString: nameLong: id
AgeMap<Person,Integer>
NameMap<Person,String>
IdMap<Person,Long>
Imported property
static final Property<Object,Integer> cardinality = new Property<Object,Integer>(0) {};{ defineImported(cardinality, ImporterTest.class);}public static void main(String[] args) { assertTrue(cardinality.apply(null) == 0); assertTrue(cardinality.apply(5) == 1); assertTrue(cardinality.apply(Arrays.asList(1,2,3)) == 3); assertTrue(cardinality.apply(new int[] { 1,2,3 }) == 3);}
public class ImporterTest { public static int getCardinality(Object o) { return 1; } public static int getCardinality(Object[] o) { return o.length; } public static int getCardinality(Collection c) { return c.size(); } public static int getCardinality(Map m) { return m.size(); }}
Property re-definition
Policy<I,O> = List<Predicate<I> + O>
FunctionPolicy<I,O> = Policy<I, Function<I,O>>
Property definition is a policy Based on the quality of parameter bean
(usually its class) the actual definition is chosen
Definition policy is open for modifications (additions etc.)
Policy is ordered (…)
Property chaining and null safety
class CompositeFunction<A,B> implements Function<A,B> {
final Function<A,B> function;
<C> CompositeFunction<A,C> compose(final Function<? super B,C> f) {
return new CompositeFunction<A,C>(new Function<A,C>(){
public C apply(A from) {
return f.apply(CompositeFunction.this.apply(from));
}
});
}
B apply(A from) {
return function.apply(from);
}
}
{
Person p = …;
Property<Person,Address> address = …;
Property<Address,Street> street = …;
String street = self(Person.class).compose(address).
compose(street).apply(p);
}
Management of Properties
Get properties by bean class, including inherited ones
BiDi Map between property id and instance
…
Multi-value properties
Open Issue
Mapped definition – type conversions
Open Issue
Binding/Hosting
Open Issue
Adding special behavior
Open IssueTransactionsThreadLocalAtomicDifferent reference types
Other possible directions
Integration with Quare Full type-safe reflection Modularity Auto-generate from existing Java
code As above, but from DDL, XSD, …
Qi4j
New library (alpha) many innovative concepts
Property = mix-in Mix-in expressed as Java interface
interface Name { String getName(); setName(String name);}interface Age { int getAge(); setAge(int age);}class Person implements Name, Age { … }
.NET - LINQ
Simplifies and unifies the implementation of any kind of data accessData can belong to different domains (db,
array, object, XML, file) and each one has its own access protocol. LINQ offers a uniform way to access and manage data without forcing any particular model.
Introduces queries as first-class concept into .NET languages
LINQ - example
Codevar query =
from c in Customers
where c.Country == “Italy”
select c.CompanyName;
Results is list of strings.foreach (string name in query) {
Console.WriteLine(name);
}
LINQ for Java - Quare
Scala Properties
sourceforge: Joda Beans
java.net Bean Properties
java.net Properties
Top Related