fancyplants
fancyplants

Reputation: 1727

Metamodel generator for any old class?

I'm finding the JPA metamodel generator functionality really useful for avoiding bugs when column names change. It would be really cool if there was some more general-purpose metamodel generation tool that you could point at any class (or a number of packages) that would generate similar metamodel classes. This could then be used to create compile errors rather than runtime ones when things change:

public class SomeClass {
  public int somePublicProperty;

  public String someStringMethod() {
    ..
  }
}

This might create a metamodel class like:

public class SomeClass_ {
  public static final FieldAttribute<SomeClass,Integer> somePublicProperty;

  public static final MethodAttribute<SomeClass,String> somePublicMethod;
}

where FieldAttribute and MethodAttribute have useful Attribute-like methods to assist with reflection calls (i.e. remove the need to have bare strings):

Object someClassInstance = ... 
Integer value = SomeClass_.somePublicProperty.get( someClassInstance );

// rather than 
Integer value = someClassInstance.getClass().getDeclaredField( "somePublicProperty" ).get( someClassInstance );

Is there anything like this currently available? There's a bit of support in Java 8 now we can do method references, but I'd like something a little bit more metamodel-like if it exists.

Upvotes: 3

Views: 714

Answers (1)

MhagnumDw
MhagnumDw

Reputation: 963

I've had this need a few times and I've implemented this: https://github.com/mhagnumdw/bean-info-generator

Below how you do use this

If you're using Maven, add it to pom.xml

<dependency>
    <groupId>io.github.mhagnumdw</groupId>
    <artifactId>bean-info-generator</artifactId>
    <version>0.0.1</version>
    <scope>compile</scope>
</dependency>

Annotate your class with @GenerateBeanMetaInfo

import io.github.mhagnumdw.beaninfogenerator.GenerateBeanMetaInfo;
@GenerateBeanMetaInfo
public class SomeClass {
    private int someProperty;
}

When the build run, SomeClass_INFO.java and SomeClass_INFO.class are generated

public abstract class SomeClass_INFO {
    public static final BeanMetaInfo someProperty = new BeanMetaInfo("someProperty");
}

Now you can do something like this

Field field = SomeClass.class.getDeclaredField(SomeClass_INFO.someProperty.getName());

Generate *_INFO.java at development time in Eclipse

  • Right click on the project > Properties
  • Java Compiler > Annotation Processing > Factory path
  • Add two jars: bean-info-generator-0.0.1.jar and javapoet-1.9.0.jar

I hope it helps!

Upvotes: 3

Related Questions