Property - Google Project Hosting
Download
Report
Transcript Property - Google Project Hosting
Java Properties
BeanUtopia
Yardena Meymann
February 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
Property
type
Value
type
Value
instance
Owner
type
Property
instance
Owner
instance
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
Typical JEE Application
Example
Browser
Transform
HttpRequest
Strings map or
XML to object
Servlet
Pass objects
through set of
rules and
policies
Business
Logic
Map object to
relational
representation:
templates or
ORM
Single user operation
processing round-trip
Browser
JSP/JSF/…
JEE
Tier
Data
Access
Business
Logic
Data
Access
Database
Template around
object properties,
transform to view
representation
Postprocess
results
Transform map-like
ResultSet entries
to objects: DAO or
ORM
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 beans
redefinition 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, DynaProperty
Lets access maps or beans as if they
were maps
Lets 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 sourcegenerations 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 name
V valueType
B beanType
Class namespace
Class<? extends
id
Annotation[] annotations
AbstractProperty<B,V>>
Abstract
Property
Property
Updatable
Property
Value
Function
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) ???
Example 1-1
class Rectangle extends IntraMap { //definition
static final UpdatableProperty<Rectangle, Integer> length =
new UpdatableProperty<Rectangle, Integer>(0, notNull()) {};
default
constraints
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 { //usage
public static void main(String[] args) {
Rectangle r = new Rectangle(length.value(10), width.value(5));
assert(width.of(r) == 5);
}
}
Example 1-2
class Box extends Rectangle { //definition
static final UpdatableProperty<Rectangle, Integer> height =
new UpdatableProperty<Rectangle, Integer>(0, notNull()) {};
Box(UpdatableProperty<? super Box, ?>.Value... args) {
PropertyUtils.populate(this, args)
}
}
class BoxTest { //usage
public static void main(String[] args) {
Box b = new Box(length.value(10), width.value(5), height.value(4));
assert(height.of(b) == 4);
}
}
Example 2
class Apple {
class AppleTest {
static final UpdatableProperty<Apple,String> color =
new UpdatableProperty<Apple,String>() {};
private String _color = null;
public static void main(String[] args) {
Apple a = new Apple(“red”);
assert(color.of(a).equals("red"));
public Apple() {}
public Apple(String color) {
this._color = color;
}
reflection
public String getColor() {
return _color;
}
public void setColor(String color) {
_color = color;
}
}
color.assign(a, “yellow”);
reflection
assert(a.getColor().equals(“yellow”));
}
}
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 interface
IntraMap class
Extra-Mapped
Imported
can be extended…
Intra-Mapped properties
Base bean holds a container for
properties
Now implemented with Map
Future: array
Extra-Mapped properties
Person1
Integer: age
String: name
Long: id
Age
Map<Person,Integer>
Name
Map<Person,String>
Person2
Integer: age
String: name
Long: id
Id
Map<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));
}
});
{
}
Person p = …;
B apply(A from) {
Property<Person,Address> address = …;
return function.apply(from);
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 Issue
Transactions
ThreadLocal
Atomic
Different 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 access
Data 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
Code
var 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