This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch branch-1.0
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.0 by this push:
     new 019da2a3d6 [#8781] feat(core): Add event support job template 
operation (#8798)
019da2a3d6 is described below

commit 019da2a3d681661d9e353eafe97abfa1c800c3b9
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Oct 13 11:57:27 2025 +0800

    [#8781] feat(core): Add event support job template operation (#8798)
    
    ### What changes were proposed in this pull request?
    
    This PR adds the event for job template related operations.
    
    ### Why are the changes needed?
    
    Fix: #8781
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Add UTs.
    
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../java/org/apache/gravitino/GravitinoEnv.java    |   7 +-
 .../event => }/AccessControlEventDispatcher.java   |  63 +++-
 .../gravitino/listener/JobEventDispatcher.java     | 192 ++++++++++++
 .../listener/api/event/AddGroupEvent.java          |   2 +-
 .../listener/api/event/AddGroupPreEvent.java       |   2 +-
 .../gravitino/listener/api/event/AddUserEvent.java |   2 +-
 .../listener/api/event/CreateRolePreEvent.java     |   2 +-
 .../listener/api/event/DeleteRoleFailureEvent.java |   2 +-
 .../listener/api/event/GetGroupEvent.java          |   2 +-
 .../listener/api/event/GetGroupPreEvent.java       |   2 +-
 .../gravitino/listener/api/event/GetUserEvent.java |   2 +-
 .../listener/api/event/GrantUserRolesPreEvent.java |   2 +-
 .../listener/api/event/ListGroupNamesEvent.java    |   2 +-
 .../listener/api/event/ListGroupNamesPreEvent.java |   2 +-
 .../listener/api/event/ListGroupsEvent.java        |   2 +-
 .../listener/api/event/ListGroupsPreEvent.java     |   2 +-
 .../listener/api/event/ListRoleNamesEvent.java     |   2 +-
 .../listener/api/event/ListUserNamesEvent.java     |   2 +-
 .../api/event/ListUserNamesFailureEvent.java       |   2 +-
 .../listener/api/event/ListUserNamesPreEvent.java  |   2 +-
 .../listener/api/event/ListUsersEvent.java         |   2 +-
 .../listener/api/event/ListUsersFailureEvent.java  |   2 +-
 .../listener/api/event/ListUsersPreEvent.java      |   2 +-
 .../listener/api/event/OperationType.java          |  13 +
 .../listener/api/event/RemoveGroupEvent.java       |   2 +-
 .../listener/api/event/RemoveGroupPreEvent.java    |   2 +-
 .../listener/api/event/RemoveUserEvent.java        |   2 +-
 .../listener/api/event/RemoveUserPreEvent.java     |   2 +-
 .../api/event/job/AlterJobTemplateEvent.java       |  88 ++++++
 .../event/job/AlterJobTemplateFailureEvent.java    |  72 +++++
 .../api/event/job/AlterJobTemplatePreEvent.java    |  65 ++++
 .../api/event/job/DeleteJobTemplateEvent.java      |  66 ++++
 .../DeleteJobTemplateFailureEvent.java}            |  43 +--
 .../DeleteJobTemplatePreEvent.java}                |  29 +-
 .../GetJobTemplateEvent.java}                      |  43 ++-
 .../GetJobTemplateFailureEvent.java}               |  39 +--
 .../GetJobTemplatePreEvent.java}                   |  29 +-
 .../JobTemplateEvent.java}                         |  31 +-
 .../JobTemplateFailureEvent.java}                  |  32 +-
 .../JobTemplatePreEvent.java}                      |  31 +-
 .../ListJobTemplatesEvent.java}                    |  23 +-
 .../ListJobTemplatesFailureEvent.java}             |  28 +-
 .../ListJobTemplatesPreEvent.java}                 |  24 +-
 .../api/event/job/RegisterJobTemplateEvent.java    |  63 ++++
 .../event/job/RegisterJobTemplateFailureEvent.java |  66 ++++
 .../RegisterJobTemplatePreEvent.java}              |  43 ++-
 .../apache/gravitino/meta/JobTemplateEntity.java   |  31 ++
 .../listener/api/event/TestGroupEvent.java         |   1 +
 .../listener/api/event/TestJobEventDispatcher.java | 332 +++++++++++++++++++++
 .../listener/api/event/TestRoleEvent.java          |   1 +
 .../listener/api/event/TestUserEvent.java          |   1 +
 docs/gravitino-server-config.md                    |  64 ++--
 52 files changed, 1294 insertions(+), 274 deletions(-)

diff --git a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java 
b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
index 7b5929d5e5..d8746dcb2d 100644
--- a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
+++ b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
@@ -60,10 +60,12 @@ import org.apache.gravitino.hook.TableHookDispatcher;
 import org.apache.gravitino.hook.TopicHookDispatcher;
 import org.apache.gravitino.job.JobManager;
 import org.apache.gravitino.job.JobOperationDispatcher;
+import org.apache.gravitino.listener.AccessControlEventDispatcher;
 import org.apache.gravitino.listener.CatalogEventDispatcher;
 import org.apache.gravitino.listener.EventBus;
 import org.apache.gravitino.listener.EventListenerManager;
 import org.apache.gravitino.listener.FilesetEventDispatcher;
+import org.apache.gravitino.listener.JobEventDispatcher;
 import org.apache.gravitino.listener.MetalakeEventDispatcher;
 import org.apache.gravitino.listener.ModelEventDispatcher;
 import org.apache.gravitino.listener.PartitionEventDispatcher;
@@ -71,7 +73,6 @@ import org.apache.gravitino.listener.SchemaEventDispatcher;
 import org.apache.gravitino.listener.TableEventDispatcher;
 import org.apache.gravitino.listener.TagEventDispatcher;
 import org.apache.gravitino.listener.TopicEventDispatcher;
-import org.apache.gravitino.listener.api.event.AccessControlEventDispatcher;
 import org.apache.gravitino.lock.LockManager;
 import org.apache.gravitino.metalake.MetalakeDispatcher;
 import org.apache.gravitino.metalake.MetalakeManager;
