0

I have been working with custom attribute types, and JPA's Attribute Converter.

For an example @Entity class like so:

@Entity
public class ExampleEntity {

    private CustomAttribute customAttribute = new CustomAttribute();

    public CustomAttribute getCustomAttribute() {
        if(this.customAttribute == null){
            this.customAttribute = new CustomAttribute();
        }
        return this.customAttribute;
    }
}

My CustomAttribute has some attributes of itself, and I do not want it to be null (ever). I had to choose between two alternatives, and both of those were examplified simultaneously:

  1. Instantiate the object on attribute declaration (like I did on the example for the field).
  2. Instantiate a new object for that attribute in case of a true null checking on a getter.

Since my @Entity on production application has more than 10 attributes, it would be too verbose to apply any of those alternatives on all fields/getters.

Question: Is there any way to instantiate the CustomAttribute object on null field access?

I could not find any answer for this specific question on my research online, so any insight would be appreciated.

EDIT: My question is not about lazy instantiating of fields on relationship mappings, it is about instantiating custom attribute objects on access.

Gabriel Robaina
  • 709
  • 9
  • 24

1 Answers1

0

Bit of a hacky solution, you may prefer it plain java approach you yourself suggested:

I created a class called MyClass, which has following consturctor:

@Data // Lombok annotation
public class ExampleEntity {

    @NotNullGetter
    private CustomAttribute customAttribute;

    public ExampleEntity() {

        Class<?> cls = this.getClass();

        for(Field field: cls.getDeclaredFields()) {
            if(field.isAnnotationPresent(NotNullGetter.class)) {
                Class clazz = field.getType();
                try {
                    for(Method method: cls.getDeclaredMethods()) {

                        if(method.getName().startsWith("set") && method.getName().toLowerCase().endsWith(field.getName().toLowerCase())) {
                            // This will create not null object.
                            method.invoke(this, field.getType().newInstance());
                        }
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

And my @NotNullGetter annotation

   import java.lang.annotation.*;

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    @Documented
    public @interface NotNullGetter {
    }
YoManTaMero
  • 391
  • 4
  • 10
  • I have considered using custom annotations in the past, but what I am really looking for is a cleaner sollution... Or some annotation I could use on the CustomAttribute class, so that everywhere it is called it would be instantiated if it is null... – Gabriel Robaina Jul 31 '19 at 10:40
  • You mean, generic annotation for any classes or attributes? I do agree this is not a clean solution. – YoManTaMero Jul 31 '19 at 10:59
  • I mean an annotation on the CustomAttribute class, so that everywhere it is declared as a field type, it would be instantiated if it is null. Or something on the same line. It would be perfect for my needs. There should be something like that out there, I just need help finding it. – Gabriel Robaina Jul 31 '19 at 11:07
  • 1
    If your ExampleEntity is a bean, you can annotate your class and do it in BeanPostProcessor. CustomAttribute can be initialized when BeanPostProcessor.postProcessAfterInitialization is called. Otherwise, I will wait for answer to this interesting problem. – YoManTaMero Jul 31 '19 at 23:55
  • Currently on our production application, the ExampleEntity is not a bean managed by Spring. So, treating it in BeanPostProcessor is of no effect (correct me if I am wrong...). I am questioning myself if your answer is driving people away from engaging with the question... lets see – Gabriel Robaina Aug 01 '19 at 00:13