Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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