Note that in the sample code that follows, the facade and listener classes can be the same classes as from our Insert example. We're just looking at different methods. By the same token, if you just have a single Listener class to handle both Insert and Read then you only have to do the Listener registration once. Here's how it all looks in practice. As before, we're assuming that you've already declared a new "classic" entity called MyAdditionalEntity and have extended the façade parameters to take the new details.
Here's the original façade:
... public class MyFacade { @Inject protected MyEntityDAO myEntityDAO; public MyEntityDetails readMyEntity(final MyEntityKey key) throws AppException, InformationalException { MyEntityDetails details = new MyEntityDetails(); MyEntity myEntity = myEntityDAO.get(key.id); getDetails(myEntity, details.dtls); return details; } protected void getDetails(final MyEntity myEntity, final MyEntityDtls dtls) throws AppException, InformationalException { dtls.firstname = myEntity.getFirstname(); dtls.surname = myEntity.getSurname(); } }
Here's our override of the façade:
... public class MyCustomFacade extends curam.custom.facade.impl.MyFacade { @Override public MyEntityDetails readMyEntity(final MyEntityKey key) throws AppException, InformationalException { MyEntityDetails details = new MyEntityDetails(); MyEntity myEntity = myEntityDAO.get(key.id); getDetails(myEntity, details.dtls); /* * Retrieve additional details from entity context */ details.additionalDtls = myEntity.getContextContainer().get( MyAdditionalEntityDtls.class); return details; } }
Here's our listener for reads on the original entity. Note, we're assuming that there will always be a corresponding record on the new entity. Your design may have to cater for the situation where this is not the case.
@Singleton class MyEntityListener extends PersistenceEvent<MyEntity> { /** * After MyEntity is read, also read MyAdditionalEntity. */ @Override public void postRead(final MyEntity e) throws AppException, InformationalException { /* * Read additional details from database */ MyAdditionalEntity additionalEntity = MyAdditionalEntityFactory .newInstance(); MyAdditionalEntityKey key = new MyAdditionalEntityKey(); key.id = e.getID(); MyAdditionalEntityDtls dtls = additionalEntity.read(key); /* * Store additional details in entity context */ e.getContextContainer().put(MyAdditionalEntityDtls.class, dtls); } }
Here's how we register our listener. Note that if you combined the listener from the Insert example and the Read example into a single listener class, you won't need this step. You only register each listener class once:
public class MyModule extends AbstractModule { @Override protected void configure() { /* * Get the listener set */ Multibinder<PersistenceEvent<MyEntity>> myEventListeners = Multibinder.newSetBinder(binder(), new TypeLiteral<PersistenceEvent<MyEntity>>() {/**/}); /* * Add a listener */ myEventListeners.addBinding().to(MyEntityListener.class); } }
In summary, we've created a listener which receives read events for one entity and performs reads on another, supplemental entity. The data from the supplemental entity is piggybacked on "entity context", and is available to a façade method which returns the details to a client.