You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@isis.apache.org by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com> on 2014/12/13 19:08:56 UTC

Default implementations for "Delete Entity" and "Collection Remove" actions

There are a lot of cases where the implementation of those operations is the same, and Isis could avoid to explicitly implement it.

For entities, normally is something like:

public void delete(Entity entity) {
  this.getContainer().remove(entity);
  this.getContainer().flush();
}

Perhaps flush can be optional, perhaps if implemented directly on the entity there shouldn't be any params, but base code remains the same.

If all entities have a common descendant, it can be implemented on a generic service that accepts one instance as a param. But perhaps that "basic" operation could be implemented directly by the framework.

Its deletion could be vetoed by means of the Isis "removing()" method, for example, and also by means of the EventServiceBus.

Perhaps a default implementation on an Isis service could be given?



But there's another case that it's "polluting" our domain entities and we haven't achieve a standard way to implement it, despite I think it's possible.

For nearly each collection, we need:
- an "addXXX" action (that normally accepts one existing instance of the collection elements - i.e., a Price List adding existing Items -).
- sometimes, a "createXXX" action (that create an instance and after that calls addXXX; think of an Aggregated Root creating all contained Entity instances - i.e., an Order creating new Line Items -). 
- a "deleteXXX" action (that mainly consists of a "getCollection.remove(entity)"; if the collection was annotated with dependentElement="true", the instance will removed AND deleted by DataNucleus after executing it).

From those three, createXXX need custom business logic to work and cannot be easily generalized (createXXX needs required fields of the entity created).

But addXXX and deleteXXX, when available, have a quite generic implementation:

@PersistenceCapable
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
@Discriminator(value = "BusinessService")
public class InformationSystem extends ApplicationComponent {

    // {{ UsesSoftwareServices (Collection)
    @Persistent(mappedBy = "usedByInformationSystem", dependentElement = "false")
    private SortedSet<SoftwareService> usesSoftwareServices = new TreeSet<SoftwareService>();

    @MemberOrder(sequence = "710")
    public SortedSet<SoftwareService> getUsesSoftwareServices() {
        return this.usesSoftwareServices;
    }

    public void setUsesSoftwareServices(final SortedSet<SoftwareService> usesSoftwareServices) {
        this.usesSoftwareServices = usesSoftwareServices;
    }

    // }}

    // {{ addSoftwareService (action)
    @ActionSemantics(Of.IDEMPOTENT)
    @MemberOrder(name = "usesSoftwareServices", sequence = "010")
    public void addSoftwareService(@XMSBulkParam @Named("Software Service") final SoftwareService softwareService) {
        this.getUsesSoftwareServices().add(softwareService);
        this.getContainer().flush();
    }

    // }}

    // {{ deleteFromUsesSoftwareServices (action)
    @ActionSemantics(Of.IDEMPOTENT)
    @MemberOrder(name = "usesSoftwareServices", sequence = "020")
    public void deleteFromUsesSoftwareServices(@XMSBulkParam @Named("Servicio de Software") final SoftwareService softwareService) {
        this.getUsesSoftwareServices().remove(softwareService);
        this.getContainer().flush();
    }

    // }}

   ...
}



Couldn't they be provided by default also by Isis?


For example, by annotating the collection with something similar to:

@Collection(addAction="Add Software Service", deleteAction="Remove Software Service")
    
Which would reduced the code to:


@PersistenceCapable
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
@Discriminator(value = "BusinessService")
public class InformationSystem extends ApplicationComponent {

    // {{ UsesSoftwareServices (Collection)
    @Persistent(mappedBy = "usedByInformationSystem", dependentElement = "false")
    private SortedSet<SoftwareService> usesSoftwareServices = new TreeSet<SoftwareService>();

    @Collection(addMethodName="Add Software Service", deleteAction="Remove Software Service")
    @MemberOrder(sequence = "710")
    public SortedSet<SoftwareService> getUsesSoftwareServices() {
        return this.usesSoftwareServices;
    }

    public void setUsesSoftwareServices(final SortedSet<SoftwareService> usesSoftwareServices) {
        this.usesSoftwareServices = usesSoftwareServices;
    }

    // }}

   ...
}



If I remember it well, Martin suggested once something similar for collections.


Perhaps am I missing anything not allowing such generic implementations being supported by Isis ?


Regards,

Oscar









Óscar Bou Bou
Responsable de Producto
Auditor Jefe de Certificación ISO 27001 en BSI
CISA, CRISC, APMG ISO 20000, ITIL-F

   902 900 231 / 620 267 520
   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>

   http://www.GesConsultor.com <http://www.gesconsultor.com/> 




Este mensaje y los ficheros anexos son confidenciales. Los mismos contienen información reservada que no puede ser difundida. Si usted ha recibido este correo por error, tenga la amabilidad de eliminarlo de su sistema y avisar al remitente mediante reenvío a su dirección electrónica; no deberá copiar el mensaje ni divulgar su contenido a ninguna persona.
Su dirección de correo electrónico junto a sus datos personales constan en un fichero titularidad de Gesdatos Software, S.L. cuya finalidad es la de mantener el contacto con Ud. Si quiere saber de qué información disponemos de Ud., modificarla, y en su caso, cancelarla, puede hacerlo enviando un escrito al efecto, acompañado de una fotocopia de su D.N.I. a la siguiente dirección: Gesdatos Software, S.L. , Paseo de la Castellana, 153 bajo - 28046 (Madrid), y Avda. Cortes Valencianas num. 50, 1ºC - 46015 (Valencia). Asimismo, es su responsabilidad comprobar que este mensaje o sus archivos adjuntos no contengan virus informáticos, y en caso que los tuvieran eliminarlos.






Re: Default implementations for "Delete Entity" and "Collection Remove" actions

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
I've raised ISIS-991 [1] and ISIS-992 [2] for these two points.

The first (collections) I agree with, shold be implemented; the second
(delete action) I'm not so sure.

Dan

[1] https://issues.apache.org/jira/browse/ISIS-991
[2] https://issues.apache.org/jira/browse/ISIS-992.

On 13 December 2014 at 18:08, GESCONSULTOR - Óscar Bou <
o.bou@gesconsultor.com> wrote:

> There are a lot of cases where the implementation of those operations is
> the same, and Isis could avoid to explicitly implement it.
>
> For entities, normally is something like:
>
> public void delete(Entity entity) {
>   this.getContainer().remove(entity);
>   this.getContainer().flush();
> }
>
> Perhaps flush can be optional, perhaps if implemented directly on the
> entity there shouldn't be any params, but base code remains the same.
>
> If all entities have a common descendant, it can be implemented on a
> generic service that accepts one instance as a param. But perhaps that
> "basic" operation could be implemented directly by the framework.
>
> Its deletion could be vetoed by means of the Isis "removing()" method, for
> example, and also by means of the EventServiceBus.
>
> Perhaps a default implementation on an Isis service could be given?
>
>
>
> But there's another case that it's "polluting" our domain entities and we
> haven't achieve a standard way to implement it, despite I think it's
> possible.
>
> For nearly each collection, we need:
> - an "addXXX" action (that normally accepts one existing instance of the
> collection elements - i.e., a Price List adding existing Items -).
> - sometimes, a "createXXX" action (that create an instance and after that
> calls addXXX; think of an Aggregated Root creating all contained Entity
> instances - i.e., an Order creating new Line Items -).
> - a "deleteXXX" action (that mainly consists of a
> "getCollection.remove(entity)"; if the collection was annotated with
> dependentElement="true", the instance will removed AND deleted by
> DataNucleus after executing it).
>
> From those three, createXXX need custom business logic to work and cannot
> be easily generalized (createXXX needs required fields of the entity
> created).
>
> But addXXX and deleteXXX, when available, have a quite generic
> implementation:
>
> @PersistenceCapable
> @Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
> @Discriminator(value = "BusinessService")
> public class InformationSystem extends ApplicationComponent {
>
>     // {{ UsesSoftwareServices (Collection)
>     @Persistent(mappedBy = "usedByInformationSystem", dependentElement
> = "false")
>
>   private SortedSet<SoftwareService> usesSoftwareServices = new TreeSet<SoftwareService>();
>
>     @MemberOrder(sequence = "710")
>     public SortedSet<SoftwareService> getUsesSoftwareServices() {
>         return this.usesSoftwareServices;
>     }
>
>     public void setUsesSoftwareServices(final SortedSet<SoftwareService>
> usesSoftwareServices) {
>         this.usesSoftwareServices = usesSoftwareServices;
>     }
>
>     // }}
>
>     // {{ addSoftwareService (action)
>     @ActionSemantics(Of.IDEMPOTENT)
>     @MemberOrder(name = "usesSoftwareServices", sequence = "010")
>     public void addSoftwareService(@XMSBulkParam @Named("Software
> Service") final SoftwareService softwareService) {
>         this.getUsesSoftwareServices().add(softwareService);
>         this.getContainer().flush();
>     }
>
>     // }}
>
>     // {{ deleteFromUsesSoftwareServices (action)
>     @ActionSemantics(Of.IDEMPOTENT)
>     @MemberOrder(name = "usesSoftwareServices", sequence = "020")
>
>   public void deleteFromUsesSoftwareServices(@XMSBulkParam @Named("Servicio
> de Software") final SoftwareService softwareService) {
>         this.getUsesSoftwareServices().remove(softwareService);
>         this.getContainer().flush();
>     }
>
>     // }}
>
>    ...
> }
>
>
>
> Couldn't they be provided by default also by Isis?
>
>
> For example, by annotating the collection with something similar to:
>
> @Collection(addAction="Add Software Service", deleteAction="Remove
> Software Service")
>
>
> Which would reduced the code to:
>
>
> @PersistenceCapable
> @Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
> @Discriminator(value = "BusinessService")
> public class InformationSystem extends ApplicationComponent {
>
>     // {{ UsesSoftwareServices (Collection)
>     @Persistent(mappedBy = "usedByInformationSystem", dependentElement
> = "false")
>
>   private SortedSet<SoftwareService> usesSoftwareServices = new TreeSet<SoftwareService>();
>
>     @Collection(addMethodName="Add Software Service", deleteAction="Remove
> Software Service")
>     @MemberOrder(sequence = "710")
>     public SortedSet<SoftwareService> getUsesSoftwareServices() {
>         return this.usesSoftwareServices;
>     }
>
>     public void setUsesSoftwareServices(final SortedSet<SoftwareService>
> usesSoftwareServices) {
>         this.usesSoftwareServices = usesSoftwareServices;
>     }
>
>     // }}
>
>    ...
> }
>
>
>
> If I remember it well, Martin suggested once something similar for
> collections.
>
>
> Perhaps am I missing anything not allowing such generic implementations
> being supported by Isis ?
>
>
> Regards,
>
> Oscar
>
>
>
>
>
>
>
>
>
> *Óscar Bou Bou*
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
>
>    902 900 231 / 620 267 520
>    http://www.twitter.com/oscarbou
>
>    http://es.linkedin.com/in/oscarbou
>
>    http://www.GesConsultor.com <http://www.gesconsultor.com/>
>
>
>
> Este mensaje y los ficheros anexos son confidenciales. Los mismos
> contienen información reservada que no puede ser difundida. Si usted ha
> recibido este correo por error, tenga la amabilidad de eliminarlo de su
> sistema y avisar al remitente mediante reenvío a su dirección electrónica;
> no deberá copiar el mensaje ni divulgar su contenido a ninguna persona.
> Su dirección de correo electrónico junto a sus datos personales constan en
> un fichero titularidad de Gesdatos Software, S.L. cuya finalidad es la de
> mantener el contacto con Ud. Si quiere saber de qué información disponemos
> de Ud., modificarla, y en su caso, cancelarla, puede hacerlo enviando un
> escrito al efecto, acompañado de una fotocopia de su D.N.I. a la siguiente
> dirección: Gesdatos Software, S.L. , Paseo de la Castellana, 153 bajo -
> 28046 (Madrid), y Avda. Cortes Valencianas num. 50, 1ºC - 46015 (Valencia).
> Asimismo, es su responsabilidad comprobar que este mensaje o sus archivos
> adjuntos no contengan virus informáticos, y en caso que los tuvieran
> eliminarlos.
>
>
>
>
>
>