@@ -599,7 +600,7 @@ public class GravitinoEnv {
     // todo: support policy event dispatcher
     this.policyDispatcher = new PolicyManager(idGenerator, entityStore);
 
-    // TODO: Support event for job operation dispatcher
-    this.jobOperationDispatcher = new JobManager(config, entityStore, 
idGenerator);
+    this.jobOperationDispatcher =
+        new JobEventDispatcher(eventBus, new JobManager(config, entityStore, 
idGenerator));
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
 
b/core/src/main/java/org/apache/gravitino/listener/AccessControlEventDispatcher.java
similarity index 80%
rename from 
core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
rename to 
core/src/main/java/org/apache/gravitino/listener/AccessControlEventDispatcher.java
index cecf20de50..4985c9e4ee 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/AccessControlEventDispatcher.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener;
 
 import java.util.List;
 import java.util.Map;
@@ -38,7 +38,66 @@ import org.apache.gravitino.exceptions.NoSuchRoleException;
 import org.apache.gravitino.exceptions.NoSuchUserException;
 import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
 import org.apache.gravitino.exceptions.UserAlreadyExistsException;
-import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.api.event.AddGroupEvent;
+import org.apache.gravitino.listener.api.event.AddGroupFailureEvent;
+import org.apache.gravitino.listener.api.event.AddGroupPreEvent;
+import org.apache.gravitino.listener.api.event.AddUserEvent;
+import org.apache.gravitino.listener.api.event.AddUserFailureEvent;
+import org.apache.gravitino.listener.api.event.AddUserPreEvent;
+import org.apache.gravitino.listener.api.event.CreateRoleEvent;
+import org.apache.gravitino.listener.api.event.CreateRoleFailureEvent;
+import org.apache.gravitino.listener.api.event.CreateRolePreEvent;
+import org.apache.gravitino.listener.api.event.DeleteRoleEvent;
+import org.apache.gravitino.listener.api.event.DeleteRoleFailureEvent;
+import org.apache.gravitino.listener.api.event.DeleteRolePreEvent;
+import org.apache.gravitino.listener.api.event.GetGroupEvent;
+import org.apache.gravitino.listener.api.event.GetGroupFailureEvent;
+import org.apache.gravitino.listener.api.event.GetGroupPreEvent;
+import org.apache.gravitino.listener.api.event.GetRoleEvent;
+import org.apache.gravitino.listener.api.event.GetRoleFailureEvent;
+import org.apache.gravitino.listener.api.event.GetRolePreEvent;
+import org.apache.gravitino.listener.api.event.GetUserEvent;
+import org.apache.gravitino.listener.api.event.GetUserFailureEvent;
+import org.apache.gravitino.listener.api.event.GetUserPreEvent;
+import org.apache.gravitino.listener.api.event.GrantGroupRolesEvent;
+import org.apache.gravitino.listener.api.event.GrantGroupRolesFailureEvent;
+import org.apache.gravitino.listener.api.event.GrantGroupRolesPreEvent;
+import org.apache.gravitino.listener.api.event.GrantPrivilegesEvent;
+import org.apache.gravitino.listener.api.event.GrantPrivilegesFailureEvent;
+import org.apache.gravitino.listener.api.event.GrantPrivilegesPreEvent;
+import org.apache.gravitino.listener.api.event.GrantUserRolesEvent;
+import org.apache.gravitino.listener.api.event.GrantUserRolesFailureEvent;
+import org.apache.gravitino.listener.api.event.GrantUserRolesPreEvent;
+import org.apache.gravitino.listener.api.event.ListGroupNamesEvent;
+import org.apache.gravitino.listener.api.event.ListGroupNamesFailureEvent;
+import org.apache.gravitino.listener.api.event.ListGroupNamesPreEvent;
+import org.apache.gravitino.listener.api.event.ListGroupsEvent;
+import org.apache.gravitino.listener.api.event.ListGroupsFailureEvent;
+import org.apache.gravitino.listener.api.event.ListGroupsPreEvent;
+import org.apache.gravitino.listener.api.event.ListRoleNamesEvent;
+import org.apache.gravitino.listener.api.event.ListRoleNamesFailureEvent;
+import org.apache.gravitino.listener.api.event.ListRoleNamesPreEvent;
+import org.apache.gravitino.listener.api.event.ListUserNamesEvent;
+import org.apache.gravitino.listener.api.event.ListUserNamesFailureEvent;
+import org.apache.gravitino.listener.api.event.ListUserNamesPreEvent;
+import org.apache.gravitino.listener.api.event.ListUsersEvent;
+import org.apache.gravitino.listener.api.event.ListUsersFailureEvent;
+import org.apache.gravitino.listener.api.event.ListUsersPreEvent;
+import org.apache.gravitino.listener.api.event.RemoveGroupEvent;
+import org.apache.gravitino.listener.api.event.RemoveGroupFailureEvent;
+import org.apache.gravitino.listener.api.event.RemoveGroupPreEvent;
+import org.apache.gravitino.listener.api.event.RemoveUserEvent;
+import org.apache.gravitino.listener.api.event.RemoveUserFailureEvent;
+import org.apache.gravitino.listener.api.event.RemoveUserPreEvent;
+import org.apache.gravitino.listener.api.event.RevokeGroupRolesEvent;
+import org.apache.gravitino.listener.api.event.RevokeGroupRolesFailureEvent;
+import org.apache.gravitino.listener.api.event.RevokeGroupRolesPreEvent;
+import org.apache.gravitino.listener.api.event.RevokePrivilegesEvent;
+import org.apache.gravitino.listener.api.event.RevokePrivilegesFailureEvent;
+import org.apache.gravitino.listener.api.event.RevokePrivilegesPreEvent;
+import org.apache.gravitino.listener.api.event.RevokeUserRolesEvent;
+import org.apache.gravitino.listener.api.event.RevokeUserRolesFailureEvent;
+import org.apache.gravitino.listener.api.event.RevokeUserRolesPreEvent;
 import org.apache.gravitino.listener.api.info.GroupInfo;
 import org.apache.gravitino.listener.api.info.RoleInfo;
 import org.apache.gravitino.listener.api.info.UserInfo;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/JobEventDispatcher.java 
b/core/src/main/java/org/apache/gravitino/listener/JobEventDispatcher.java
new file mode 100644
index 0000000000..30e3b97be6
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/listener/JobEventDispatcher.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import org.apache.gravitino.exceptions.InUseException;
+import org.apache.gravitino.exceptions.JobTemplateAlreadyExistsException;
+import org.apache.gravitino.exceptions.NoSuchJobException;
+import org.apache.gravitino.exceptions.NoSuchJobTemplateException;
+import org.apache.gravitino.job.JobOperationDispatcher;
+import org.apache.gravitino.job.JobTemplateChange;
+import org.apache.gravitino.listener.api.event.job.AlterJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.AlterJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.AlterJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.DeleteJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.DeleteJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.DeleteJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplateEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.ListJobTemplatesEvent;
+import 
org.apache.gravitino.listener.api.event.job.ListJobTemplatesFailureEvent;
+import org.apache.gravitino.listener.api.event.job.ListJobTemplatesPreEvent;
+import org.apache.gravitino.listener.api.event.job.RegisterJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.RegisterJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.RegisterJobTemplatePreEvent;
+import org.apache.gravitino.meta.JobEntity;
+import org.apache.gravitino.meta.JobTemplateEntity;
+import org.apache.gravitino.utils.PrincipalUtils;
+
+public class JobEventDispatcher implements JobOperationDispatcher {
+
+  private final EventBus eventBus;
+  private final JobOperationDispatcher jobOperationDispatcher;
+
+  public JobEventDispatcher(EventBus eventBus, JobOperationDispatcher 
jobOperationDispatcher) {
+    this.eventBus = eventBus;
+    this.jobOperationDispatcher = jobOperationDispatcher;
+  }
+
+  @Override
+  public List<JobTemplateEntity> listJobTemplates(String metalake) {
+    eventBus.dispatchEvent(
+        new ListJobTemplatesPreEvent(PrincipalUtils.getCurrentUserName(), 
metalake));
+
+    try {
+      List<JobTemplateEntity> jobTemplates = 
jobOperationDispatcher.listJobTemplates(metalake);
+      eventBus.dispatchEvent(
+          new ListJobTemplatesEvent(PrincipalUtils.getCurrentUserName(), 
metalake));
+      return jobTemplates;
+    } catch (Exception e) {
+      eventBus.dispatchEvent(
+          new 
ListJobTemplatesFailureEvent(PrincipalUtils.getCurrentUserName(), metalake, e));
+      throw e;
+    }
+  }
+
+  @Override
+  public void registerJobTemplate(String metalake, JobTemplateEntity 
jobTemplateEntity)
+      throws JobTemplateAlreadyExistsException {
+    eventBus.dispatchEvent(
+        new RegisterJobTemplatePreEvent(
+            PrincipalUtils.getCurrentUserName(), metalake, 
jobTemplateEntity.toJobTemplate()));
+
+    try {
+      jobOperationDispatcher.registerJobTemplate(metalake, jobTemplateEntity);
+      eventBus.dispatchEvent(
+          new RegisterJobTemplateEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, 
jobTemplateEntity.toJobTemplate()));
+    } catch (Exception e) {
+      eventBus.dispatchEvent(
+          new RegisterJobTemplateFailureEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, 
jobTemplateEntity.toJobTemplate(), e));
+      throw e;
+    }
+  }
+
+  @Override
+  public JobTemplateEntity getJobTemplate(String metalake, String 
jobTemplateName)
+      throws NoSuchJobTemplateException {
+    eventBus.dispatchEvent(
+        new GetJobTemplatePreEvent(PrincipalUtils.getCurrentUserName(), 
metalake, jobTemplateName));
+
+    try {
+      JobTemplateEntity jobTemplate =
+          jobOperationDispatcher.getJobTemplate(metalake, jobTemplateName);
+      eventBus.dispatchEvent(
+          new GetJobTemplateEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, 
jobTemplate.toJobTemplate()));
+      return jobTemplate;
+    } catch (Exception e) {
+      eventBus.dispatchEvent(
+          new GetJobTemplateFailureEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName, 
e));
+      throw e;
+    }
+  }
+
+  @Override
+  public boolean deleteJobTemplate(String metalake, String jobTemplateName) 
throws InUseException {
+    eventBus.dispatchEvent(
+        new DeleteJobTemplatePreEvent(
+            PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName));
+
+    try {
+      boolean result = jobOperationDispatcher.deleteJobTemplate(metalake, 
jobTemplateName);
+      eventBus.dispatchEvent(
+          new DeleteJobTemplateEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName, 
result));
+      return result;
+    } catch (Exception e) {
+      eventBus.dispatchEvent(
+          new DeleteJobTemplateFailureEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName, 
e));
+      throw e;
+    }
+  }
+
+  @Override
+  public JobTemplateEntity alterJobTemplate(
+      String metalake, String jobTemplateName, JobTemplateChange... changes)
+      throws NoSuchJobTemplateException, IllegalArgumentException {
+    eventBus.dispatchEvent(
+        new AlterJobTemplatePreEvent(
+            PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName, 
changes));
+
+    try {
+      JobTemplateEntity updatedJobTemplate =
+          jobOperationDispatcher.alterJobTemplate(metalake, jobTemplateName, 
changes);
+      eventBus.dispatchEvent(
+          new AlterJobTemplateEvent(
+              PrincipalUtils.getCurrentUserName(),
+              metalake,
+              changes,
+              updatedJobTemplate.toJobTemplate()));
+      return updatedJobTemplate;
+    } catch (Exception e) {
+      eventBus.dispatchEvent(
+          new AlterJobTemplateFailureEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, jobTemplateName, 
changes, e));
+      throw e;
+    }
+  }
+
+  @Override
+  public List<JobEntity> listJobs(String metalake, java.util.Optional<String> 
jobTemplateName)
+      throws NoSuchJobTemplateException {
+    return jobOperationDispatcher.listJobs(metalake, jobTemplateName);
+  }
+
+  @Override
+  public JobEntity getJob(String metalake, String jobId) throws 
NoSuchJobException {
+    return jobOperationDispatcher.getJob(metalake, jobId);
+  }
+
+  @Override
+  public JobEntity runJob(String metalake, String jobTemplateName, Map<String, 
String> jobConf)
+      throws NoSuchJobTemplateException {
+    return jobOperationDispatcher.runJob(metalake, jobTemplateName, jobConf);
+  }
+
+  @Override
+  public JobEntity cancelJob(String metalake, String jobId) throws 
NoSuchJobException {
+    return jobOperationDispatcher.cancelJob(metalake, jobId);
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (jobOperationDispatcher != null) {
+      jobOperationDispatcher.close();
+    }
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
index 248111915f..5a40403c2d 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
@@ -36,7 +36,7 @@ public class AddGroupEvent extends GroupEvent {
    * @param metalake the name of the metalake where the group was added.
    * @param addedGroupInfo the information about the group that was added.
    */
-  protected AddGroupEvent(String initiator, String metalake, GroupInfo 
addedGroupInfo) {
+  public AddGroupEvent(String initiator, String metalake, GroupInfo 
addedGroupInfo) {
     super(initiator, NameIdentifierUtil.ofGroup(metalake, 
addedGroupInfo.name()));
 
     this.addedGroupInfo = addedGroupInfo;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
index f0a8df36ee..e73f0fd7ac 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
@@ -35,7 +35,7 @@ public class AddGroupPreEvent extends GroupPreEvent {
    * @param metalake the name of the metalake where the group is to be added.
    * @param groupName the name of the group that is requested to be added to 
the metalake.
    */
-  protected AddGroupPreEvent(String initiator, String metalake, String 
groupName) {
+  public AddGroupPreEvent(String initiator, String metalake, String groupName) 
{
     super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
 
     this.groupName = groupName;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddUserEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddUserEvent.java
index 027a04a87c..332a308658 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddUserEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddUserEvent.java
@@ -36,7 +36,7 @@ public class AddUserEvent extends UserEvent {
    * @param metalake the name of the metalake where the user was added.
    * @param addedUserInfo the user information of the newly added user.
    */
-  protected AddUserEvent(String initiator, String metalake, UserInfo 
addedUserInfo) {
+  public AddUserEvent(String initiator, String metalake, UserInfo 
addedUserInfo) {
     super(initiator, NameIdentifierUtil.ofUser(metalake, 
addedUserInfo.name()));
 
     this.addedUserInfo = addedUserInfo;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRolePreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRolePreEvent.java
index 0fe009fd9f..55a74c1c69 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRolePreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRolePreEvent.java
@@ -45,7 +45,7 @@ public class CreateRolePreEvent extends RolePreEvent {
    * @param properties The properties of the role being created.
    * @param securableObjects The list of securable objects belonging to the 
role.
    */
-  protected CreateRolePreEvent(
+  public CreateRolePreEvent(
       String initiator,
       String metalake,
       String roleName,
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
index a020030a2e..d7a45747fd 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
@@ -38,7 +38,7 @@ public class DeleteRoleFailureEvent extends RoleFailureEvent {
    * @param exception the exception that caused the failure
    * @param roleName the name of the role intended for deletion
    */
-  protected DeleteRoleFailureEvent(
+  public DeleteRoleFailureEvent(
       String user, String metalake, Exception exception, String roleName) {
     super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
index 05c7d54e43..4cbe7afddb 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
@@ -38,7 +38,7 @@ public class GetGroupEvent extends GroupEvent {
    * @param metalake the name of the metalake from which the group is 
retrieved.
    * @param loadedGroupInfo the information of the group that was retrieved.
    */
-  protected GetGroupEvent(String initiator, String metalake, GroupInfo 
loadedGroupInfo) {
+  public GetGroupEvent(String initiator, String metalake, GroupInfo 
loadedGroupInfo) {
     super(initiator, NameIdentifierUtil.ofGroup(metalake, 
loadedGroupInfo.name()));
 
     this.loadedGroupInfo = loadedGroupInfo;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
index fbc67fc0ea..ef8aba7c4f 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
@@ -35,7 +35,7 @@ public class GetGroupPreEvent extends GroupPreEvent {
    * @param metalake the name of the metalake from which the group is being 
retrieved.
    * @param groupName the name of the group that is requested to be retrieved.
    */
-  protected GetGroupPreEvent(String initiator, String metalake, String 
groupName) {
+  public GetGroupPreEvent(String initiator, String metalake, String groupName) 
{
     super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
 
     this.groupName = groupName;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetUserEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetUserEvent.java
index 15957695ae..606d2269e8 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetUserEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetUserEvent.java
@@ -36,7 +36,7 @@ public class GetUserEvent extends UserEvent {
    * @param metalake the name of the metalake from which the user is retrieved.
    * @param loadedUserInfo the user information of the retrieved user.
    */
-  protected GetUserEvent(String initiator, String metalake, UserInfo 
loadedUserInfo) {
+  public GetUserEvent(String initiator, String metalake, UserInfo 
loadedUserInfo) {
     super(initiator, NameIdentifierUtil.ofUser(metalake, 
loadedUserInfo.name()));
 
     this.loadedUserInfo = loadedUserInfo;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GrantUserRolesPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantUserRolesPreEvent.java
index 43febc7f9e..8f200ef7cf 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GrantUserRolesPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantUserRolesPreEvent.java
@@ -38,7 +38,7 @@ public class GrantUserRolesPreEvent extends UserPreEvent {
    * @param userName the username of the user to whom the roles will be 
granted.
    * @param roles the list of roles that will be granted to the user.
    */
-  protected GrantUserRolesPreEvent(
+  public GrantUserRolesPreEvent(
       String initiator, String metalake, String userName, List<String> roles) {
     super(initiator, NameIdentifierUtil.ofUser(metalake, userName));
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
index 297df5cc0a..f9b3530c3b 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
@@ -34,7 +34,7 @@ public class ListGroupNamesEvent extends GroupEvent {
    * @param initiator the user who initiated the list-group-names request.
    * @param metalake the name of the metalake from which group names are 
listed.
    */
-  protected ListGroupNamesEvent(String initiator, String metalake) {
+  public ListGroupNamesEvent(String initiator, String metalake) {
     super(initiator, NameIdentifierUtil.ofMetalake(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
index b4c8886019..3667485921 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
@@ -32,7 +32,7 @@ public class ListGroupNamesPreEvent extends GroupPreEvent {
    * @param initiator the user who initiated the list-group-names request.
    * @param metalake the name of the metalake from which group names will be 
listed.
    */
-  protected ListGroupNamesPreEvent(String initiator, String metalake) {
+  public ListGroupNamesPreEvent(String initiator, String metalake) {
     super(initiator, NameIdentifierUtil.ofMetalake(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
index e732cdff92..73ead32d8f 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
@@ -32,7 +32,7 @@ public class ListGroupsEvent extends GroupEvent {
    * @param initiator the user who initiated the list-groups request.
    * @param metalake the name of the metalake from which the groups were 
listed.
    */
-  protected ListGroupsEvent(String initiator, String metalake) {
+  public ListGroupsEvent(String initiator, String metalake) {
     super(initiator, NameIdentifierUtil.ofMetalake(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
index a709e83a57..8deec0ff01 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
@@ -31,7 +31,7 @@ public class ListGroupsPreEvent extends GroupPreEvent {
    * @param initiator the user who initiated the list-groups request.
    * @param metalake the name of the metalake from which groups will be listed.
    */
-  protected ListGroupsPreEvent(String initiator, String metalake) {
+  public ListGroupsPreEvent(String initiator, String metalake) {
     super(initiator, NameIdentifierUtil.ofMetalake(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesEvent.java
index 9b59c70fe0..ac0df1500d 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesEvent.java
@@ -46,7 +46,7 @@ public class ListRoleNamesEvent extends RoleEvent {
    * @param metalake the metalake name where the roles are listed.
    * @param object the {@code MetadataObject} related to the role names.
    */
-  protected ListRoleNamesEvent(String initiator, String metalake, 
MetadataObject object) {
+  public ListRoleNamesEvent(String initiator, String metalake, MetadataObject 
object) {
     super(initiator, NameIdentifierUtil.ofMetalake(metalake));
 
     this.object = Optional.ofNullable(object);
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesEvent.java
index 6c2bca1368..7f6cd33afb 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesEvent.java
@@ -32,7 +32,7 @@ public class ListUserNamesEvent extends UserEvent {
    * @param initiator the user who initiated the request to list usernames.
    * @param metalake the name of the metalake from which the usernames are 
listed.
    */
-  protected ListUserNamesEvent(String initiator, String metalake) {
+  public ListUserNamesEvent(String initiator, String metalake) {
     super(initiator, NameIdentifier.of(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
index c692047726..d7f7048c4b 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
@@ -35,7 +35,7 @@ public class ListUserNamesFailureEvent extends 
UserFailureEvent {
    * @param metalake the name of the metalake where the operation was attempted
    * @param exception the exception encountered during the operation
    */
-  protected ListUserNamesFailureEvent(String user, String metalake, Exception 
exception) {
+  public ListUserNamesFailureEvent(String user, String metalake, Exception 
exception) {
     super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesPreEvent.java
index e34d10cb74..bff5ee5797 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesPreEvent.java
@@ -33,7 +33,7 @@ public class ListUserNamesPreEvent extends UserPreEvent {
    * @param initiator the user who initiated the request to list usernames.
    * @param metalake the name of the metalake from which to list usernames.
    */
-  protected ListUserNamesPreEvent(String initiator, String metalake) {
+  public ListUserNamesPreEvent(String initiator, String metalake) {
     super(initiator, NameIdentifier.of(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
index 5188e22a9a..2a5b7ed2eb 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
@@ -33,7 +33,7 @@ public class ListUsersEvent extends UserEvent {
    * @param initiator the user who initiated the request to list users.
    * @param metalake the name of the metalake from which the users are listed.
    */
-  protected ListUsersEvent(String initiator, String metalake) {
+  public ListUsersEvent(String initiator, String metalake) {
     super(initiator, NameIdentifier.of(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersFailureEvent.java
index 3cd52e0654..4a7e4753cd 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersFailureEvent.java
@@ -35,7 +35,7 @@ public class ListUsersFailureEvent extends UserFailureEvent {
    * @param metalake the name of the metalake where the operation was attempted
    * @param exception the exception encountered during the operation
    */
-  protected ListUsersFailureEvent(String user, String metalake, Exception 
exception) {
+  public ListUsersFailureEvent(String user, String metalake, Exception 
exception) {
     super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
index 1c3d21c67a..9988706b87 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
@@ -32,7 +32,7 @@ public class ListUsersPreEvent extends UserPreEvent {
    * @param initiator the user who initiated the list-user request.
    * @param metalake the metalake name to list users from.
    */
-  protected ListUsersPreEvent(String initiator, String metalake) {
+  public ListUsersPreEvent(String initiator, String metalake) {
     super(initiator, NameIdentifier.of(metalake));
   }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
index 3c7b1439b1..62b86ed13a 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
@@ -146,5 +146,18 @@ public enum OperationType {
   GET_OWNER,
   SET_OWNER,
 
+  // Job template operations
+  LIST_JOB_TEMPLATES,
+  REGISTER_JOB_TEMPLATE,
+  GET_JOB_TEMPLATE,
+  ALTER_JOB_TEMPLATE,
+  DELETE_JOB_TEMPLATE,
+
+  // Job operations
+  LIST_JOBS,
+  RUN_JOB,
+  GET_JOB,
+  CANCEL_JOB,
+
   UNKNOWN,
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
index 417070cb5d..81a9fba16b 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
@@ -38,7 +38,7 @@ public class RemoveGroupEvent extends GroupEvent {
    * @param isExists {@code true} if the group was successfully removed, 
{@code false} if there was
    *     no such group in the metalake.
    */
-  protected RemoveGroupEvent(
+  public RemoveGroupEvent(
       String initiator, String metalake, String removedGroupName, boolean 
isExists) {
     super(initiator, NameIdentifierUtil.ofGroup(metalake, removedGroupName));
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
index bafe80c126..66d429d253 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
@@ -35,7 +35,7 @@ public class RemoveGroupPreEvent extends GroupPreEvent {
    * @param metalake the name of the metalake from which the group will be 
removed.
    * @param groupName the name of the group that is requested to be removed 
from the metalake.
    */
-  protected RemoveGroupPreEvent(String initiator, String metalake, String 
groupName) {
+  public RemoveGroupPreEvent(String initiator, String metalake, String 
groupName) {
     super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
 
     this.groupName = groupName;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserEvent.java
index 5b48dd7743..2dfd48972b 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserEvent.java
@@ -38,7 +38,7 @@ public class RemoveUserEvent extends UserEvent {
    * @param isExists {@code true} if the user was successfully removed, {@code 
false} if no such
    *     user exists in the metalake.
    */
-  protected RemoveUserEvent(
+  public RemoveUserEvent(
       String initiator, String metalake, String removedUserName, boolean 
isExists) {
     super(initiator, NameIdentifierUtil.ofUser(metalake, removedUserName));
 
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserPreEvent.java
index a6b66ec883..c8ad3afc95 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveUserPreEvent.java
@@ -34,7 +34,7 @@ public class RemoveUserPreEvent extends UserPreEvent {
    * @param metalake the metalake name of the metalake from which the user is 
to be removed.
    * @param userName the username which is requested to be removed from the 
metalake.
    */
-  protected RemoveUserPreEvent(String initiator, String metalake, String 
userName) {
+  public RemoveUserPreEvent(String initiator, String metalake, String 
userName) {
     super(initiator, NameIdentifierUtil.ofUser(metalake, userName));
 
     this.userName = userName;
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateEvent.java
new file mode 100644
index 0000000000..2310132459
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateEvent.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import javax.annotation.Nullable;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.job.JobTemplateChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered upon the successful alteration of a job 
template. */
+@DeveloperApi
+public final class AlterJobTemplateEvent extends JobTemplateEvent {
+  private final JobTemplate updatedJobTemplate;
+  private final JobTemplateChange[] jobTemplateChanges;
+
+  /**
+   * Constructs an instance of {@code AlterJobTemplateEvent}, encapsulating 
the key details about
+   * the successful alteration of a job template.
+   *
+   * @param user The username of the individual responsible for initiating the 
job template
+   *     alteration.
+   * @param metalake The metalake from which the job template is being altered.
+   * @param jobTemplateChanges An array of {@link JobTemplateChange} objects 
representing the
+   *     specific changes applied to the job template during the alteration 
process.
+   * @param updatedJobTemplate The post-alteration state of the job template.
+   */
+  public AlterJobTemplateEvent(
+      String user,
+      String metalake,
+      JobTemplateChange[] jobTemplateChanges,
+      JobTemplate updatedJobTemplate) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, 
updatedJobTemplate.name()));
+    this.jobTemplateChanges = jobTemplateChanges;
+    this.updatedJobTemplate = updatedJobTemplate;
+  }
+
+  /**
+   * Retrieves the final state of the job template as it was returned to the 
user after successful
+   * alteration.
+   *
+   * @return A {@link JobTemplate} instance encapsulating the comprehensive 
details of the newly
+   *     altered job template.
+   */
+  public JobTemplate updatedJobTemplate() {
+    return updatedJobTemplate;
+  }
+
+  /**
+   * Retrieves the specific changes that were made to the job template during 
the alteration
+   * process.
+   *
+   * @return An array of {@link JobTemplateChange} objects detailing each 
modification applied to
+   *     the job template.
+   */
+  @Nullable
+  public JobTemplateChange[] changes() {
+    return jobTemplateChanges;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.ALTER_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateFailureEvent.java
new file mode 100644
index 0000000000..7de9bf0008
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplateFailureEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplateChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to alter a job template in 
the database fails due
+ * to an exception.
+ */
+@DeveloperApi
+public class AlterJobTemplateFailureEvent extends JobTemplateFailureEvent {
+  private final JobTemplateChange[] changes;
+
+  /**
+   * Constructs a new AlterJobTemplateFailureEvent.
+   *
+   * @param user the user who attempted to alter the job template
+   * @param metalake the metalake identifier
+   * @param jobTemplateName the name of the job template
+   * @param changes the changes attempted to be made to the job template
+   * @param exception the exception that caused the failure
+   */
+  public AlterJobTemplateFailureEvent(
+      String user,
+      String metalake,
+      String jobTemplateName,
+      JobTemplateChange[] changes,
+      Exception exception) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName), 
exception);
+    this.changes = changes;
+  }
+
+  /**
+   * Returns the changes attempted to be made to the job template.
+   *
+   * @return the changes attempted to be made to the job template
+   */
+  public JobTemplateChange[] changes() {
+    return changes;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.ALTER_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplatePreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplatePreEvent.java
new file mode 100644
index 0000000000..df9ecc9b9a
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/AlterJobTemplatePreEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplateChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered before altering a job template. */
+@DeveloperApi
+public class AlterJobTemplatePreEvent extends JobTemplatePreEvent {
+
+  private final JobTemplateChange[] changes;
+
+  /**
+   * Constructs a new AlterJobTemplatePreEvent instance.
+   *
+   * @param user The user responsible for the operation.
+   * @param metalake The namespace of the job template.
+   * @param jobTemplateName The name of the job template being altered.
+   * @param changes The changes being applied to the job template.
+   */
+  public AlterJobTemplatePreEvent(
+      String user, String metalake, String jobTemplateName, 
JobTemplateChange[] changes) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName));
+    this.changes = changes;
+  }
+
+  /**
+   * Returns the changes being applied to the job template.
+   *
+   * @return An array of {@link JobTemplateChange}.
+   */
+  public JobTemplateChange[] changes() {
+    return changes;
+  }
+
+  /**
+   * Returns the operation type for this event.
+   *
+   * @return The operation type {@link OperationType#ALTER_JOB_TEMPLATE}.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.ALTER_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateEvent.java
new file mode 100644
index 0000000000..dbedea489b
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event that is generated after a job template is successfully 
deleted. */
+@DeveloperApi
+public final class DeleteJobTemplateEvent extends JobTemplateEvent {
+  private final boolean isExists;
+
+  /**
+   * Constructs a new {@code DeleteJobTemplateEvent} instance, encapsulating 
information about the
+   * outcome of a job template delete operation.
+   *
+   * @param user The user who initiated the delete job template operation.
+   * @param metalake The metalake from which the job template was deleted.
+   * @param jobTemplateName The name of the job template.
+   * @param isExists A boolean flag indicating whether the job template 
existed at the time of the
+   *     delete operation.
+   */
+  public DeleteJobTemplateEvent(
+      String user, String metalake, String jobTemplateName, boolean isExists) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName));
+    this.isExists = isExists;
+  }
+
+  /**
+   * Retrieves the existence status of the job template at the time of the 
delete operation.
+   *
+   * @return A boolean value indicating whether the job template existed. 
{@code true} if the job
+   *     template existed, otherwise {@code false}.
+   */
+  public boolean isExists() {
+    return isExists;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.DELETE_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateFailureEvent.java
similarity index 50%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateFailureEvent.java
index a020030a2e..625db0d76b 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplateFailureEvent.java
@@ -17,50 +17,39 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
 /**
- * Represents an event triggered when an attempt to delete a role from a 
metalake fails due to an
- * exception.
+ * Represents an event triggered when an attempt to delete a job template in 
the database fails due
+ * to an exception.
  */
 @DeveloperApi
-public class DeleteRoleFailureEvent extends RoleFailureEvent {
-  private final String roleName;
-
-  /**
-   * Constructs a new {@code DeleteRoleFailureEvent} instance.
-   *
-   * @param user the user who initiated the deletion attempt
-   * @param metalake the target metalake from which the role is to be deleted
-   * @param exception the exception that caused the failure
-   * @param roleName the name of the role intended for deletion
-   */
-  protected DeleteRoleFailureEvent(
-      String user, String metalake, Exception exception, String roleName) {
-    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
-
-    this.roleName = roleName;
-  }
-
+public class DeleteJobTemplateFailureEvent extends JobTemplateFailureEvent {
   /**
-   * Returns the name of the role that was intended for deletion.
+   * Constructs a new {@code DeleteJobTemplateFailureEvent} instance.
    *
-   * @return the name of the role
+   * @param user The user who initiated the job template deletion operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplateName The name of the job template to delete.
+   * @param exception The exception encountered during the job template 
deletion operation,
+   *     providing insights into the reasons behind the operation's failure.
    */
-  public String roleName() {
-    return roleName;
+  public DeleteJobTemplateFailureEvent(
+      String user, String metalake, String jobTemplateName, Exception 
exception) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName), 
exception);
   }
 
   /**
-   * Returns the operation type of this event.
+   * Returns the type of operation.
    *
    * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.DELETE_ROLE;
+    return OperationType.DELETE_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplatePreEvent.java
similarity index 55%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplatePreEvent.java
index c692047726..80b2e520e4 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/DeleteJobTemplatePreEvent.java
@@ -17,35 +17,34 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
-/**
- * Represents an event triggered when an attempt to list usernames from a 
metalake fails due to an
- * exception.
- */
+/** Represents an event triggered before deleting a job template. */
 @DeveloperApi
-public class ListUserNamesFailureEvent extends UserFailureEvent {
+public class DeleteJobTemplatePreEvent extends JobTemplatePreEvent {
+
   /**
-   * Constructs a new {@code ListUserNamesFailureEvent} instance.
+   * Constructs a new {@code DeleteJobTemplatePreEvent} instance.
    *
-   * @param user the user who initiated the operation
-   * @param metalake the name of the metalake where the operation was attempted
-   * @param exception the exception encountered during the operation
+   * @param user The user who initiated the job template deletion operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplateName The name of the job template to delete.
    */
-  protected ListUserNamesFailureEvent(String user, String metalake, Exception 
exception) {
-    super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
+  public DeleteJobTemplatePreEvent(String user, String metalake, String 
jobTemplateName) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName));
   }
 
   /**
-   * Returns the operation type for this event.
+   * Returns the type of operation.
    *
-   * @return the operation type for this event.
+   * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.LIST_USER_NAMES;
+    return OperationType.DELETE_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateEvent.java
similarity index 50%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateEvent.java
index a020030a2e..87f11332a7 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateEvent.java
@@ -17,50 +17,47 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
-/**
- * Represents an event triggered when an attempt to delete a role from a 
metalake fails due to an
- * exception.
- */
+/** Represents an event triggered when a job template has been successfully 
retrieved. */
 @DeveloperApi
-public class DeleteRoleFailureEvent extends RoleFailureEvent {
-  private final String roleName;
+public class GetJobTemplateEvent extends JobTemplateEvent {
+
+  private final JobTemplate jobTemplate;
 
   /**
-   * Constructs a new {@code DeleteRoleFailureEvent} instance.
+   * Constructs a new {@code GetJobTemplateEvent} instance.
    *
-   * @param user the user who initiated the deletion attempt
-   * @param metalake the target metalake from which the role is to be deleted
-   * @param exception the exception that caused the failure
-   * @param roleName the name of the role intended for deletion
+   * @param user The user who initiated the job template retrieval operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplate The job template that has been retrieved.
    */
-  protected DeleteRoleFailureEvent(
-      String user, String metalake, Exception exception, String roleName) {
-    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
-
-    this.roleName = roleName;
+  public GetJobTemplateEvent(String user, String metalake, JobTemplate 
jobTemplate) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, 
jobTemplate.name()));
+    this.jobTemplate = jobTemplate;
   }
 
   /**
-   * Returns the name of the role that was intended for deletion.
+   * Returns the job template that has been loaded.
    *
-   * @return the name of the role
+   * @return the retrieved job template
    */
-  public String roleName() {
-    return roleName;
+  public JobTemplate loadedJobTemplate() {
+    return jobTemplate;
   }
 
   /**
-   * Returns the operation type of this event.
+   * Returns the type of operation.
    *
    * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.DELETE_ROLE;
+    return OperationType.GET_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateFailureEvent.java
similarity index 50%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateFailureEvent.java
index f0a8df36ee..3ab7295f10 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplateFailureEvent.java
@@ -17,46 +17,37 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
-/** Represents an event triggered before a group is added to a metalake. */
+/** Represents an event triggered when the retrieval of a job template has 
failed. */
 @DeveloperApi
-public class AddGroupPreEvent extends GroupPreEvent {
-  private final String groupName;
+public class GetJobTemplateFailureEvent extends JobTemplateFailureEvent {
 
   /**
-   * Constructs a new {@link AddGroupPreEvent} with the specified initiator, 
metalake name, and
-   * group name.
+   * Constructs a new {@code GetJobTemplateFailureEvent} instance.
    *
-   * @param initiator the user who initiated the add-group request.
-   * @param metalake the name of the metalake where the group is to be added.
-   * @param groupName the name of the group that is requested to be added to 
the metalake.
+   * @param user The user who initiated the job template retrieval operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplateName The name of the job template that failed to be 
retrieved.
+   * @param exception The exception encountered during the job template 
retrieval, providing
+   *     insights into the reasons behind the failure.
    */
-  protected AddGroupPreEvent(String initiator, String metalake, String 
groupName) {
-    super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
-
-    this.groupName = groupName;
-  }
-
-  /**
-   * Retrieves the name of the group that is being requested to be added to 
the metalake.
-   *
-   * @return the name of the group to be added.
-   */
-  public String groupName() {
-    return groupName;
+  public GetJobTemplateFailureEvent(
+      String user, String metalake, String jobTemplateName, Exception 
exception) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName), 
exception);
   }
 
   /**
-   * Returns the operation type of this event.
+   * Returns the type of operation.
    *
    * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.ADD_GROUP;
+    return OperationType.GET_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplatePreEvent.java
similarity index 55%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplatePreEvent.java
index c692047726..fc1369a569 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUserNamesFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/GetJobTemplatePreEvent.java
@@ -17,35 +17,34 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
-/**
- * Represents an event triggered when an attempt to list usernames from a 
metalake fails due to an
- * exception.
- */
+/** Represents an event triggered before the retrieval of a job template. */
 @DeveloperApi
-public class ListUserNamesFailureEvent extends UserFailureEvent {
+public class GetJobTemplatePreEvent extends JobTemplatePreEvent {
+
   /**
-   * Constructs a new {@code ListUserNamesFailureEvent} instance.
+   * Constructs a new {@code GetJobTemplatePreEvent} instance.
    *
-   * @param user the user who initiated the operation
-   * @param metalake the name of the metalake where the operation was attempted
-   * @param exception the exception encountered during the operation
+   * @param user The user who initiated the job template retrieval operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplateName The name of the job template to be retrieved.
    */
-  protected ListUserNamesFailureEvent(String user, String metalake, Exception 
exception) {
-    super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
+  public GetJobTemplatePreEvent(String user, String metalake, String 
jobTemplateName) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, jobTemplateName));
   }
 
   /**
-   * Returns the operation type for this event.
+   * Returns the type of operation.
    *
-   * @return the operation type for this event.
+   * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.LIST_USER_NAMES;
+    return OperationType.GET_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateEvent.java
similarity index 51%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateEvent.java
index 1c3d21c67a..96c13208d8 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateEvent.java
@@ -17,32 +17,33 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.Event;
+import org.apache.gravitino.listener.api.event.OperationStatus;
 
-/** Represents an event triggered before list user from specific metalake */
+/**
+ * Represents an abstract base class for events related to job template 
operations. This class
+ * extends {@link Event} to provide a more specific context involving 
operations on job templates,
+ * such as register, alter, or delete.
+ */
 @DeveloperApi
-public class ListUsersPreEvent extends UserPreEvent {
+public abstract class JobTemplateEvent extends Event {
 
   /**
-   * Construct a new {@link ListUsersPreEvent} instance with the specified 
user and identifier.
+   * Constructs a new {@code JobTemplateEvent} with the specified user and job 
template identifier.
    *
-   * @param initiator the user who initiated the list-user request.
-   * @param metalake the metalake name to list users from.
+   * @param user The user responsible for triggering the job template 
operation.
+   * @param identifier The identifier of the job template involved in the 
operation.
    */
-  protected ListUsersPreEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
+  protected JobTemplateEvent(String user, NameIdentifier identifier) {
+    super(user, identifier);
   }
 
-  /**
-   * Returns the operation type for this event.
-   *
-   * @return the operation type for this event.
-   */
   @Override
-  public OperationType operationType() {
-    return OperationType.LIST_USERS;
+  public OperationStatus operationStatus() {
+    return OperationStatus.SUCCESS;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateFailureEvent.java
similarity index 53%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateFailureEvent.java
index 1c3d21c67a..6d18ac4538 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplateFailureEvent.java
@@ -17,32 +17,28 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.FailureEvent;
 
-/** Represents an event triggered before list user from specific metalake */
+/**
+ * Represents an event triggered when an attempt to perform a job template 
operation fails due to an
+ * exception.
+ */
 @DeveloperApi
-public class ListUsersPreEvent extends UserPreEvent {
-
-  /**
-   * Construct a new {@link ListUsersPreEvent} instance with the specified 
user and identifier.
-   *
-   * @param initiator the user who initiated the list-user request.
-   * @param metalake the metalake name to list users from.
-   */
-  protected ListUsersPreEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
-  }
+public abstract class JobTemplateFailureEvent extends FailureEvent {
 
   /**
-   * Returns the operation type for this event.
+   * Constructs a new {@code JobTemplateFailureEvent} instance.
    *
-   * @return the operation type for this event.
+   * @param user The user who initiated the job template operation.
+   * @param identifier The identifier of the job template involved in the 
operation.
+   * @param exception The exception encountered during the job template 
operation, providing
+   *     insights into the reasons behind the failure.
    */
-  @Override
-  public OperationType operationType() {
-    return OperationType.LIST_USERS;
+  protected JobTemplateFailureEvent(String user, NameIdentifier identifier, 
Exception exception) {
+    super(user, identifier, exception);
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplatePreEvent.java
similarity index 56%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplatePreEvent.java
index 1c3d21c67a..1c2e07700d 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/JobTemplatePreEvent.java
@@ -17,32 +17,27 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.PreEvent;
 
-/** Represents an event triggered before list user from specific metalake */
+/**
+ * Represents a pre-event for job template operations. This event is triggered 
before actions such
+ * as registering, altering, or deleting a job template.
+ */
 @DeveloperApi
-public class ListUsersPreEvent extends UserPreEvent {
-
-  /**
-   * Construct a new {@link ListUsersPreEvent} instance with the specified 
user and identifier.
-   *
-   * @param initiator the user who initiated the list-user request.
-   * @param metalake the metalake name to list users from.
-   */
-  protected ListUsersPreEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
-  }
+public abstract class JobTemplatePreEvent extends PreEvent {
 
   /**
-   * Returns the operation type for this event.
+   * Constructs a new {@code JobTemplatePreEvent} with the specified user and 
job template
+   * identifier.
    *
-   * @return the operation type for this event.
+   * @param user The user responsible for triggering the job template 
operation.
+   * @param identifier The identifier of the job template involved in the 
operation.
    */
-  @Override
-  public OperationType operationType() {
-    return OperationType.LIST_USERS;
+  protected JobTemplatePreEvent(String user, NameIdentifier identifier) {
+    super(user, identifier);
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesEvent.java
similarity index 58%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesEvent.java
index 1c3d21c67a..9495311960 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesEvent.java
@@ -17,32 +17,33 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 
-/** Represents an event triggered before list user from specific metalake */
+/** Represents an event that is triggered upon the successful listing of job 
templates. */
 @DeveloperApi
-public class ListUsersPreEvent extends UserPreEvent {
+public final class ListJobTemplatesEvent extends JobTemplateEvent {
 
   /**
-   * Construct a new {@link ListUsersPreEvent} instance with the specified 
user and identifier.
+   * Constructs an instance of {@code ListJobTemplatesEvent}.
    *
-   * @param initiator the user who initiated the list-user request.
-   * @param metalake the metalake name to list users from.
+   * @param user The username of the individual who initiated the job template 
listing.
+   * @param metalake The namespace from which job templates were listed.
    */
-  protected ListUsersPreEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
+  public ListJobTemplatesEvent(String user, String metalake) {
+    super(user, NameIdentifier.of(metalake));
   }
 
   /**
-   * Returns the operation type for this event.
+   * Returns the type of operation.
    *
-   * @return the operation type for this event.
+   * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.LIST_USERS;
+    return OperationType.LIST_JOB_TEMPLATES;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesFailureEvent.java
similarity index 52%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesFailureEvent.java
index 5188e22a9a..ab88fb0466 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesFailureEvent.java
@@ -17,33 +17,37 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 
-/** Represents an event triggered after successfully listing users from a 
specific metalake. */
+/**
+ * Represents an event triggered when an attempt to list job templates fails 
due to an exception.
+ */
 @DeveloperApi
-public class ListUsersEvent extends UserEvent {
+public class ListJobTemplatesFailureEvent extends JobTemplateFailureEvent {
 
   /**
-   * Constructs a new {@link ListUsersEvent} instance with the specified 
initiator and metalake
-   * name.
+   * Constructs a new {@code ListJobTemplatesFailureEvent} instance.
    *
-   * @param initiator the user who initiated the request to list users.
-   * @param metalake the name of the metalake from which the users are listed.
+   * @param user The user who initiated the job template listing operation.
+   * @param metalake The metalake name where the job templates are being 
listed.
+   * @param exception The exception encountered during the job template 
listing operation, providing
+   *     insights into the reasons behind the failure.
    */
-  protected ListUsersEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
+  public ListJobTemplatesFailureEvent(String user, String metalake, Exception 
exception) {
+    super(user, NameIdentifier.of(metalake), exception);
   }
 
   /**
-   * Returns the operation type for this event.
+   * Returns the type of operation.
    *
-   * @return the operation type for this event.
+   * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.LIST_USERS;
+    return OperationType.LIST_JOB_TEMPLATES;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesPreEvent.java
similarity index 59%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesPreEvent.java
index 1c3d21c67a..bd3803ec93 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListUsersPreEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/ListJobTemplatesPreEvent.java
@@ -17,32 +17,32 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
 
-/** Represents an event triggered before list user from specific metalake */
+/** Represents an event triggered before listing job templates. */
 @DeveloperApi
-public class ListUsersPreEvent extends UserPreEvent {
-
+public class ListJobTemplatesPreEvent extends JobTemplatePreEvent {
   /**
-   * Construct a new {@link ListUsersPreEvent} instance with the specified 
user and identifier.
+   * Constructs a new {@code ListJobTemplatesPreEvent} instance.
    *
-   * @param initiator the user who initiated the list-user request.
-   * @param metalake the metalake name to list users from.
+   * @param user The user who initiated the job template listing operation.
+   * @param metalake The metalake name where the job templates are being 
listed.
    */
-  protected ListUsersPreEvent(String initiator, String metalake) {
-    super(initiator, NameIdentifier.of(metalake));
+  public ListJobTemplatesPreEvent(String user, String metalake) {
+    super(user, NameIdentifier.of(metalake));
   }
 
   /**
-   * Returns the operation type for this event.
+   * Returns the type of operation.
    *
-   * @return the operation type for this event.
+   * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.LIST_USERS;
+    return OperationType.LIST_JOB_TEMPLATES;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateEvent.java
new file mode 100644
index 0000000000..9030a1a6af
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateEvent.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered when a job template has been successfully 
registered. */
+@DeveloperApi
+public class RegisterJobTemplateEvent extends JobTemplateEvent {
+
+  private final JobTemplate jobTemplate;
+
+  /**
+   * Constructs a new {@code RegisterJobTemplateEvent} instance.
+   *
+   * @param user The user who initiated the job template registration 
operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplate The job template that has been registered.
+   */
+  public RegisterJobTemplateEvent(String user, String metalake, JobTemplate 
jobTemplate) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, 
jobTemplate.name()));
+    this.jobTemplate = jobTemplate;
+  }
+
+  /**
+   * Returns the job template that has been registered.
+   *
+   * @return the registered job template
+   */
+  public JobTemplate registeredJobTemplate() {
+    return jobTemplate;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.REGISTER_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateFailureEvent.java
new file mode 100644
index 0000000000..9b59c23916
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplateFailureEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event.job;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered when the registration of a job template has 
failed. */
+@DeveloperApi
+public class RegisterJobTemplateFailureEvent extends JobTemplateFailureEvent {
+
+  private final JobTemplate jobTemplate;
+
+  /**
+   * Constructs a new {@code RegisterJobTemplateFailureEvent} instance.
+   *
+   * @param user The user who initiated the job template registration 
operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplate The job template that failed to register.
+   * @param exception The exception encountered during the job template 
registration, providing
+   *     insights into the reasons behind the failure.
+   */
+  public RegisterJobTemplateFailureEvent(
+      String user, String metalake, JobTemplate jobTemplate, Exception 
exception) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, 
jobTemplate.name()), exception);
+    this.jobTemplate = jobTemplate;
+  }
+
+  /**
+   * Returns the job template that failed to register.
+   *
+   * @return the job template
+   */
+  public JobTemplate jobTemplate() {
+    return jobTemplate;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.REGISTER_JOB_TEMPLATE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplatePreEvent.java
similarity index 50%
copy from 
core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
copy to 
core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplatePreEvent.java
index a020030a2e..527c7e797c 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/job/RegisterJobTemplatePreEvent.java
@@ -17,50 +17,47 @@
  * under the License.
  */
 
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.event.job;
 
 import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.listener.api.event.OperationType;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
-/**
- * Represents an event triggered when an attempt to delete a role from a 
metalake fails due to an
- * exception.
- */
+/** Represents an event triggered before the registration of a job template. */
 @DeveloperApi
-public class DeleteRoleFailureEvent extends RoleFailureEvent {
-  private final String roleName;
+public class RegisterJobTemplatePreEvent extends JobTemplatePreEvent {
+
+  private final JobTemplate jobTemplate;
 
   /**
-   * Constructs a new {@code DeleteRoleFailureEvent} instance.
+   * Constructs a new {@code RegisterJobTemplatePreEvent} instance.
    *
-   * @param user the user who initiated the deletion attempt
-   * @param metalake the target metalake from which the role is to be deleted
-   * @param exception the exception that caused the failure
-   * @param roleName the name of the role intended for deletion
+   * @param user The user who initiated the job template registration 
operation.
+   * @param metalake The metalake name where the job template resides.
+   * @param jobTemplate The job template to be registered.
    */
-  protected DeleteRoleFailureEvent(
-      String user, String metalake, Exception exception, String roleName) {
-    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
-
-    this.roleName = roleName;
+  public RegisterJobTemplatePreEvent(String user, String metalake, JobTemplate 
jobTemplate) {
+    super(user, NameIdentifierUtil.ofJobTemplate(metalake, 
jobTemplate.name()));
+    this.jobTemplate = jobTemplate;
   }
 
   /**
-   * Returns the name of the role that was intended for deletion.
+   * Returns the job template to be registered.
    *
-   * @return the name of the role
+   * @return the job template
    */
-  public String roleName() {
-    return roleName;
+  public JobTemplate jobTemplate() {
+    return jobTemplate;
   }
 
   /**
-   * Returns the operation type of this event.
+   * Returns the type of operation.
    *
    * @return the operation type.
    */
   @Override
   public OperationType operationType() {
-    return OperationType.DELETE_ROLE;
+    return OperationType.REGISTER_JOB_TEMPLATE;
   }
 }
diff --git 
a/core/src/main/java/org/apache/gravitino/meta/JobTemplateEntity.java 
b/core/src/main/java/org/apache/gravitino/meta/JobTemplateEntity.java
index de030c5d50..fe60ea4678 100644
--- a/core/src/main/java/org/apache/gravitino/meta/JobTemplateEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/JobTemplateEntity.java
@@ -190,6 +190,37 @@ public class JobTemplateEntity implements Entity, 
Auditable, HasIdentifier {
     return Objects.hash(id, name, namespace, comment, templateContent, 
auditInfo);
   }
 
+  public JobTemplate toJobTemplate() {
+    JobTemplate.JobType jobType = this.templateContent.jobType();
+    if (jobType == JobTemplate.JobType.SHELL) {
+      return ShellJobTemplate.builder()
+          .withName(name)
+          .withComment(comment)
+          .withExecutable(this.templateContent.executable())
+          .withArguments(this.templateContent.arguments())
+          .withEnvironments(this.templateContent.environments())
+          .withCustomFields(this.templateContent.customFields())
+          .withScripts(this.templateContent.scripts())
+          .build();
+    } else if (jobType == JobTemplate.JobType.SPARK) {
+      return SparkJobTemplate.builder()
+          .withName(name)
+          .withComment(comment)
+          .withExecutable(this.templateContent.executable())
+          .withArguments(this.templateContent.arguments())
+          .withEnvironments(this.templateContent.environments())
+          .withCustomFields(this.templateContent.customFields())
+          .withClassName(this.templateContent.className())
+          .withJars(this.templateContent.jars())
+          .withFiles(this.templateContent.files())
+          .withArchives(this.templateContent.archives())
+          .withConfigs(this.templateContent.configs())
+          .build();
+    } else {
+      throw new IllegalStateException("Unsupported job type: " + jobType);
+    }
+  }
+
   public static Builder builder() {
     return new Builder();
   }
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
index a8ba88e9d2..e3f0f5545e 100644
--- 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
@@ -30,6 +30,7 @@ import org.apache.gravitino.authorization.Group;
 import org.apache.gravitino.exceptions.GravitinoRuntimeException;
 import org.apache.gravitino.exceptions.NoSuchGroupException;
 import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+import org.apache.gravitino.listener.AccessControlEventDispatcher;
 import org.apache.gravitino.listener.DummyEventListener;
 import org.apache.gravitino.listener.EventBus;
 import org.apache.gravitino.listener.api.info.GroupInfo;
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestJobEventDispatcher.java
 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestJobEventDispatcher.java
new file mode 100644
index 0000000000..3133b1412b
--- /dev/null
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestJobEventDispatcher.java
@@ -0,0 +1,332 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Objects;
+import org.apache.gravitino.exceptions.GravitinoRuntimeException;
+import org.apache.gravitino.exceptions.JobTemplateAlreadyExistsException;
+import org.apache.gravitino.exceptions.NoSuchJobException;
+import org.apache.gravitino.exceptions.NoSuchJobTemplateException;
+import org.apache.gravitino.job.JobOperationDispatcher;
+import org.apache.gravitino.job.JobTemplate;
+import org.apache.gravitino.job.JobTemplateChange;
+import org.apache.gravitino.listener.DummyEventListener;
+import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.JobEventDispatcher;
+import org.apache.gravitino.listener.api.event.job.AlterJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.AlterJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.AlterJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.DeleteJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.DeleteJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.DeleteJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplateEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.GetJobTemplatePreEvent;
+import org.apache.gravitino.listener.api.event.job.ListJobTemplatesEvent;
+import 
org.apache.gravitino.listener.api.event.job.ListJobTemplatesFailureEvent;
+import org.apache.gravitino.listener.api.event.job.ListJobTemplatesPreEvent;
+import org.apache.gravitino.listener.api.event.job.RegisterJobTemplateEvent;
+import 
org.apache.gravitino.listener.api.event.job.RegisterJobTemplateFailureEvent;
+import org.apache.gravitino.listener.api.event.job.RegisterJobTemplatePreEvent;
+import org.apache.gravitino.meta.AuditInfo;
+import org.apache.gravitino.meta.JobTemplateEntity;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+
+@TestInstance(Lifecycle.PER_CLASS)
+public class TestJobEventDispatcher {
+  private JobEventDispatcher failureDispatcher;
+  private JobEventDispatcher dispatcher;
+  private DummyEventListener dummyEventListener;
+  private JobTemplateEntity jobTemplateEntity;
+
+  @BeforeAll
+  void init() {
+    this.jobTemplateEntity = mockJobTemplateEntity();
+    this.dummyEventListener = new DummyEventListener();
+    EventBus eventBus = new 
EventBus(Collections.singletonList(dummyEventListener));
+    JobOperationDispatcher jobExceptionDispatcher = 
mockExceptionJobDispatcher();
+    this.failureDispatcher = new JobEventDispatcher(eventBus, 
jobExceptionDispatcher);
+    JobOperationDispatcher jobDispatcher = mockJobDispatcher();
+    this.dispatcher = new JobEventDispatcher(eventBus, jobDispatcher);
+  }
+
+  @Test
+  void testListJobTemplatesEvent() {
+    dispatcher.listJobTemplates("metalake");
+    PreEvent preEvent = dummyEventListener.popPreEvent();
+
+    Assertions.assertEquals("metalake", 
Objects.requireNonNull(preEvent.identifier()).toString());
+    Assertions.assertInstanceOf(ListJobTemplatesPreEvent.class, preEvent);
+    Assertions.assertEquals(OperationType.LIST_JOB_TEMPLATES, 
preEvent.operationType());
+    Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postEvent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals("metalake", 
Objects.requireNonNull(postEvent.identifier()).toString());
+    Assertions.assertInstanceOf(ListJobTemplatesEvent.class, postEvent);
+    Assertions.assertEquals(OperationType.LIST_JOB_TEMPLATES, 
postEvent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postEvent.operationStatus());
+  }
+
+  @Test
+  void testRegisterJobTemplateEvent() {
+    dispatcher.registerJobTemplate("metalake", jobTemplateEntity);
+    PreEvent preEvent = dummyEventListener.popPreEvent();
+
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(preEvent.identifier()));
+    Assertions.assertInstanceOf(RegisterJobTemplatePreEvent.class, preEvent);
+    Assertions.assertEquals(OperationType.REGISTER_JOB_TEMPLATE, 
preEvent.operationType());
+    Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    JobTemplate jobTemplate = ((RegisterJobTemplatePreEvent) 
preEvent).jobTemplate();
+    checkJobTemplate(jobTemplate, jobTemplateEntity);
+
+    Event postEvent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(postEvent.identifier()));
+    Assertions.assertInstanceOf(RegisterJobTemplateEvent.class, postEvent);
+    Assertions.assertEquals(OperationType.REGISTER_JOB_TEMPLATE, 
postEvent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postEvent.operationStatus());
+
+    JobTemplate registeredJobTemplate =
+        ((RegisterJobTemplateEvent) postEvent).registeredJobTemplate();
+    checkJobTemplate(registeredJobTemplate, jobTemplateEntity);
+  }
+
+  @Test
+  void testGetJobTemplateEvent() {
+    dispatcher.getJobTemplate("metalake", jobTemplateEntity.name());
+    PreEvent preEvent = dummyEventListener.popPreEvent();
+
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(preEvent.identifier()));
+    Assertions.assertInstanceOf(GetJobTemplatePreEvent.class, preEvent);
+    Assertions.assertEquals(OperationType.GET_JOB_TEMPLATE, 
preEvent.operationType());
+    Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postEvent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(postEvent.identifier()));
+    Assertions.assertInstanceOf(GetJobTemplateEvent.class, postEvent);
+    Assertions.assertEquals(OperationType.GET_JOB_TEMPLATE, 
postEvent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postEvent.operationStatus());
+
+    JobTemplate retrievedJobTemplate = ((GetJobTemplateEvent) 
postEvent).loadedJobTemplate();
+    checkJobTemplate(retrievedJobTemplate, jobTemplateEntity);
+  }
+
+  @Test
+  void testDeleteJobTemplateEvent() {
+    dispatcher.deleteJobTemplate("metalake", jobTemplateEntity.name());
+    PreEvent preEvent = dummyEventListener.popPreEvent();
+
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(preEvent.identifier()));
+    Assertions.assertInstanceOf(DeleteJobTemplatePreEvent.class, preEvent);
+    Assertions.assertEquals(OperationType.DELETE_JOB_TEMPLATE, 
preEvent.operationType());
+    Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postEvent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(postEvent.identifier()));
+    Assertions.assertInstanceOf(DeleteJobTemplateEvent.class, postEvent);
+    Assertions.assertEquals(OperationType.DELETE_JOB_TEMPLATE, 
postEvent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postEvent.operationStatus());
+
+    boolean isExists = ((DeleteJobTemplateEvent) postEvent).isExists();
+    Assertions.assertTrue(isExists);
+  }
+
+  @Test
+  void testAlterJobTemplateEvent() {
+    JobTemplateChange change1 = JobTemplateChange.rename("newName");
+    JobTemplateChange[] changes = {change1};
+
+    dispatcher.alterJobTemplate("metalake", jobTemplateEntity.name(), changes);
+    PreEvent preEvent = dummyEventListener.popPreEvent();
+
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(preEvent.identifier()));
+    Assertions.assertInstanceOf(AlterJobTemplatePreEvent.class, preEvent);
+    Assertions.assertEquals(OperationType.ALTER_JOB_TEMPLATE, 
preEvent.operationType());
+    Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    JobTemplateChange[] eventChanges = ((AlterJobTemplatePreEvent) 
preEvent).changes();
+    Assertions.assertArrayEquals(changes, eventChanges);
+
+    Event postEvent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofJobTemplate("metalake", jobTemplateEntity.name()),
+        Objects.requireNonNull(postEvent.identifier()));
+    Assertions.assertInstanceOf(AlterJobTemplateEvent.class, postEvent);
+    Assertions.assertEquals(OperationType.ALTER_JOB_TEMPLATE, 
postEvent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postEvent.operationStatus());
+
+    JobTemplateChange[] postChanges = ((AlterJobTemplateEvent) 
postEvent).changes();
+    Assertions.assertArrayEquals(changes, postChanges);
+
+    JobTemplate updatedJobTemplate = ((AlterJobTemplateEvent) 
postEvent).updatedJobTemplate();
+    checkJobTemplate(updatedJobTemplate, jobTemplateEntity);
+  }
+
+  // Failure event tests
+  @Test
+  void testRegisterJobTemplateFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.registerJobTemplate("metalake", 
jobTemplateEntity));
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertInstanceOf(RegisterJobTemplateFailureEvent.class, event);
+    Assertions.assertEquals(
+        GravitinoRuntimeException.class,
+        ((RegisterJobTemplateFailureEvent) event).exception().getClass());
+    Assertions.assertEquals(OperationType.REGISTER_JOB_TEMPLATE, 
event.operationType());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+
+    JobTemplate jobTemplate = ((RegisterJobTemplateFailureEvent) 
event).jobTemplate();
+    checkJobTemplate(jobTemplate, jobTemplateEntity);
+  }
+
+  @Test
+  void testGetJobTemplateFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.getJobTemplate("metalake", 
jobTemplateEntity.name()));
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertInstanceOf(GetJobTemplateFailureEvent.class, event);
+    Assertions.assertEquals(
+        GravitinoRuntimeException.class,
+        ((GetJobTemplateFailureEvent) event).exception().getClass());
+    Assertions.assertEquals(OperationType.GET_JOB_TEMPLATE, 
event.operationType());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+  }
+
+  @Test
+  void testDeleteJobTemplateFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.deleteJobTemplate("metalake", 
jobTemplateEntity.name()));
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertInstanceOf(DeleteJobTemplateFailureEvent.class, event);
+    Assertions.assertEquals(
+        GravitinoRuntimeException.class,
+        ((DeleteJobTemplateFailureEvent) event).exception().getClass());
+    Assertions.assertEquals(OperationType.DELETE_JOB_TEMPLATE, 
event.operationType());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+  }
+
+  @Test
+  void testAlterJobTemplateFailureEvent() {
+    JobTemplateChange change1 = JobTemplateChange.rename("newName");
+    JobTemplateChange change2 = JobTemplateChange.updateComment("new comment");
+    JobTemplateChange[] changes = new JobTemplateChange[] {change1, change2};
+
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.alterJobTemplate("metalake", 
jobTemplateEntity.name(), changes));
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertInstanceOf(AlterJobTemplateFailureEvent.class, event);
+    Assertions.assertEquals(
+        GravitinoRuntimeException.class,
+        ((AlterJobTemplateFailureEvent) event).exception().getClass());
+    Assertions.assertEquals(changes, ((AlterJobTemplateFailureEvent) 
event).changes());
+    Assertions.assertEquals(OperationType.ALTER_JOB_TEMPLATE, 
event.operationType());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+  }
+
+  @Test
+  void testListJobTemplatesFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class, () -> 
failureDispatcher.listJobTemplates("metalake"));
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertInstanceOf(ListJobTemplatesFailureEvent.class, event);
+    Assertions.assertEquals(
+        GravitinoRuntimeException.class,
+        ((ListJobTemplatesFailureEvent) event).exception().getClass());
+    Assertions.assertEquals(OperationType.LIST_JOB_TEMPLATES, 
event.operationType());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+  }
+
+  private JobTemplateEntity mockJobTemplateEntity() {
+    JobTemplateEntity entity = mock(JobTemplateEntity.class);
+    when(entity.name()).thenReturn("testJobTemplate");
+    when(entity.comment()).thenReturn("test comment");
+    when(entity.auditInfo()).thenReturn(mock(AuditInfo.class));
+
+    JobTemplate jobTemplate = mock(JobTemplate.class);
+    when(jobTemplate.name()).thenReturn("testJobTemplate");
+    when(jobTemplate.comment()).thenReturn("test comment");
+    when(entity.toJobTemplate()).thenReturn(jobTemplate);
+
+    return entity;
+  }
+
+  private JobOperationDispatcher mockExceptionJobDispatcher() {
+    return mock(
+        JobOperationDispatcher.class,
+        invocation -> {
+          throw new GravitinoRuntimeException("Exception for all methods");
+        });
+  }
+
+  private void checkJobTemplate(JobTemplate actual, JobTemplateEntity 
expected) {
+    Assertions.assertEquals(expected.name(), actual.name());
+    Assertions.assertEquals(expected.comment(), actual.comment());
+  }
+
+  private JobOperationDispatcher mockJobDispatcher() {
+    JobOperationDispatcher dispatcher = mock(JobOperationDispatcher.class);
+    String metalake = "metalake";
+
+    try {
+      when(dispatcher.listJobTemplates(metalake))
+          .thenReturn(Collections.singletonList(jobTemplateEntity));
+      when(dispatcher.getJobTemplate(any(String.class), any(String.class)))
+          .thenReturn(jobTemplateEntity);
+      when(dispatcher.deleteJobTemplate(metalake, 
jobTemplateEntity.name())).thenReturn(true);
+      when(dispatcher.alterJobTemplate(
+              any(String.class), any(String.class), 
any(JobTemplateChange[].class)))
+          .thenReturn(jobTemplateEntity);
+    } catch (JobTemplateAlreadyExistsException
+        | NoSuchJobTemplateException
+        | NoSuchJobException e) {
+      // This shouldn't happen in our mock setup
+    }
+
+    return dispatcher;
+  }
+}
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
index 697c3836bd..515fd3cdcb 100644
--- 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
@@ -40,6 +40,7 @@ import org.apache.gravitino.authorization.Role;
 import org.apache.gravitino.authorization.SecurableObject;
 import org.apache.gravitino.authorization.User;
 import org.apache.gravitino.exceptions.GravitinoRuntimeException;
+import org.apache.gravitino.listener.AccessControlEventDispatcher;
 import org.apache.gravitino.listener.DummyEventListener;
 import org.apache.gravitino.listener.EventBus;
 import org.apache.gravitino.listener.api.info.RoleInfo;
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestUserEvent.java 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestUserEvent.java
index d4fe9f00e8..c6574a140e 100644
--- 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestUserEvent.java
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestUserEvent.java
@@ -30,6 +30,7 @@ import org.apache.gravitino.authorization.User;
 import org.apache.gravitino.exceptions.GravitinoRuntimeException;
 import org.apache.gravitino.exceptions.NoSuchMetalakeException;
 import org.apache.gravitino.exceptions.NoSuchUserException;
+import org.apache.gravitino.listener.AccessControlEventDispatcher;
 import org.apache.gravitino.listener.DummyEventListener;
 import org.apache.gravitino.listener.EventBus;
 import org.apache.gravitino.listener.api.info.UserInfo;
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index 749d0e66f3..b3aaec9fca 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -172,41 +172,41 @@ Gravitino triggers a pre-event before the operation, a 
post-event after the comp
 
 ##### Post-event
 
-| Operation type                      | Post-event                             
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
-|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
-| table operation                     | `CreateTableEvent`, `AlterTableEvent`, 
`DropTableEvent`, `LoadTableEvent`, `ListTableEvent`, `PurgeTableFailureEvent`, 
`CreateTableFailureEvent`, `AlterTableFailureEvent`, `DropTableFailureEvent`, 
`LoadTableFailureEvent`, `ListTableFailureEvent`, `PurgeTableFailureEvent`      
                                                                                
                                                                                
                [...]
-| fileset operation                   | `CreateFileSetEvent`, 
`AlterFileSetEvent`, `DropFileSetEvent`, `LoadFileSetEvent`, 
`ListFileSetEvent`, `CreateFileSetFailureEvent`, `AlterFileSetFailureEvent`, 
`DropFileSetFailureEvent`, `LoadFileSetFailureEvent`, 
`ListFileSetFailureEvent`, `ListFilesFailureEvent`                              
                                                                                
                                                                               
[...]
-| topic operation                     | `CreateTopicEvent`, `AlterTopicEvent`, 
`DropTopicEvent`, `LoadTopicEvent`, `ListTopicEvent`, 
`CreateTopicFailureEvent`, `AlterTopicFailureEvent`, `DropTopicFailureEvent`, 
`LoadTopicFailureEvent`, `ListTopicFailureEvent`                                
                                                                                
                                                                                
                                          [...]
-| schema operation                    | `CreateSchemaEvent`, 
`AlterSchemaEvent`, `DropSchemaEvent`, `LoadSchemaEvent`, `ListSchemaEvent`, 
`CreateSchemaFailureEvent`, `AlterSchemaFailureEvent`, 
`DropSchemaFailureEvent`, `LoadSchemaFailureEvent`, `ListSchemaFailureEvent`    
                                                                                
                                                                                
                                                            [...]
-| catalog operation                   | `CreateCatalogEvent`, 
`AlterCatalogEvent`, `DropCatalogEvent`, `LoadCatalogEvent`, 
`ListCatalogEvent`, `CreateCatalogFailureEvent`, `AlterCatalogFailureEvent`, 
`DropCatalogFailureEvent`, `LoadCatalogFailureEvent`, `ListCatalogFailureEvent` 
                                                                                
                                                                                
                                                     [...]
-| metalake operation                  | `CreateMetalakeEvent`, 
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`, 
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`, 
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`, 
`ListMetalakeFailureEvent`                                                      
                                                                                
                                                                      [...]
-| Iceberg REST server table operation | `IcebergCreateTableEvent`, 
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`, 
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`, 
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`, 
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`, 
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`, 
`IcebergTableExistsFailureEvent`                                        [...]
-| tag operation                       | `ListTagsEvent`, `ListTagsInfoEvent`, 
`CreateTagEvent`, `GetTagEvent`, `AlterTagEvent`, `DeleteTagEvent`, 
`ListMetadataObjectsForTagEvent`, `ListTagsForMetadataObjectEvent`, 
`ListTagsInfoForMetadataObjectEvent`, `AssociateTagsForMetadataObjectEvent`, 
`GetTagForMetadataObjectEvent`, `ListTagsFailureEvent`, 
`ListTagInfoFailureEvent`, `CreateTagFailureEvent`, `GetTagFailureEvent`, 
`AlterTagFailureEvent`, `DeleteTagFailureEvent`, `ListMetadataObjectsFo [...]
-| model operation                     | `DeleteModelEvent`,  
`DeleteModelVersionEvent`,  `GetModelEvent`, `GetModelVersionEvent`, 
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,  
`RegisterAndLinkModelEvent`, `RegisterModelEvent`, `AlterModelEvent`, 
`AlterModelVersionEvent`,`DeleteModelFailureEvent`, 
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`, 
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`, 
`ListModelFailureEvent`, `ListModelVersionFailure [...]
-| user operation                      | `AddUserEvent`, `GetUserEvent`, 
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`, 
`GrantUserRolesEvent`, `RevokeUserRolesEvent`, `AddUserFailureEvent`, 
`GetUserFailureEvent`, `GrantUserRolesFailureEvent`, 
`ListUserNamesFailureEvent`, `ListUsersFailureEvent`, `RemoveUserFailureEvent`, 
`RevokeUserRolesFailureEvent`                                                   
                                                                               
[...]
-| group operation                     | `AddGroupEvent`, `GetGroupEvent`, 
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`, 
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`, `AddGroupFailureEvent`, 
`GetGroupFailureEvent`, `GrantGroupRolesFailureEvent`, 
`ListGroupNamesFailureEvent`, `ListGroupsFailureEvent`, 
`RemoveGroupFailureEvent`, `RevokeGroupRolesFailureEvent`                       
                                                                                
             [...]
-| role operation                      | `CreateRoleEvent`, `DeleteRoleEvent`, 
`GetRoleEvent`, `GrantPrivilegesEvent`, `ListRoleNamesEvent`, 
`RevokePrivilegesEvent`, `CreateRoleFailureEvent`, `DeleteRoleFailureEvent`, 
`GetRoleFailureEvent`, `GrantPrivilegesFailureEvent`, 
`ListRoleNamesFailureEvent`, `RevokePrivilegesFailureEvent`                     
                                                                                
                                                              [...]
-| owner operation                     | `SetOwnerEvent`, `GetOwnerEvent`       
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
-
-
+| Operation type                          | Post-event                         
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
+|-----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+| table operation                         | `CreateTableEvent`, 
`AlterTableEvent`, `DropTableEvent`, `LoadTableEvent`, `ListTableEvent`, 
`PurgeTableFailureEvent`, `CreateTableFailureEvent`, `AlterTableFailureEvent`, 
`DropTableFailureEvent`, `LoadTableFailureEvent`, `ListTableFailureEvent`, 
`PurgeTableFailureEvent`                                                        
                                                                                
                                          [...]
+| fileset operation                       | `CreateFileSetEvent`, 
`AlterFileSetEvent`, `DropFileSetEvent`, `LoadFileSetEvent`, 
`ListFileSetEvent`, `CreateFileSetFailureEvent`, `AlterFileSetFailureEvent`, 
`DropFileSetFailureEvent`, `LoadFileSetFailureEvent`, 
`ListFileSetFailureEvent`, `ListFilesFailureEvent`                              
                                                                                
                                                                           [...]
+| topic operation                         | `CreateTopicEvent`, 
`AlterTopicEvent`, `DropTopicEvent`, `LoadTopicEvent`, `ListTopicEvent`, 
`CreateTopicFailureEvent`, `AlterTopicFailureEvent`, `DropTopicFailureEvent`, 
`LoadTopicFailureEvent`, `ListTopicFailureEvent`                                
                                                                                
                                                                                
                                      [...]
+| schema operation                        | `CreateSchemaEvent`, 
`AlterSchemaEvent`, `DropSchemaEvent`, `LoadSchemaEvent`, `ListSchemaEvent`, 
`CreateSchemaFailureEvent`, `AlterSchemaFailureEvent`, 
`DropSchemaFailureEvent`, `LoadSchemaFailureEvent`, `ListSchemaFailureEvent`    
                                                                                
                                                                                
                                                        [...]
+| catalog operation                       | `CreateCatalogEvent`, 
`AlterCatalogEvent`, `DropCatalogEvent`, `LoadCatalogEvent`, 
`ListCatalogEvent`, `CreateCatalogFailureEvent`, `AlterCatalogFailureEvent`, 
`DropCatalogFailureEvent`, `LoadCatalogFailureEvent`, `ListCatalogFailureEvent` 
                                                                                
                                                                                
                                                 [...]
+| metalake operation                      | `CreateMetalakeEvent`, 
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`, 
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`, 
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`, 
`ListMetalakeFailureEvent`                                                      
                                                                                
                                                                  [...]
+| Iceberg REST server table operation     | `IcebergCreateTableEvent`, 
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`, 
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`, 
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`, 
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`, 
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`, 
`IcebergTableExistsFailureEvent`                                    [...]
+| tag operation                           | `ListTagsEvent`, 
`ListTagsInfoEvent`, `CreateTagEvent`, `GetTagEvent`, `AlterTagEvent`, 
`DeleteTagEvent`, `ListMetadataObjectsForTagEvent`, 
`ListTagsForMetadataObjectEvent`, `ListTagsInfoForMetadataObjectEvent`, 
`AssociateTagsForMetadataObjectEvent`, `GetTagForMetadataObjectEvent`, 
`ListTagsFailureEvent`, `ListTagInfoFailureEvent`, `CreateTagFailureEvent`, 
`GetTagFailureEvent`, `AlterTagFailureEvent`, `DeleteTagFailureEvent`, 
`ListMetadataObjec [...]
+| model operation                         | `DeleteModelEvent`,  
`DeleteModelVersionEvent`,  `GetModelEvent`, `GetModelVersionEvent`, 
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,  
`RegisterAndLinkModelEvent`, `RegisterModelEvent`, `AlterModelEvent`, 
`AlterModelVersionEvent`,`DeleteModelFailureEvent`, 
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`, 
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`, 
`ListModelFailureEvent`, `ListModelVersionFai [...]
+| user operation                          | `AddUserEvent`, `GetUserEvent`, 
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`, 
`GrantUserRolesEvent`, `RevokeUserRolesEvent`, `AddUserFailureEvent`, 
`GetUserFailureEvent`, `GrantUserRolesFailureEvent`, 
`ListUserNamesFailureEvent`, `ListUsersFailureEvent`, `RemoveUserFailureEvent`, 
`RevokeUserRolesFailureEvent`                                                   
                                                                           [...]
+| group operation                         | `AddGroupEvent`, `GetGroupEvent`, 
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`, 
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`, `AddGroupFailureEvent`, 
`GetGroupFailureEvent`, `GrantGroupRolesFailureEvent`, 
`ListGroupNamesFailureEvent`, `ListGroupsFailureEvent`, 
`RemoveGroupFailureEvent`, `RevokeGroupRolesFailureEvent`                       
                                                                                
         [...]
+| role operation                          | `CreateRoleEvent`, 
`DeleteRoleEvent`, `GetRoleEvent`, `GrantPrivilegesEvent`, 
`ListRoleNamesEvent`, `RevokePrivilegesEvent`, `CreateRoleFailureEvent`, 
`DeleteRoleFailureEvent`, `GetRoleFailureEvent`, `GrantPrivilegesFailureEvent`, 
`ListRoleNamesFailureEvent`, `RevokePrivilegesFailureEvent`                     
                                                                                
                                                          [...]
+| owner operation                         | `SetOwnerEvent`, `GetOwnerEvent`   
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
+| Gravitino server job template operation | `RegisterJobTemplateEvent`, 
`GetJobTemplateEvent`, `ListJobTemplatesEvent`, `AlterJobTemplateEvent`, 
`DeleteJobTemplateEvent`, `RegisterJobTemplateFailureEvent`, 
`GetJobTemplateFailureEvent`, `ListJobTemplatesFailureEvent`, 
`AlterJobTemplateFailureEvent`, `DeleteJobTemplateFailureEvent`                 
                                                                                
                                                                 [...]
 
 ##### Pre-event
 
-| Operation type                       | Pre-event                             
                                                                                
                                                                                
                                                                                
                                     | Since Version    |
-|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
-| Iceberg REST server table operation  | `IcebergCreateTablePreEvent`, 
`IcebergUpdateTablePreEvent`, `IcebergDropTablePreEvent`, 
`IcebergLoadTablePreEvent`, `IcebergListTablePreEvent`, 
`IcebergTableExistsPreEvent`, `IcebergRenameTablePreEvent`                      
                                                                                
           | 0.7.0-incubating |
-| Gravitino server table operation     | `CreateTablePreEvent`, 
`AlterTablePreEvent`, `DropTablePreEvent`, `PurgeTablePreEvent`, 
`LoadTablePreEvent`, `ListTablePreEvent`                                        
                                                                                
                                                                   | 
0.8.0-incubating |
-| Gravitino server schema operation    | `CreateSchemaPreEvent`, 
`AlterSchemaPreEvent`, `DropSchemaPreEvent`, `LoadSchemaPreEvent`, 
`ListSchemaPreEvent`                                                            
                                                                                
                                                                | 
0.8.0-incubating |
-| Gravitino server catalog operation   | `CreateCatalogPreEvent`, 
`AlterCatalogPreEvent`, `DropCatalogPreEvent`, `LoadCatalogPreEvent`, 
`ListCatalogPreEvent`                                                           
                                                                                
                                                            | 0.8.0-incubating |
-| Gravitino server metalake operation  | `CreateMetalakePreEvent`, 
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
                                                                                
                                                                                
                                     | 0.8.0-incubating |
-| Gravitino server partition operation | `AddPartitionPreEvent`, 
`DropPartitionPreEvent`, `GetPartitionPreEvent`, 
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`   
                                                                                
                                                                                
  | 0.8.0-incubating |
-| Gravitino server fileset operation   | `CreateFilesetPreEvent`, 
`AlterFilesetPreEvent`, `DropFilesetPreEvent`, 
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`, 
`ListFilesPreEvent`                                                             
                                                                                
            | 0.8.0-incubating |
-| Gravitino server model operation     | `DeleteModelPreEvent`, 
`DeleteModelVersionPreEvent`, 
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`, 
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`,
 `AlterModelPreEvent`, `AlterModelVersionPreEvent`, `AlterModelVersionPreEvent` 
                                  | 0.9.0-incubating |
-| Gravitino server tag operation       | `ListTagsPreEvent`, 
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`, 
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`, 
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`, 
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` | 
0.9.0-incubating |
-| Gravitino server user operation      | `AddUserPreEvent`, `GetUserPreEvent`, 
`ListUserNamesPreEvent`, `ListUsersPreEvent`, `RemoveUserPreEvent`, 
`GrantUserRolesPreEvent`, `RevokeUserRolesPreEvent`                             
                                                                                
                                                 | 0.9.0-incubating |
-| Gravitino server group operation     | `AddGroupPreEvent`, 
`GetGroupPreEvent`, `ListGroupNamesPreEvent`, `ListGroupsPreEvent`, 
`RemoveGroupPreEvent`, `GrantGroupRolesPreEvent`, `RevokeGroupRolesPreEvent`    
                                                                                
                                                                   | 
0.9.0-incubating |
-| Gravitino server role operation      | `CreateRolePreEvent`, 
`DeleteRolePreEvent`, `GetRolePreEvent`, `GrantPrivilegesPreEvent`, 
`ListRoleNamesPreEvent`, `RevokePrivilegesPreEvent`                             
                                                                                
                                                                 | 
0.9.0-incubating |
- | Gravitino server owner operation    | `SetOwnerPreEvent`, 
`GetOwnerPreEvent`                                                              
                                                                                
                                                                                
                                                       | 1.0.0            |
+| Operation type                          | Pre-event                          
                                                                                
                                                                                
                                                                                
                                        | Since Version    |
+|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
+| Iceberg REST server table operation     | `IcebergCreateTablePreEvent`, 
`IcebergUpdateTablePreEvent`, `IcebergDropTablePreEvent`, 
`IcebergLoadTablePreEvent`, `IcebergListTablePreEvent`, 
`IcebergTableExistsPreEvent`, `IcebergRenameTablePreEvent`                      
                                                                                
           | 0.7.0-incubating |
+| Gravitino server table operation        | `CreateTablePreEvent`, 
`AlterTablePreEvent`, `DropTablePreEvent`, `PurgeTablePreEvent`, 
`LoadTablePreEvent`, `ListTablePreEvent`                                        
                                                                                
                                                                   | 
0.8.0-incubating |
+| Gravitino server schema operation       | `CreateSchemaPreEvent`, 
`AlterSchemaPreEvent`, `DropSchemaPreEvent`, `LoadSchemaPreEvent`, 
`ListSchemaPreEvent`                                                            
                                                                                
                                                                | 
0.8.0-incubating |
+| Gravitino server catalog operation      | `CreateCatalogPreEvent`, 
`AlterCatalogPreEvent`, `DropCatalogPreEvent`, `LoadCatalogPreEvent`, 
`ListCatalogPreEvent`                                                           
                                                                                
                                                            | 0.8.0-incubating |
+| Gravitino server metalake operation     | `CreateMetalakePreEvent`, 
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
                                                                                
                                                                                
                                     | 0.8.0-incubating |
+| Gravitino server partition operation    | `AddPartitionPreEvent`, 
`DropPartitionPreEvent`, `GetPartitionPreEvent`, 
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`   
                                                                                
                                                                                
  | 0.8.0-incubating |
+| Gravitino server fileset operation      | `CreateFilesetPreEvent`, 
`AlterFilesetPreEvent`, `DropFilesetPreEvent`, 
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`, 
`ListFilesPreEvent`                                                             
                                                                                
            | 0.8.0-incubating |
+| Gravitino server model operation        | `DeleteModelPreEvent`, 
`DeleteModelVersionPreEvent`, 
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`, 
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`,
 `AlterModelPreEvent`, `AlterModelVersionPreEvent`, `AlterModelVersionPreEvent` 
                                  | 0.9.0-incubating |
+| Gravitino server tag operation          | `ListTagsPreEvent`, 
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`, 
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`, 
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`, 
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` | 
0.9.0-incubating |
+| Gravitino server user operation         | `AddUserPreEvent`, 
`GetUserPreEvent`, `ListUserNamesPreEvent`, `ListUsersPreEvent`, 
`RemoveUserPreEvent`, `GrantUserRolesPreEvent`, `RevokeUserRolesPreEvent`       
                                                                                
                                                                       | 
0.9.0-incubating |
+| Gravitino server group operation        | `AddGroupPreEvent`, 
`GetGroupPreEvent`, `ListGroupNamesPreEvent`, `ListGroupsPreEvent`, 
`RemoveGroupPreEvent`, `GrantGroupRolesPreEvent`, `RevokeGroupRolesPreEvent`    
                                                                                
                                                                   | 
0.9.0-incubating |
+| Gravitino server role operation         | `CreateRolePreEvent`, 
`DeleteRolePreEvent`, `GetRolePreEvent`, `GrantPrivilegesPreEvent`, 
`ListRoleNamesPreEvent`, `RevokePrivilegesPreEvent`                             
                                                                                
                                                                 | 
0.9.0-incubating |
+| Gravitino server owner operation        | `SetOwnerPreEvent`, 
`GetOwnerPreEvent`                                                              
                                                                                
                                                                                
                                                       | 1.0.0            |
+| Gravitino server job template operation | `RegisterJobTemplatePreEvent`, 
`GetJobTemplatePreEvent`, `ListJobTemplatesPreEvent`, 
`AlterJobTemplatePreEvent`, `DeleteJobTemplatePreEvent`                         
                                                                                
                                                                      | 1.0.1   
         |
 
 #### Event listener plugin
 


Reply via email to