Utilities for Graal VM metadata generation.
This library allows generation of graalvm metadata.
There is also a native-helper-maven-plugin available, to add the generation to project build.
1.1 Add dependency
<dependency>
<groupId>org.fugerit.java</groupId>
<artifactId>native-helper-graalvm</artifactId>
<version>x.y.z</version>
</dependency>
1.2 Create your reflect config entry model
// entry setup type 1
Entry entry1 = new Entry( String.class.getName() );
entry1.setCondition( new EntryCondition( String.class.getName() ));
entry1.setFields( Arrays.asList( new EntryField( "prop1" ) ) );
entry1.setMethods( Arrays.asList( new EntryMethod( "test1" ) ) );
// entry setup type 2
EntryCondition condition2 = new EntryCondition();
condition2.setTypeReachable( Double.class.getName() );
EntryField field2 = new EntryField();
field2.setName( "prop2" );
EntryMethod method2 = new EntryMethod();
method2.setName( "test2" );
method2.setParameterTypes( Arrays.asList(Date.class.getName()) );
Entry entry2 = new Entry();
entry2.setCondition( condition2 );
entry2.setFields( Arrays.asList( field2 ) );
entry2.setMethods( Arrays.asList( method2 ) );
entry2.setName( Integer.class.getName() );
// auto generate entry from class :
Entry entry3 = EntryHelper.addDefaultInit( ReflectConfigUtil.GETTERS_ONLY.toEntry( EntryMethod.class ) );
// generate
GenerateReflectConfig gen = new GenerateReflectConfig();
try (StringWriter writer = new StringWriter()) {
List<Entry> entries = Arrays.asList( entry1, entry2, entry3 );
// if you want the methods in fixed order :
entries.forEach( EntryHelper::fixedOrder );
// generate reflect-config.json
gen.generate( writer, entries);
log.info( "output : \n{}", writer.toString() );
}
1.3 Output will be
[ {
"condition" : {
"typeReachable" : "java.lang.String"
},
"name" : "java.lang.String",
"fields" : [ {
"name" : "prop1"
} ],
"methods" : [ {
"name" : "test1",
"parameterTypes" : [ ]
} ]
}, {
"condition" : {
"typeReachable" : "java.lang.Double"
},
"name" : "java.lang.Integer",
"fields" : [ {
"name" : "prop2"
} ],
"methods" : [ {
"name" : "test2",
"parameterTypes" : [ "java.util.Date" ]
} ]
}, {
"name" : "org.fugerit.java.nhg.reflect.config.EntryMethod",
"methods" : [ {
"name" : "<init>",
"parameterTypes" : [ ]
}, {
"name" : "getClass",
"parameterTypes" : [ ]
}, {
"name" : "getName",
"parameterTypes" : [ ]
}, {
"name" : "getParameterTypes",
"parameterTypes" : [ ]
} ]
} ]
It is possible to use ReflectConfigUtil to generate reflect config entries content.
// choose ReflectConfigUtil or define a cusom one
// in this example we will render only getters methods
ReflectConfigUtil reflectConfigUtil = ReflectConfigUtil.GETTERS_ONLY;
// creates new reflect config entry, with selected methods and all constructors
Entry entry = reflectConfigUtil.toEntryWithConstructors( c );
// order methods, constructors first, then methods in alphabetical order
EntryHelper.fixedOrder( entry );
Here is a full code example.
To bulk generate reflect-config.json, you can use the NativeHelperFacade.
NativeHelperFacade uses a yaml configuration file to generate the entries.
Here is a sample native-helper-config.yaml configuration file :
#Sample native helper config file
---
generate:
- className: org.fugerit.java.nhg.reflect.config.Entry
skipConstructors: true
mode: getters
- className: org.fugerit.java.nhg.reflect.config.EntryCondition
skipConstructors: true
mode: getters
- className: org.fugerit.java.nhg.reflect.config.EntryField
skipConstructors: true
mode: getters
- className: org.fugerit.java.nhg.reflect.config.EntryMethod
skipConstructors: true
mode: getters
And then use NativeHelperFacade to generate entries :
// path the native-helper-config.yaml file
String path = "src/test/resources/tool/config/native-helper-config-1.yaml";
// reads configuration
NativeHelperConfig config = NativeHelperFacade.loadConfig( path );
// creates entries from configuration
List<Entry> entries = NativeHelperFacade.generateEntries( config );
Here is a full code example.
top level properties :
name | default | required | type | description |
---|---|---|---|---|
reflectConfigJsonOutputPath | none | false | string | default generation path for reflect-config.json file |
createParentDirectory | false | false | boolean | if true will generate reflectConfigJsonOutputPath parent directory |
jarPackageDiscovery | false | false | boolean | if true will try to discover packages in jar |
generate | none | false | list of entry config | list of entries to generate |
merge | none | false | list of merge coinfig | list of reflect-config.json to merge in the output |
entry config properties :
name | default | required | type | description |
---|---|---|---|---|
className | none | false | string | fully qualified class name (alternative to packageName) |
packageName | none | false | string | fully qualified package name (alternative to className) (*) |
excludeClassNames | none | false | string | if packageName is set, comma separeted list of class simple names to excludes |
mode | none | true | string | accept values : getters, setters, getters_setters, all |
skipGenerators | false | false | boolean | if set to true will not generate constructors metadata |
typeReachable | none | false | string | type for typeReachable condition |
jarPackageDiscovery | false | false | boolean | if true will try to discover packages in jar |
(*) currently package packed ar only supported if jarPackageDiscovery is set to true
merge config properties :
name | default | required | type | description |
---|---|---|---|---|
reflectConfigPath | none | true | string | path to reflect-config.json file to merge |
mode | warnOnError | false | string | Can be warnOnError : error will be just logged on error, failOnError : the generation will fail in case of error |
Once the entry list has been generated, use the GenerateReflectConfig utility to write the json file.
File reflectConfigFile = new File( "META-INF/native-image/relfect-config.json" ):
GenerateReflectConfig generateReflectConfig = new GenerateReflectConfig();
try (Writer writer = new FileWriter( reflectConfigFile ) ) {
generateReflectConfig.generate( writer, entries );
}