Orthogonal Persistence in Java Supported by Aspect- Oriented Programming and Reflection
Total Page:16
File Type:pdf, Size:1020Kb
CORE Metadata, citation and similar papers at core.ac.uk Provided by Repositório Científico do Instituto Politécnico do Porto Orthogonal Persistence in Java supported by Aspect- Oriented Programming and Reflection Rui Humbero R. Pereira J.Baltasar García Perez-Schofield Instituto Superior Contabilidade e Administração do Porto Departamento de Informática ISCAP/IPP Universidad de Vigo Porto, Portugal Vigo, España [email protected] [email protected] Abstract — The persistence concern implemented as an aspect the database. It was designed to be totally reusable without the has been studied since the appearance of the Aspect-Oriented need of any kind of adaption on the code. The following code paradigm. Frequently, persistence is given as an example that fragment shows the way an application can interact with data can be aspectized, but until today no real world solution has objects. applied that paradigm. Such solution should be able to enhance the programmer productivity and make the application less CPersistentRoot psRoot; prone to errors. To test the viability of that concept, in a previous Student student; study we developed a prototype that implements Orthogonal Student student2; Persistence as an aspect. This first version of the prototype was Course course; already fully functional with all Java types including arrays. In this work the results of our new research to overcome some // get a persistent root (psRoot) limitations that we have identified on the data type abstraction psRoot=new CPersistentRoot(); and transparency in the prototype are presented. One of our goals was to avoid the Java standard idiom for genericity, based //Get one Student object from the psRoot (the on casts, type tests and subtyping. Moreover, we also find the database) need to introduce some dynamic data type abilities. We consider student=psRoot.getRootObject("rui"); that the Reflection is the solution to those issues. To achieve that, we have extended our prototype with a new static weaver that preprocesses the application source code in order to introduce //Get one Course object from the psRoot (the database) changes to the normal behavior of the Java compiler with a new generated reflective code. course=psRoot.getRootObject("TO"); Keywords-component; aspect-oriented programming; reflection; //Associate the persistent Student object with the genericity, type inference; type erasure; framework; persistent Course course.addStudent(student); I. INTRODUCTION // Instantiates a new Student object (still transient) The initial version of the aof4oop [1][2] framework was student2=new Student(1234,”Student Name”,”Student already a fully functional system capable of providing Address”); Orthogonal Persistence [3] on any Java type, including arrays, to a software application. Using this framework prototype, the // Turns the student2 persistent simply because it application can easily and transparently manage its data objects is associated to another persistent object physically stored in a database. The current version only course.addStudent(student2); supports DB4Objects [4] as backend database and was not developed with performance goals. This form of persistence treats orthogonally all objects, This prototype, despite its limitations, demonstrated following the three principles formulated by Atkinson and some of the advantages of Orthogonal Persistence in terms of Morrison [3]. Their state persistence is only dependent if they productivity and final code quality. It implements the are associated with another persistent object, or not, that is, if persistence concern as an Aspect, maintaining the application they are reachable by another persistent object [3]. oblivious [5] of any technical details about the interaction with In the next section we will briefly describe the system III. GENERITICY architecture of the developed framework. Since the objects obtained from persistent root In the section III we will discuss the implementation of psRoot can be from any type, the method Genericity in the Java platform and the drawbacks of the type getRootObject(String rootName) must return an erasure approach adopted in the version 5.0 of this platform. object from the class Object. But when that return value is We will also debate the implications of the type erasure for the assigned to a Student, a Course or any other type of reference, parametric polymorphism and the persistence. the static type checking rules of the compiler requires a cast Object Sections IV and V will present the recently from to the actual type of the persistent object improvements supported on Generics to the transparency and obtained from database. data abstraction of the prototype. We will also describe a new Generics support came with the 5.0 version of the Java extension to our prototype that allows going even further into platform. This new feature was introduced to solve similar its orthogonality. problems, such as type checking on data collections. Before In the section VI we will debate the drawbacks of that support for generics appeared, the object references when put improvement and finish this study with some conclusions. on a collection (an ArrayList for instance) were considered as Object, the top level class in the hierarchy of the Java II. THE PROTOTYPE FRAMEWORK classes. The types of those objects were not tested, so any type The developed framework provides orthogonal could be added to that collection. A cast is mandatory in the persistence services to an application that can easily and opposite phase, when any object is retrieved from that data transparently manage its data objects physically stored in a structure. The compiler does not allow for the assigning of an database. Those persistence services were implemented as an object pertaining to a super class to a reference of a subclass. Aspect in terms of Aspect-Oriented Programming (AOP) [6]. This Java generic idiom [7], supported by the standard The AOP consists on a programming technique that libraries based on casts, type tests and the Object class as a allows the transversal separation of concerns. In an object generic type, allows the programmer to deal with the data type oriented context, a concern that is transversal to all objects can generiticity, but the expressiveness and the type safety of the be segregated from those objects and put in a specialized object language is very compromised. Consequently, the presented called Aspect, while the remaining concerns, which are specific framework in this work is also compromised. to each object, maintain themselves implemented in the object A. Parametric Polimorphism and type erasure class. With the Parametric Polymorphism [7] present in the The persistence is a concern that is transversal to any Java 5.0, classes can be generic through types parameters. The component (objects, functions or procedures) in the majority of instantiation code statement of a collection should use a the software. Due to that, it is frequently considered as a good parameter with a type but, as a result, those problems example of crosscutting concern that can be aspectized. The described above are solved. The compiler does consider that main goal of the prototype is to test that concept. all objects on that collection pertain to a single type, the class specified in the type parameter. It will only accept that class of The following diagram presents the system architecture. objects and when objects are retrieved it will not require any cast, because the compiler will insert it automatically. This new approach is based on a type erasure idiom [8] and frees the programmer of all those concerns. When the generic class is instantiated the compiler statically replaces (erases) that parametric data type by a raw data type, typically an Object. The compiler also introduces the necessary type checks at compile-time and uses bridge methods to ensure the type security of the retrieved objects. The authors [7] of this approach justify their option, of using raw types, because serves two important purposes: the support of interfacing with legacy code, retrofitting all existing and used libraries in many production applications; and they support writing code in those few situations where it is necessary to downcast from an unparameterized type (like Object) to a parameterized type (like ArrayList<A>), and one cannot determine the value of the type parameter. The adopted solution in the Java platform 5.0, as Figure 1- System architecture already described, allows a normal coexistence of non-generic and generic code. That it is achieved by the compatibility of the binary class files that represents each class. That generic method that returns a generic type. That gives the compatibility it a complex issue to solve that results of the opportunity to the compiler to decide, in each case, what kind multiple versions of structure that a polymorphic class may of class the method effectively returns by doing type inference have, depending of the polymorphic parameters. That multiple [16]. The underling process of calculating persistence closures representations of the same class are not suitable of being continues to be the same one, based on subtyping. The added represented within a pure homogeneous translation [9][10], value is given by the support for generics. The following applied in the previous versions of the Java platform. Another listing presents the signature of that method. considered alternative was the heterogeneous translation public <T extends Object> T [9][10]. This one maps a parameterised