Skip to content

A java annotation processor to generate a static meta data class for DTOs

License

Notifications You must be signed in to change notification settings

sc-moonlight/meta-fields

Repository files navigation

Meta-Fields

An annotation processor, inspired by JPA Static Metamodel

Overview

[Java][java] provides Method references, but if you need to access a property of a DTO by name, you still need to reference it by using a String.

This leads to code that is prone to mistakes.

My original motivation was from generating a meta-model for editing a DTO with a React frontend. I needed to create a map of properties to form data, that could be mapped back to a data DTO when the form was saved. It was much too easy to misspell a field.

A more common example is using rejectValue() from Spring's Errors interface. This allows you to reject the value for a specific field in your DTO.

errors.rejectValue("userId", "invalid");

However, there is no guarantee that "userId" is a property in the DTO. Which will result in a runtime problem. If you rename userId to userName, it is easy to miss updating anywhere that "userId" was used.

You could create constants for all your DTO properties, but those must then be manually managed.

This processor adds an easy to use Meta DTO class with references to the original DTO properties.

Example usage

Let's start with a simple User DTO.

@GenStaticMeta
public class UserDTO {
    private String id;
    private String firstName;
    private String lastName;
    private Integer customerId;
}

This will automatically create this class

@Generated(value = "net.scmoonlight.annotationproc.staticmeta.GenStaticModelProcessor", date = "2023-11-05T10:15:30.346441400-05:00")
@StaticModel(UserDTO.class)
public final class UserDTOMeta {
  private UserDTOMeta() {}

  public static final String id = "id";
  public static final String firstName = "firstName";
  public static final String lastName = "lastName";
  public static final String customerId = "customerId";
  public static final List<String> allFields = List.of(id,firstName,lastName,customerId);
}

The original example now would change to this:

errors.rejectValue(UserDTOMeta.id, "invalid");

Usage Configuration

The annotation processor supports two options.

  • metaFieldsSuffix
    • The default suffix for the generated class is "Meta". Adding a value for metaFieldsSuffix, allows you to override that.
  • metaFieldsVerbose
    • Log messages during annotation processing

Example gradle configuration

repositories {
  mavenCentral()
  maven {
    url = uri("https://maven.pkg.github.com/sc-moonlight/meta-fields")
    credentials {
      username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
      password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
    }
  }
}

dependencies {
    annotationProcessor group: 'net.scmoonlight', name: 'meta-fields', version: '0.1-SNAPSHOT'
    compileOnly group: 'net.scmoonlight', name: 'meta-fields', version: '0.1-SNAPSHOT'
}

// Optional. Only needed, if you want to see logs, or change the suffix
tasks.withType(JavaCompile) {
  options.compilerArgs += ['-AmetaFieldsVerbose', '-AmetaFieldsSuffix=Meta']
}

License

Copyright 2023 Scott Carlson

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

A java annotation processor to generate a static meta data class for DTOs

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages