You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@isis.apache.org by Dan Haywood <da...@haywood-associates.co.uk> on 2013/07/26 12:08:23 UTC

Re: New Isis annotation @IsisRepository

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




On 24 July 2013 20:16, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote:

>
> Hi, Dan.
>
> 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?
>
> Thanks,
>
> Oscar
>
>
>
>
>
>
>
>

Re: New Isis annotation @IsisRepository

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
I've created ISIS-493 [1] for this idea; I think it has merit.  As Oscar
says, there are a bunch of possible follow-ons, eg improved BDD spec
support, or automatic registration of services (rather than in
isis.properties).

There are also some cases where I think we emperically guess which objects
are services (looking for an injectXxx prefix); could remove that as well.

Dan

[1] https://issues.apache.org/jira/browse/ISIS-493


On 31 July 2013 15:57, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote:

>
> 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).
>
>
>
>
>
>
>
>
> El 26/07/2013, a las 12:08, Dan Haywood <da...@haywood-associates.co.uk>
> escribió:
>
> > 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
> >
> >
> >
> >
> > On 24 July 2013 20:16, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com
> >wrote:
> >
> >>
> >> Hi, Dan.
> >>
> >> 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?
> >>
> >> Thanks,
> >>
> >> Oscar
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
>
>

Re: New Isis annotation @IsisRepository

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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).


 





El 26/07/2013, a las 12:08, Dan Haywood <da...@haywood-associates.co.uk> escribió:

> 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
> 
> 
> 
> 
> On 24 July 2013 20:16, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote:
> 
>> 
>> Hi, Dan.
>> 
>> 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?
>> 
>> Thanks,
>> 
>> Oscar
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>>