Create simple POJO classes (bytecode) at runtime (dynamically)

Muhammad Hewedy picture Muhammad Hewedy · Mar 3, 2011 · Viewed 46.3k times · Source

I've the following scenario..

I am writing some tool that run user-entered query against the database and return the result..

The simplest way is to return the result as: List<String[]> but I need to take this a step further.

I need to create (at runtime) some POJO (or DTO) with some name and create fields and setters and getters for it and populate it with the data returned and then return it to the user among with the .class file generated...

So the idea here is How to Create simple class(bytecode) at runtime (dynamically) I do a basic search and found many lib including Apache BCEL But I think I need something more simpler...

What do you think of that?

Thanks.

Answer

Sean Patrick Floyd picture Sean Patrick Floyd · Mar 3, 2011

Creating a simple POJO with getters and setters is easy if you use CGLib:

public static Class<?> createBeanClass(
    /* fully qualified class name */
    final String className,
    /* bean properties, name -> type */
    final Map<String, Class<?>> properties){

    final BeanGenerator beanGenerator = new BeanGenerator();

    /* use our own hard coded class name instead of a real naming policy */
    beanGenerator.setNamingPolicy(new NamingPolicy(){
        @Override public String getClassName(final String prefix,
            final String source, final Object key, final Predicate names){
            return className;
        }});
    BeanGenerator.addProperties(beanGenerator, properties);
    return (Class<?>) beanGenerator.createClass();
}

Test code:

public static void main(final String[] args) throws Exception{
    final Map<String, Class<?>> properties =
        new HashMap<String, Class<?>>();
    properties.put("foo", Integer.class);
    properties.put("bar", String.class);
    properties.put("baz", int[].class);

    final Class<?> beanClass =
        createBeanClass("some.ClassName", properties);
    System.out.println(beanClass);
    for(final Method method : beanClass.getDeclaredMethods()){
        System.out.println(method);
    }

}

Output:

class some.ClassName
public int[] some.ClassName.getBaz()
public void some.ClassName.setBaz(int[])
public java.lang.Integer some.ClassName.getFoo()
public void some.ClassName.setFoo(java.lang.Integer)
public java.lang.String some.ClassName.getBar()
public void some.ClassName.setBar(java.lang.String)

But the problem is: you have no way of coding against these methods, as they don't exist at compile time, so I don't know what good this will do you.