Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap @Column annotation with my own annotation in Java or Kotlin

I simply want to have my own annotation to clean up the annotation mass and to be able to change them easily when I want;

import javax.persistence.Column
import javax.validation.constraints.Size
class Foo(){
    @Column(name="bar_", nullable = false, length = 32)
    @Size(min = 32, max = 32)
    String bar;

    @Column(nullable = false, length = 32)
    @Size(min = 32, max = 32)
    String bas;

    @Column(nullable = false, length = 32, unique=true)
    @Size(min = 32, max = 32)
    String baq;
}

Wish I could

class Foo(){
    @MyColumn(name="bar_")
    String bar;

    @MyColumn
    String bas;

    @MyColumn(unique=true)
    String baq;
}

nullable = false, length = 32 are the default params.

Java or Kotlin solutions are welcome.

like image 799
hevi Avatar asked Nov 27 '20 13:11

hevi


People also ask

Can we create our own annotations in Java?

To create your own Java Annotation you must use @interface Annotation_name, this will create a new Java Annotation for you. The @interface will describe the new annotation type declaration. After giving a name to your Annotation, you will need to create a block of statements inside which you may declare some variables.

How do you wrap a method in Java?

wrap(int[] array, int offset, int length) The wrap() method wraps an int array into a buffer. The new buffer will be backed by the given int array; that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer's capacity will be array.


1 Answers

Since you're using 3-rd party annotations imported from javax the best option is to introduce a composite annotation. (Kotlin doesn't support annotation inheritance.

@Column(name = "bar_", nullable = false, length = 32)
@Size(min = 32, max = 32)
annotation class Anno

Spring boot is doing a pretty good job combining tons of config annotations all together - check it out.

There is a problem with composite annotation Anno, tho. You have to supply annotation parameters with constant values.

If you're sure, you need a parametrised annotation like

@Column(...)
@Size(min = Anno.max, max = Anno.min)
annotation class Anno(val min: Int, val max: Int)

have a look at Kapt or Kotlin Compiler plugins, you will need a piece of code generation.

With Kapt or Kotlin compiler plugin you will need just to override a newField method of your custom ClassBuilder:

  override fun newField(
      origin: JvmDeclarationOrigin,
      access: Int,
      name: String,
      desc: String,
      signature: String?,
      value: Any?
  ): FieldVisitor {
    // if field is annotated with Anno -- add two custom annotation with parameters of your choice
    // otherwise perform a standard field init
  }

And then register it with

class AnnoRegister : ComponentRegistrar {
  override fun registerProjectComponents(
      project: MockProject,
      configuration: CompilerConfiguration
  ) {
    ...
  }

It should be relatively easy to integrate this processing into an existing gradle or maven project, or just pass to kotlinc.

like image 197
Sergei Rybalkin Avatar answered Nov 02 '22 06:11

Sergei Rybalkin