All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.server.deploy.BeanLifecycleAdapterFactory Maven / Gradle / Ivy

There is a newer version: 15.8.1
Show newest version
package io.ebeaninternal.server.deploy;

import io.ebean.annotation.PostSoftDelete;
import io.ebean.annotation.PreSoftDelete;
import io.ebean.DatabaseBuilder;
import io.ebean.event.BeanPersistAdapter;
import io.ebean.event.BeanPersistRequest;
import io.ebean.event.BeanPostConstructListener;
import io.ebean.event.BeanPostLoad;
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;

import javax.annotation.PostConstruct;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.PostLoad;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostRemove;
import jakarta.persistence.PostUpdate;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreRemove;
import jakarta.persistence.PreUpdate;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Helper that looks for methods annotated with lifecycle events and registers an adapter for them.
 * 

* This includes PrePersist, PostPersist, PreUpdate, PostUpdate, PreRemove, PostRemove and PostLoad * lifecycle events. *

*/ final class BeanLifecycleAdapterFactory { private final boolean postConstructPresent; BeanLifecycleAdapterFactory(DatabaseBuilder.Settings config) { this.postConstructPresent = config.getClassLoadConfig().isJavaxPostConstructPresent(); } /** * Register a BeanPersistController for methods annotated with lifecycle events. */ void addLifecycleMethods(DeployBeanDescriptor deployDesc) { Method[] methods = deployDesc.getBeanType().getMethods(); // look for annotated methods MethodsHolder methodHolder = new MethodsHolder(); for (Method m : methods) { methodHolder.checkMethod(m, postConstructPresent); } if (methodHolder.hasPersistMethods()) { // has pre/post persist annotated methods deployDesc.addPersistController(new PersistAdapter(new PersistMethodsHolder(methodHolder))); } if (!methodHolder.postLoads.isEmpty()) { // has postLoad methods deployDesc.addPostLoad(new PostLoadAdapter(methodHolder.postLoads)); } if (!methodHolder.postConstructs.isEmpty()) { // has postConstruct methods deployDesc.addPostConstructListener(new PostConstructAdapter(methodHolder.postConstructs)); } } /** * Holds Methods for the lifecycle events.s */ private static final class MethodsHolder { private boolean hasPersistMethods; private final List preInserts = new ArrayList<>(); private final List postInserts = new ArrayList<>(); private final List preUpdates = new ArrayList<>(); private final List postUpdates = new ArrayList<>(); private final List preDeletes = new ArrayList<>(); private final List postDeletes = new ArrayList<>(); private final List preSoftDeletes = new ArrayList<>(); private final List postSoftDeletes = new ArrayList<>(); private final List postLoads = new ArrayList<>(); private final List postConstructs = new ArrayList<>(); /** * Has one of the pre or post insert update delete annotated methods. */ private boolean hasPersistMethods() { return hasPersistMethods; } /** * Check the method for all the annotations we are interested in. */ private void checkMethod(Method method, boolean postConstructPresent) { if (method.isAnnotationPresent(PrePersist.class)) { preInserts.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PostPersist.class)) { postInserts.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PreUpdate.class)) { preUpdates.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PostUpdate.class)) { postUpdates.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PreRemove.class)) { preDeletes.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PostRemove.class)) { postDeletes.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PreSoftDelete.class)) { preSoftDeletes.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PostSoftDelete.class)) { postSoftDeletes.add(method); hasPersistMethods = true; } if (method.isAnnotationPresent(PostLoad.class)) { postLoads.add(method); } if (postConstructPresent) { if (method.isAnnotationPresent(PostConstruct.class)) { postConstructs.add(method); } } } } /** * Utility method to covert List of Method into array (because we care about performance here). */ private static Method[] toArray(List methodList) { return methodList.toArray(new Method[0]); } private static RuntimeException unwrapException(ReflectiveOperationException e) { if (e instanceof InvocationTargetException) { Throwable targetException = ((InvocationTargetException)e).getTargetException(); if (targetException instanceof RuntimeException) { // return unchecked exceptions return (RuntimeException) targetException; } else { // wrap checked exceptions return new PersistenceException("Error invoking lifecycle method", targetException); } } return new PersistenceException("Error invoking lifecycle method", e); } /** * Holds Methods for the lifecycle events.s */ private static final class PersistMethodsHolder { private final Method[] preInserts; private final Method[] postInserts; private final Method[] preUpdates; private final Method[] postUpdates; private final Method[] preDeletes; private final Method[] postDeletes; private final Method[] preSoftDeletes; private final Method[] postSoftDeletes; PersistMethodsHolder(MethodsHolder methodsHolder) { this.preInserts = toArray(methodsHolder.preInserts); this.preUpdates = toArray(methodsHolder.preUpdates); this.preDeletes = toArray(methodsHolder.preDeletes); this.preSoftDeletes = toArray(methodsHolder.preSoftDeletes); this.postInserts = toArray(methodsHolder.postInserts); this.postUpdates = toArray(methodsHolder.postUpdates); this.postDeletes = toArray(methodsHolder.postDeletes); this.postSoftDeletes = toArray(methodsHolder.postSoftDeletes); } } /** * BeanPersistAdapter using reflection to invoke lifecycle methods. */ private static final class PersistAdapter extends BeanPersistAdapter { private final PersistMethodsHolder methodHolder; private PersistAdapter(PersistMethodsHolder methodHolder) { this.methodHolder = methodHolder; } @Override public boolean isRegisterFor(Class cls) { // Not used return false; } private void invoke(Method method, Object bean) { try { method.invoke(bean); } catch (InvocationTargetException | IllegalAccessException e) { throw unwrapException(e); } } private void invoke(Method[] methods, BeanPersistRequest request) { for (Method method : methods) { invoke(method, request.bean()); } } @Override public boolean preDelete(BeanPersistRequest request) { invoke(methodHolder.preDeletes, request); return true; } @Override public boolean preSoftDelete(BeanPersistRequest request) { invoke(methodHolder.preSoftDeletes, request); return true; } @Override public boolean preInsert(BeanPersistRequest request) { invoke(methodHolder.preInserts, request); return true; } @Override public boolean preUpdate(BeanPersistRequest request) { invoke(methodHolder.preUpdates, request); return true; } @Override public void postDelete(BeanPersistRequest request) { invoke(methodHolder.postDeletes, request); } @Override public void postSoftDelete(BeanPersistRequest request) { invoke(methodHolder.postSoftDeletes, request); } @Override public void postInsert(BeanPersistRequest request) { invoke(methodHolder.postInserts, request); } @Override public void postUpdate(BeanPersistRequest request) { invoke(methodHolder.postUpdates, request); } } /** * BeanPostLoad using reflection to invoke lifecycle methods. */ private static final class PostLoadAdapter implements BeanPostLoad { private final Method[] postLoadMethods; private PostLoadAdapter(List postLoadMethods) { this.postLoadMethods = toArray(postLoadMethods); } @Override public boolean isRegisterFor(Class cls) { // Not used return false; } private void invoke(Method method, Object bean) { try { method.invoke(bean); } catch (InvocationTargetException | IllegalAccessException e) { throw unwrapException(e); } } @Override public void postLoad(Object bean) { for (Method postLoadMethod : postLoadMethods) { invoke(postLoadMethod, bean); } } } /** * PostConstructAdapter using reflection to invoke lifecycle methods. */ private static final class PostConstructAdapter implements BeanPostConstructListener { private final Method[] postConstructMethods; private PostConstructAdapter(List postConstructMethods) { this.postConstructMethods = toArray(postConstructMethods); } @Override public boolean isRegisterFor(Class cls) { // Not used return false; } private void invoke(Method method, Object bean) { try { method.invoke(bean); } catch (InvocationTargetException | IllegalAccessException e) { throw unwrapException(e); } } @Override public void postConstruct(Object bean) { for (Method postConstructMethod : postConstructMethods) { invoke(postConstructMethod, bean); } } @Override public void autowire(Object bean) { // autowire is done by global PostConstructListener only } @Override public void postCreate(Object bean) { // postCreate is done by global PostConstructListener only } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy