Java – create immutable objects using JAXB

I am using JAXB to create Java objects from XSD files I'm creating immutable wrappers to hide JAXB generated objects (I was updating JAXB objects to implement immutable interfaces and return to the client, but I realized that changing automatically generated classes is not good, so I used wrappers)

For now, I return these non - convertible wrappers to the client application Whether there are any options so that the automatically generated class will be immutable, it will avoid the extra work of creating immutable wrappers Encourage any other method

>Thank you

Solution

You can create a proxy server for you before returning the bean to the client You will need javassist to create proxies from classes (directly from Java se to create proxies from interfaces)

Then, if you call a method starting with "set", you can throw an exception

This is a reusable class that can wrap "any" POJO methods:

import java.lang.reflect.Method;

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;

public class Utils {

 public static <C> C createInmutableBean(Class<C> clazz,final C instance)
        throws InstantiationException,illegalaccessexception {
    if (!clazz.isAssignableFrom(instance.getClass())) {
        throw new IllegalArgumentException("given instance of class "
                + instance.getClass() + " is not a subclass of " + clazz);
    }
    ProxyFactory f = new ProxyFactory();
    f.setSuperclass(clazz);
    f.setFilter(new MethodFilter() {
        public boolean isHandled(Method m) {
            // ignore finalize()
            return !m.getName().equals("finalize");
        }
    });
    Class c = f.createClass();
    MethodHandler mi = new MethodHandler() {
        public Object invoke(Object self,Method m,Method proceed,Object[] args) throws Throwable {
            if (m.getName().startsWith("set")) {
                throw new RuntimeException("this bean is inmutable!");
            }

            return m.invoke(instance,args); // execute the original method
                                                // over the instance
        }
    };
    C proxy = (C) c.newInstance();

    ((Proxy) proxy).setHandler(mi);
    return (C) proxy;
 }
}

Here is a sample code Make employees your beans:

public class Employee{
  private String name="John";
  private String surname="Smith";
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getSurname() {
    return surname;
  }
  public void setSurname(String surname) {
    this.surname = surname;
  }
};

Here is a test case that shows that you can create a proxy for POJO and use its getter, but not its setter

@Test
public void testProxy() throws InstantiationException,illegalaccessexception{
    Employee aBean = new Employee();

    //I can modify the bean
    aBean.setName("Obi-Wan");
    aBean.setSurname("Kenobi");

    //create the protected java bean with the generic utility
    Employee protectedBean = Utils.createInmutableBean(Employee.class,aBean);

    //I can read
    System.out.println("Name: "+protectedBean.getName());
    System.out.println("Name: "+protectedBean.getSurname());

    //but I can't modify
    try{
        protectedBean.setName("Luke");
        protectedBean.setSurname("Skywalker");
        throw new RuntimeException("The test should not have reached this line!");
    }catch(Exception e){
        //I should be here
        System.out.println("The exception was expected! The bean should not be modified (exception message: "+e.getMessage()+")");
        assertEquals("Obi-Wan",protectedBean.getName());
        assertEquals("Kenobi",protectedBean.getSurname());
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>