180 likes | 300 Views
Implementation of domain models using dynamic proxies Bjørn Vidar Bøe, JavaZone 2005. Agenda. Rationale Overall design Handling business logic Conclusion. Rationale. The new mantra for many new frameworks is simplification (Hibernate, Spring, EJB3, Prevayler, Ruby on Rails…)
E N D
Implementation of domain models using dynamic proxies Bjørn Vidar Bøe, JavaZone 2005
Agenda • Rationale • Overall design • Handling business logic • Conclusion
Rationale • The new mantra for many new frameworks is simplification(Hibernate, Spring, EJB3, Prevayler, Ruby on Rails…) • AOP getting popular for handling cross-cutting concerns like logging, security, caching… • How far can we take this?
Simple Patient class and implementation Patient public class Patient { public String firstName; public String lastName; public Date dob; } +firstName : String +lastName : String +dob : Date
Correct implementation of the Patient class public class Patient { private String firstName; private String lastName; public Date dob; public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; } ... }
Reverse engineered UML from the new class Patient -firstName : String -lastName : String -dob : Date +getFirstName() : String +setFirstName(in firstName : String) +getLastName() : String +setLastName(in lastName : String) +getDob() : Date +setDob(in dob : Date)
Patient class from a user’s perspective public interface Patient { public String getFirstName(); public void setFirstName(String firstName); public String getLastName(); public void setLastName(String lastName); public Date getDob(); public void setDob(Date dob); }
What’s interesting about this? • What is the minimum of information needed to define a Patient-class? • Should the implementation matter? • Should the user need to know about the implementation? • New opportunities?
What if the interface was all that’s needed? • No implementation, just the interface to specify the model • Let a framework implement the model • Other frameworks do this in varying degree, but not in this way
Dynamic proxies Patient (dynamic proxy) Invocation handler +getFirstName() : String +setFirstName(in firstName : String) +getLastName() : String +setLastName(in lastName : String) +getDob() : Date +setDob(in dob : Date) public Object invoke(Object proxy, Method m, Object[] args) Patient patient = (Patient) Proxy.newProxyInstance(Patient.class.getClassLoader(), new Class[] { Patient.class }, myInvocationHandlerImpl);
What about business logic? public String sayHello() { return ”Hello! My name is ” + firstName; }
Split data and business logic Data definition Business service definition BS Impl Domain object
Patient with sayHello() PatientData PatientService +getFirstName() : String +setFirstName(in firstName : String) +getLastName() : String +setLastName(in lastName : String) +getDob() : Date +setDob(in dob : Date) +sayHello() : String PatientServiceImpl -patient : Patient + sayHello() : String Patient
Implementation of PatientServiceImpl public class PatientImpl implements PatientService { private Patient patient; public PatientImpl(Patient patient) { this.patient = patient; } public String sayHello() { return ”Hello! My name is ” + patient.getFirstName(); } }
Alternate solution to the business logic problem – CGLIB! • Similar to dynamic proxies but is also able to extend classes • Used in frameworks like Spring and Hibernate
CGLIB code-example Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Patient.class); enhancer.setCallback(myMethodInterceptor); Patient patient = (Patient)e.create(); public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if (!Modifier.isAbstract(method.getModifiers())) { return methodProxy.invokeSuper(proxy, objects); } else { ... } }
Alternative implementation public abstract class Patient { public abstract String getFirstName(); public abstract void setFirstName(String firstName); public abstract String getLastName(); public abstract void setLastName(String lastName); public abstract Date getDob(); public abstract void setDob(Date dob); public String sayHello() { return ”Hello! My name is ” + getFirstName(); } }
Pros and cons • Easy to change the model • Code-wise extremely lightweight • Not ment to have a database as a back-end • Interface-based solution gets complicated when business logic is added • Haven’t we seen the abstract solution before? • Where will we see this?