javaaemsling-models

Suggestions on how to create a changewatcher on a SlingModel to enable persistence to the JCR


We are currently attempting to implement an extension to SlingModels, to allow a slingmodel to be persisted to the JCR directly.

Our strategy has 2 considered starting conditions: 1. A new object that is to be persisted 2. An object that has been retrieved from the JCR, altered, and is then to be persisted again

For situation 1, we are using reflection to examine the object, create a new node for the model, insert properties for any of the primitive variables found, and recursively use the same persistence approach for any complex model objects found as variables, and collections.

My question on best approach relates to situation 2. If we pull out an object from the repository, we cannot be guaranteed that the node will not be synchronously changed in the meantime. Thus, we would like to implement a change watcher on the SlingModel that keeps a transaction journal on any changes made. The transactions can then be used to set the relevant properties when persisting the object back to the JCR again.

I have considered using an observer pattern, but this would mean that we would need to implement a function within the setter on each SlingModel, which is not ideal at all, as it requires a developer to remember to add the code and do it correctly.

Ideally, I would like to implement something like an interceptor directly on the variable, or if not possible, on the setter itself, and mandate that each model would then need to use a getter/setter for each variable. We can configure code scanning tools to enforce developers to implement getter/setters.

What would the be the best way to approach the change watcher here?


Solution

  • import java.util.List;
    
    public class Teacher {
    
        private String userName;
        private String cource;
        private List<Student> students;
    
        public List<Student> getStudents() {
            return students;
        }
    
        public void setStudents(List<Student> students) {
            this.students = students;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getCource() {
            return cource;
        }
    
        public void setCource(String cource) {
            this.cource = cource;
        }
    }
    
    public class Student {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    
    public class ClassFacadeCglib implements MethodInterceptor{
    
        private Object target; 
    
        public Object getInstance(Object target) {  
            this.target = target;  
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(this.target.getClass());  
            // callback method
            enhancer.setCallback(this);  
            // create proxy object
            return enhancer.create();  
        }  
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args,  
            MethodProxy proxy) throws Throwable {
    
            if(method.getName().startsWith("set")){
                    System.out.println(method.getName()+" start");  
                    proxy.invokeSuper(obj, args);  
                    System.out.println(method.getName()+" end..");  
            }
    
            if(method.getName().startsWith("get")){
                System.out.println(method.getName()+" start");  
                proxy.invokeSuper(obj, args);  
                System.out.println(method.getName()+" end");  
            }
    
            return null;  
        }
    
    }
    
    
    public class Main {
    
        public static void main(String[] args) {  
            ClassFacadeCglib cglib=new ClassFacadeCglib();  
            Teacher teacher=(Teacher)cglib.getInstance(new Teacher());  
            teacher.setCource("Math");
            teacher.getUserName(); 
        } 
    
    }
    

    Note :
    cglib-full-2.0.2.jar is required for running. see https://repo1.maven.org/maven2/cglib/cglib-full/2.0.2/