You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@isis.apache.org by "Dan Haywood (JIRA)" <ji...@apache.org> on 2014/02/27 09:22:22 UTC

[jira] [Updated] (ISIS-493) Annotation to identify domain services/repositories

     [ https://issues.apache.org/jira/browse/ISIS-493?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Dan Haywood updated ISIS-493:
-----------------------------

    Fix Version/s:     (was: core-1.4.0)
                   core-1.5.0

> Annotation to identify domain services/repositories
> ---------------------------------------------------
>
>                 Key: ISIS-493
>                 URL: https://issues.apache.org/jira/browse/ISIS-493
>             Project: Isis
>          Issue Type: New Feature
>          Components: Core
>    Affects Versions: core-1.2.0
>            Reporter: Dan Haywood
>            Assignee: Dan Haywood
>             Fix For: core-1.5.0
>
>         Attachments: PastedGraphic-3.png
>
>
> Introduce a new @DomainService annotation, that can optionally indicate that it is a repository for an entity.
> eg for a service that is a repository:
> @DomainService(repositoryFor=Organization.class)
> public class Organizations { 
>      public List<Organization> findByName(...) { ... }
>      ...
> }
> and for a service that isn't a repository, eg:
> @DomainService
> public class BarcodeScanner {
>      ...
> }
> ~~~~~~~~
> background to this request originally raised by Oscar Bou, :http://markmail.org/thread/7xa2gtcytwvq7ogp
> copied in for convenience:
> We are implementing some BDD tests. And we have the need to always write custom spec transformers (one for each domain entity class) like this one:
> public class ETO  {
>     private ETO() {}
> ...
>    public static class Party extends NullRecognizingTransformer<org.estatio.dom.party.Party> {
>         @Override
>         public org.estatio.dom.party.Party transformNonNull(String id) {
>             try {
>                 return ScenarioExecution.current().getVar("party", id, org.estatio.dom.party.Party.class);
>             } catch(IllegalStateException e) {
>                 return ScenarioExecution.current().service(Parties.class).findPartyByReferenceOrName(id);
>             }
>         }
>     }
> If we had an annotation like "@IsisRepository(org.estatio.dom.party.Party.class)" for annotating the Party's repository, the previous transformer could be "generalized" (previously searching also for a var on the Scenario context with the class name in camelCase).
> Obviously, if none is found it should be mandatory to declare a transformer.
> There could be also other scenarios where could be useful to be able to know what's the repository for a given domain entity class. Sure you can think about more.
> The container (or any other Isis class) could have a method for returning the proper repository for a class.
> What do you think? Could it be useful? Any problems derived from it?
> ~~~~~~~
> Dan's response:
> Hi Oscar,
> yup, I like the idea, I think... though I'd probably use @DomainService
> instead of @IsisRepository.
> Another benefit is that we can use it to automatically locate services so
> that they don't need to be explicitly registered - something that you've
> asked for in the past, IIRC.  A suitable implementation of
> org.apache.isis.core.runtime.services.ServicesInstaller would do the trick,
> I think.
> It might need a few iterations to get exactly correct, however.   A couple
> of questions I have is:
> - is it your intention to generalize the
> "findPartyByReferenceOrName(String)" bit (in the catch block) also?  If so,
> wouldn't that require that DomainService would need to be an interface
> (declaring findById(...)) rather than a simple annotation?
> - I'm not sure about how hierarchies of classes work.  for example, we have
> Parties domain service, for any sort of Party, but also Organisations
> domain service, for Organisation (subtype of Party) and Persons domain
> service (for Person, subtype of Party).  The entities are closely related
> through inheritance, but I don't really have a pattern to explain to myself
> what the relationship should be (if any) between their corresponding domain
> services of Parties, Organisations and Persons.
> Let's exchange a few more mails on this before going ahead and writing some
> new code on it....
> Dan
> ~~~
> Oscar's response:
> Hi, Dan.
> yup, I like the idea, I think... though I'd probably use @DomainService
> instead of @IsisRepository.
> Well, perhaps we need two. But I consider relevant to be able to distinguish
> "Repositories" as defined in DDD from the other kind of Domain Services.
> The @DomainService annotation would mark a service as that.
> But the @IsisRepository(entity=XXXX), @Repository(entity=XXXX), etc. would have
> the additional meaning to be acting as the repository for a specific kind of
> Domain Entities, so the "entity=XXXX" param should be mandatory.
> They should also be considered as Domain Services.
> - is it your intention to generalize the
> "findPartyByReferenceOrName(String)" bit (in the catch block) also?  If so,
> wouldn't that require that DomainService would need to be an interface
> (declaring findById(...)) rather than a simple annotation?
> Yes. In fact, we currently have a generic "findByName", "findByProperty", etc
> methods on a generic abstract repository, implemented with the help of the
> IsisJdoSupport service. We are "multi-tenant", and that allows us to always
> filter by tenant and apply some other business filters. We use those protected
> methods on the domain "finders" defined on each entity's repository.
> As we are sharing the implementation, we chose inheritance, but an interface
> would also do the trick.
> But we consider that an "implementation detail" in addition to the annotation,
> not a replacement.
> - I'm not sure about how hierarchies of classes work.  for example, we have
> Parties domain service, for any sort of Party, but also Organisations
> domain service, for Organisation (subtype of Party) and Persons domain
> service (for Person, subtype of Party).  The entities are closely related
> through inheritance, but I don't really have a pattern to explain to myself
> what the relationship should be (if any) between their corresponding domain
> services of Parties, Organisations and Persons.
> In our case, we have references to "Parties" on other Domain Entities, so we
> need to be able to associate "Parties", in addition to "Organizations" and
> "Persons". So we need to have "finders" for Parties. If that's the case, we need
> the "Party Repository", in addition to the "Organization Repository" and the
> "Person Repository". No need for inheritance between them, unless you have to
> share the implementation of some methods, validations, etc. That was not our
> case. All them inherit from the "abstract base domain repository".
> But what we have needed is the ability to distinguish between "creation" actions
> or "factory methods" (we firstly implemented it by searching for methods defined
> on services and starting with "create", but we changed after to an annotation
> called "@FactoryMethod" - perhaps other names are better, and names are
> important on DDD, we know :-) ) in order to be able to know "how" to create a
> "Party" descendant (on Edit forms and action params we are offering the user the
> option to create a new entity in addition to select from an existing one).



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)