Namazu Elements provides the ability to react to various events that are produced by either the core system, or other custom Elements. This allows for your code to react to things as they happen, such as setting startup code when an Element is loader, or configuring a Profile with default properties when a new Profile is created. Functions that receive the event are called Event Consumers, and functions that send the event are called Event Producers.
Determining Available Events #
You can see which events are available to consume by looking under Produced Events in the Core Elements section of the CMS.

DAO level events will always have two versions – one that occurs during the transaction, with a reference to the transaction itself, and one that occurs after the transaction. This is important, as sometimes you might want to communicate with the database and ensure that your event consumer has the same protections and retries that a transaction provides. In these cases, it’s important to ensure that your code is idempotent, and that you use the transaction itself to get any DAO classes. For example:
@ElementEventConsumer(ReceiptDao.RECEIPT_CREATED)
public void onReceiptCreated(Receipt receipt, Transaction transaction) {
final User user = transaction.performAndCloseV(txn -> {
final var dao = txn.getDao(UserDao.class);
final var txUser = dao.getUser(receipt.getUser.getId());
//Do something with the User here
return txUser;
});
//The transaction has completed at this point
}
You can also view the Produced Events for an individual Element by navigating to the Element Info screen for that Element.

This information comes from the SystemElementsResource (GET /elements/system) and the ApplicationElementResource (GET /elements/application) respectively.
Code Samples #
To consume an event, be sure to place it in a service that has been registered in package-info.java like so:
// Makes this discoverable by the event system
@ElementService(
value = EventHandler.class,
implementation = @ElementServiceImplementation(EventHandlerImpl.class)
)
where in this case, EventHandler is an interface that has been made public:
@ElementPublic
public interface EventHandler {}
and EventHandlerImpl is the implementation class that looks like so:
package com.namazustudios.events;
import dev.getelements.elements.sdk.ElementLoader;
import dev.getelements.elements.sdk.Event;
import dev.getelements.elements.sdk.annotation.ElementEventConsumer;
import dev.getelements.elements.sdk.dao.DistinctInventoryItemDao;
import dev.getelements.elements.sdk.dao.InventoryItemDao;
import dev.getelements.elements.sdk.dao.ItemDao;
import dev.getelements.elements.sdk.model.goods.Item;
import dev.getelements.elements.sdk.model.inventory.DistinctInventoryItem;
import dev.getelements.elements.sdk.model.inventory.InventoryItem;
import dev.getelements.elements.sdk.model.profile.Profile;
import dev.getelements.elements.sdk.service.profile.ProfileService;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.inject.Inject;
import static com.namazustudios.util.Constants.STARTING_AVATAR_ITEM_NAME;
import static com.namazustudios.util.Constants.EXP_ITEM_NAME;
@Hidden
public class EventHandlerImpl implements EventHandler {
@Inject
private InventoryItemDao inventoryItemDao;
@Inject
private DistinctInventoryItemDao distinctInventoryItemDao;
private Item startingAvatarItem;
private Item expItem;
@Inject
private void init(ItemDao itemDao) {
startingAvatarItem = itemDao.getItemByIdOrName(STARTING_AVATAR_ITEM_NAME);
expItem = itemDao.getItemByIdOrName(EXP_ITEM_NAME);
}
@ElementEventConsumer(ProfileService.PROFILE_CREATED_EVENT)
public void onNewProfileCreatedEvent(final Profile profile) {
assignStartingAvatarItem(profile);
assignStartingExp(profile);
}
@ElementEventConsumer(ElementLoader.SYSTEM_EVENT_ELEMENT_LOADED)
public void onElementLoadedEvent(Event event) {
System.out.println("System event loaded");
}
private void assignStartingAvatarItem(final Profile profile) {
final var distinctInventoryItem = new DistinctInventoryItem();
distinctInventoryItem.setItem(startingAvatarItem);
distinctInventoryItem.setProfile(profile);
distinctInventoryItem.setUser(profile.getUser());
distinctInventoryItemDao.createDistinctInventoryItem(distinctInventoryItem);
}
private void assignStartingExp(final Profile profile) {
final var inventoryItem = new InventoryItem();
inventoryItem.setItem(expItem);
inventoryItem.setUser(profile.getUser());
inventoryItem.setPriority(0);
inventoryItem.setQuantity(0);
inventoryItemDao.createInventoryItem(inventoryItem);
}
}
In this example, we have Event Consumers for when the Element is first loaded (only produced once), and when a new Profile is created (produced every time).
Warning
If you use this event: @ElementEventConsumer(ElementLoader.SYSTEM_EVENT_ELEMENT_LOADED) in conjunction with Elements Core services, then you must lazily load the services instead of injecting them, as they are not made available yet when this event fires. Injecting DAO level classes is perfectly fine though. For example:
Element element = ElementSupplier
.getElementLocal(ThisClass.class)
.get();
SomeService someService = element .getServiceLocator()
.getInstance(SomeService.class);

