diff --git a/documentation/manual/events.textile b/documentation/manual/events.textile new file mode 100644 index 0000000000..5ff58556b2 --- /dev/null +++ b/documentation/manual/events.textile @@ -0,0 +1,56 @@ +Events are a way for plugins to receive notifications from the framework or other plugins. + +The API to send events is pretty straightforward: an event is a `string` and an `Object` (the context). + +bc.. import play.PlayPlugin; + +... +PlayPlugin.postEvent("something happens", this); + +p. Plugins can listen to these events in the the @onEvent@ method: + +bc.. public class My Plugin extends PlayPlugin { + + @Override + public void onEvent(String message, Object context) { + ... + } + + +h2. Available events + +At the moment the following events are sent by Play framework. + +Events go in pair signaling the beginning and the end of a framework operation. + +Usually the context provided to the before and after events is the same except for JPQL category. +In this case, the before event gives the entity name while the after give the JPQL instance. + + +| Class | Method | Event | Context | +| Controller | renderTemplate | template.render.before | @string@: the template name | +| | | template.render.after | idem | +| JPABase | _save | JPASupport.objectSaving | @JPABase@: the object | +| | | JPASupport.objectPersisting| idem | +| | | JPASupport.objectPersisted | idem | +| | | JPASupport.objectSaved | idem | +| | _delete | JPASupport.objectDeleting | idem | +| | | JPASupport.objectDeleted | idem | +| JPQL | count | JPQL.count.before | @string@: the entity name | +| | | JPQL.count.after | @JPQL@: the object | +| | findAll | JPQL.findAll.before | idem | +| | | JPQL.findAll.after | idem | +| | findBy | JPQL.findBy.before | idem | +| | | JPQL.findBy.after | idem | +| | find | JPQL.find.before | idem | +| | | JPQL.find.after | idem | +| | all | JPQL.all.before | idem | +| | | JPQL.all.after | idem | +| | delete | JPQL.delete.before | idem | +| | | JPQL.delete.after | idem | +| | deleteAll | JPQL.deleteAll.before | idem | +| | | JPQL.deleteAll.after | idem | +| | findOneBy | JPQL.findOneBy.before | idem | +| | | JPQL.findOneBy.after | idem | +| | create | JPQL.create.before | idem | +| | | JPQL.create.after | | diff --git a/framework/src/play/db/jpa/JPABase.java b/framework/src/play/db/jpa/JPABase.java index a395931cd6..04fc7c9cf7 100644 --- a/framework/src/play/db/jpa/JPABase.java +++ b/framework/src/play/db/jpa/JPABase.java @@ -30,31 +30,42 @@ public class JPABase implements Serializable, play.db.Model { public void _save() { + boolean saving = false ; String dbName = JPA.getDBName(this.getClass()); if (!em(dbName).contains(this)) { + saving = true ; + PlayPlugin.postEvent("JPASupport.objectSaving", this); + PlayPlugin.postEvent("JPASupport.objectPersisting", this); em(dbName).persist(this); PlayPlugin.postEvent("JPASupport.objectPersisted", this); } - avoidCascadeSaveLoops.set(new HashSet()); - try { - saveAndCascade(true); - } finally { - avoidCascadeSaveLoops.get().clear(); - } - try { - em(dbName).flush(); - } catch (PersistenceException e) { - if (e.getCause() instanceof GenericJDBCException) { - throw new PersistenceException(((GenericJDBCException) e.getCause()).getSQL(), e); - } else { - throw e; - } - } - avoidCascadeSaveLoops.set(new HashSet()); - try { - saveAndCascade(false); - } finally { - avoidCascadeSaveLoops.get().clear(); + try{ + avoidCascadeSaveLoops.set(new HashSet()); + try { + saveAndCascade(true); + } finally { + avoidCascadeSaveLoops.get().clear(); + } + try { + em(dbName).flush(); + } catch (PersistenceException e) { + if (e.getCause() instanceof GenericJDBCException) { + throw new PersistenceException(((GenericJDBCException) e.getCause()).getSQL(), e); + } else { + throw e; + } + } + avoidCascadeSaveLoops.set(new HashSet()); + try { + saveAndCascade(false); + } finally { + avoidCascadeSaveLoops.get().clear(); + } + } + finally + { + if( saving ) + PlayPlugin.postEvent("JPASupport.objectSaved", this); } } @@ -62,6 +73,7 @@ public void _delete() { String dbName = JPA.getDBName(this.getClass()); try { + PlayPlugin.postEvent("JPASupport.objectDeleting", this); avoidCascadeSaveLoops.set(new HashSet()); try { saveAndCascade(true); @@ -83,13 +95,14 @@ public void _delete() { saveAndCascade(false); } finally { avoidCascadeSaveLoops.get().clear(); - } - PlayPlugin.postEvent("JPASupport.objectDeleted", this); + } } catch (PersistenceException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e); - } + } finally { + PlayPlugin.postEvent("JPASupport.objectDeleted", this); + } } public Object _key() { @@ -106,9 +119,6 @@ private void saveAndCascade(boolean willBeSaved) { return; } else { avoidCascadeSaveLoops.get().add(this); - if (willBeSaved) { - PlayPlugin.postEvent("JPASupport.objectUpdated", this); - } } // Cascade save try { diff --git a/framework/src/play/db/jpa/JPQL.java b/framework/src/play/db/jpa/JPQL.java index f69203e220..abf7cb31ad 100644 --- a/framework/src/play/db/jpa/JPQL.java +++ b/framework/src/play/db/jpa/JPQL.java @@ -7,6 +7,7 @@ import javax.persistence.Query; import play.Play; +import play.PlayPlugin; import play.data.binding.ParamNode; import play.data.binding.RootParamNode; import play.db.Configuration; @@ -28,7 +29,10 @@ public long count(String entity) { } public long count(String dbName, String entity) { - return Long.parseLong(em(dbName).createQuery("select count(*) from " + entity + " e").getSingleResult().toString()); + PlayPlugin.postEvent("JPQL.count.before", entity); + long result = Long.parseLong(em(dbName).createQuery("select count(*) from " + entity + " e").getSingleResult().toString()); + PlayPlugin.postEvent("JPQL.count.after", this); + return result ; } public long count(String entity, String query, Object[] params) { @@ -36,9 +40,12 @@ public long count(String entity, String query, Object[] params) { } public long count(String dbName, String entity, String query, Object[] params) { - return Long.parseLong( + PlayPlugin.postEvent("JPQL.count.before", entity); + long result = Long.parseLong( bindParameters(em(dbName).createQuery( createCountQuery(dbName, entity, entity, query, params)), params).getSingleResult().toString()); + PlayPlugin.postEvent("JPQL.count.after", this); + return result ; } public List findAll(String entity) { @@ -46,7 +53,10 @@ public List findAll(String entity) { } public List findAll(String dbName, String entity) { - return em(dbName).createQuery("select e from " + entity + " e").getResultList(); + PlayPlugin.postEvent("JPQL.findAll.before", entity); + List result = em(dbName).createQuery("select e from " + entity + " e").getResultList(); + PlayPlugin.postEvent("JPQL.findAll.after", this); + return result ; } public JPABase findById(String entity, Object id) throws Exception { @@ -62,9 +72,12 @@ public List findBy(String entity, String query, Object[] params) { } public List findBy(String dbName, String entity, String query, Object[] params) { + PlayPlugin.postEvent("JPQL.findBy.before", entity); Query q = em(dbName).createQuery( createFindByQuery(dbName, entity, entity, query, params)); - return bindParameters(q, params).getResultList(); + List result = bindParameters(q, params).getResultList(); + PlayPlugin.postEvent("JPQL.findBy.after", this); + return result ; } public JPAQuery find(String entity, String query, Object[] params) { @@ -73,10 +86,13 @@ public JPAQuery find(String entity, String query, Object[] params) { public JPAQuery find(String dbName, String entity, String query, Object[] params) { + PlayPlugin.postEvent("JPQL.find.before", entity); Query q = em(dbName).createQuery( createFindByQuery(dbName, entity, entity, query, params)); - return new JPAQuery( + JPAQuery result = new JPAQuery( createFindByQuery(dbName, entity, entity, query, params), bindParameters(q, params)); + PlayPlugin.postEvent("JPQL.find.after", this); + return result ; } public JPAQuery find(String entity) { @@ -84,10 +100,13 @@ public JPAQuery find(String entity) { } public JPAQuery find(String dbName, String entity) { + PlayPlugin.postEvent("JPQL.find.before", entity); Query q = em(dbName).createQuery( createFindByQuery(dbName, entity, entity, null)); - return new JPAQuery( + JPAQuery result = new JPAQuery( createFindByQuery(dbName, entity, entity, null), bindParameters(q)); + PlayPlugin.postEvent("JPQL.find.after", this); + return result ; } public JPAQuery all(String entity) { @@ -95,16 +114,22 @@ public JPAQuery all(String entity) { } public JPAQuery all(String dbName, String entity) { + PlayPlugin.postEvent("JPQL.all.before", entity); Query q = em(dbName).createQuery( createFindByQuery(dbName, entity, entity, null)); - return new JPAQuery( + JPAQuery result = new JPAQuery( createFindByQuery(dbName, entity, entity, null), bindParameters(q)); + PlayPlugin.postEvent("JPQL.all.after", this); + return result ; } public int delete(String dbName, String entity, String query, Object[] params) { + PlayPlugin.postEvent("JPQL.delete.before", entity); Query q = em(dbName).createQuery( createDeleteQuery(entity, entity, query, params)); - return bindParameters(q, params).executeUpdate(); + int result = bindParameters(q, params).executeUpdate(); + PlayPlugin.postEvent("JPQL.delete.after", this); + return result ; } public int delete(String entity, String query, Object[] params) { @@ -113,9 +138,12 @@ public int delete(String entity, String query, Object[] params) { public int deleteAll(String dbName, String entity) { + PlayPlugin.postEvent("JPQL.deleteAll.before", entity); Query q = em(dbName).createQuery( createDeleteQuery(entity, entity, null)); - return bindParameters(q).executeUpdate(); + int result = bindParameters(q).executeUpdate(); + PlayPlugin.postEvent("JPQL.deleteAll.after", this); + return result ; } public int deleteAll(String entity) { @@ -123,13 +151,16 @@ public int deleteAll(String entity) { } public JPABase findOneBy(String dbName, String entity, String query, Object[] params) { + PlayPlugin.postEvent("JPQL.findOneBy.before", entity); Query q = em(dbName).createQuery( createFindByQuery(dbName, entity, entity, query, params)); List results = bindParameters(q, params).getResultList(); - if (results.size() == 0) { - return null; - } - return (JPABase) results.get(0); + JPABase result = null ; + if (results.size() != 0) { + result = (JPABase) results.get(0); + } + PlayPlugin.postEvent("JPQL.findOneBy.after", this); + return result ; } public JPABase findOneBy(String entity, String query, Object[] params) { @@ -141,11 +172,14 @@ public JPABase create(String entity, String name, Params params) throws Exceptio } public JPABase create(String dbName, String entity, String name, Params params) throws Exception { + PlayPlugin.postEvent("JPQL.create.before", entity); Object o = Play.classloader.loadClass(entity).newInstance(); RootParamNode rootParamNode = ParamNode.convert(params.all()); - return ((GenericModel) o).edit(rootParamNode, name); + JPABase result = ((GenericModel) o).edit(rootParamNode, name); + PlayPlugin.postEvent("JPQL.create.after", this); + return result ; } public String createFindByQuery(String dbName, String entityName, String entityClass, String query, Object... params) { diff --git a/framework/src/play/mvc/Controller.java b/framework/src/play/mvc/Controller.java index e2e7f3c81f..3f6ce45565 100644 --- a/framework/src/play/mvc/Controller.java +++ b/framework/src/play/mvc/Controller.java @@ -17,6 +17,7 @@ import play.Invoker.Suspend; import play.Logger; import play.Play; +import play.PlayPlugin; import play.classloading.ApplicationClasses.ApplicationClass; import play.classloading.enhancers.ContinuationEnhancer; import play.classloading.enhancers.ControllersEnhancer.ControllerInstrumentation; @@ -663,30 +664,39 @@ protected static void renderTemplate(String templateName, Object... args) { * @param args The template data. */ protected static void renderTemplate(String templateName, Map args) { - // Template datas - Scope.RenderArgs templateBinding = Scope.RenderArgs.current(); - templateBinding.data.putAll(args); - templateBinding.put("session", Scope.Session.current()); - templateBinding.put("request", Http.Request.current()); - templateBinding.put("flash", Scope.Flash.current()); - templateBinding.put("params", Scope.Params.current()); - templateBinding.put("errors", Validation.errors()); - try { - Template template = TemplateLoader.load(template(templateName)); - throw new RenderTemplate(template, templateBinding.data); - } catch (TemplateNotFoundException ex) { - if (ex.isSourceAvailable()) { - throw ex; - } - StackTraceElement element = PlayException.getInterestingStackTraceElement(ex); - if (element != null) { - ApplicationClass applicationClass = Play.classes.getApplicationClass(element.getClassName()); - if (applicationClass != null) { - throw new TemplateNotFoundException(templateName, applicationClass, element.getLineNumber()); - } - } - throw ex; - } + PlayPlugin.postEvent("template.render.before", templateName); + Template template = null ; + try + { + // Template datas + Scope.RenderArgs templateBinding = Scope.RenderArgs.current(); + templateBinding.data.putAll(args); + templateBinding.put("session", Scope.Session.current()); + templateBinding.put("request", Http.Request.current()); + templateBinding.put("flash", Scope.Flash.current()); + templateBinding.put("params", Scope.Params.current()); + templateBinding.put("errors", Validation.errors()); + try { + template = TemplateLoader.load(template(templateName)); + throw new RenderTemplate(template, templateBinding.data); + } catch (TemplateNotFoundException ex) { + if (ex.isSourceAvailable()) { + throw ex; + } + StackTraceElement element = PlayException.getInterestingStackTraceElement(ex); + if (element != null) { + ApplicationClass applicationClass = Play.classes.getApplicationClass(element.getClassName()); + if (applicationClass != null) { + throw new TemplateNotFoundException(templateName, applicationClass, element.getLineNumber()); + } + } + throw ex; + } + } + finally + { + PlayPlugin.postEvent("template.render.after", template); + } } /**