I've raised ISIS-1282 [1] for this idea. Thx Dan
[1] https://issues.apache.org/jira/browse/ISIS-1282 On 23 December 2015 at 09:01, Óscar Bou - GOVERTIS <[email protected]> wrote: > Hi, Dan. > > I like your proposal to extend the @Action annotation. > > So, for example, for routing to “this” when returning void or null, would > it be annotated with something like ”routeUsing=ThisRouter.class”. > > Perhaps something clearer would be to have a complementary one like > “routeTo=THIS” or similar. > > Cheers, > > Oscar > > > > > > El 22 dic 2015, a las 19:13, Dan Haywood <[email protected]> > escribió: > > > > On 22 December 2015 at 15:19, Óscar Bou - GOVERTIS <[email protected]> > > wrote: > > > >> > >> Hi all. > >> > >> I find the SPI Service really useful for advanced use cases. > >> > >> But in order to have the desired behavior clearly specified on the same > >> class definition, shouldn't be helpful to also have an annotation > >> indicating the desired behavior (like returning this instance)? > >> > >> > > Seems better to provide a lower level SPI service that can work in all > use > > cases, and then use that as a building block for higher level > abstractions > > that might include annotations (or more likely, a new attribute of the > > @Action annotation). > > > > But to start that conversation, we could have a new "strategy" attribute, > > eg: > > > > @Action( > > routeUsing=MyRouter.class // implements some sort of "Router" > > interface, similar to our Specification interface > > ) > > public void whatever(...) { ... } > > > > Cheers > > Dan > > > > > > > > > >> Christmas here also :)) > >> > >> HTH, > >> > >> Oscar > >> > >>> El 22 dic 2015, a las 15:54, Cesar Lugo <[email protected]> > >> escribió: > >>> > >>> Dan, > >>> > >>> I think your proposal is quite good to have a configurable "default" > >> behavior, and having the option to return whatever the developer wants > is > >> quite useful as well. Probably this could evolve to some kind of wizard > (I > >> saw a work in progress in Isis add-ons), or even some integration with > some > >> BPM tool. Just thinking loud here, it's christmas :) . > >>> > >>> Cesar. > >>> > >>> -----Original Message----- > >>> From: Dan Haywood [mailto:[email protected]] > >>> Sent: Tuesday, December 22, 2015 6:02 AM > >>> To: users > >>> Subject: Re: How should we handle void and null results > >>> > >>> There was a related discussion a while back [1], revolving around > >> whether the Wicket viewer should always render the returned object, or > some > >> other object (eg the owning object/aggregate root). I raised a ticket > >> ISIS-666 [2] for this, and have also now referenced this thread [3]. > >>> > >>> To pick up on a couple of points made: > >>> > >>> * should the object returned by the action determine the next object > >> rendered (ie do domain object actions act as "controllers")? Yu Ri says > >> no, whereas in the previous conversation (Oscar, Jeroen, Dan) I think we > >> were always saying its ok, but to provide the ability for this to be > >> modified (eg to the aggregate root rather than leaf). We didn't discuss > >> the case of returning void, though. > >>> > >>> * Martin was wondering about whether Person#delete() even makes sense. > >> I think it does though; at least an end-user would want to press a > button > >> called "delete" on a domain object. Behind the covers that might be a > >> contributed action or mixin or double-dispatch back to a repository > >> service. But that's an implementation detail: the core responsibility > is > >> for a domain object to know how to get itself deleted > >>> > >>> * Steve suggests that where there is no obvious answer to "which object > >> should be shown next", then the home page might be a reasonable > default. I > >> agree, and think we should provide such a capability. > >>> > >>> * Cesar illustrates how to return a parent object, eg for both delete > >> and also for add. > >>> > >>> To me it seems that it's unlikely to be a single policy that will > >> support all use cases. So I propose a new optional SPI service that, if > >> present, the viewer will consult to determine which object to show > next. I > >> see this a quite low-level service and we might use it as a building > block > >> to some higher-level strategy (eg based on new annotations) at a later > date. > >>> > >>> The SPI I suggest is: > >>> > >>> public interface RoutingService { > >>> > >>> public Object route(Object original); > >>> > >>> } > >>> > >>> A default implementation could be something like: > >>> > >>> public class RoutingServiceDefault { > >>> > >>> public Object route(Object original) { > >>> return original != null? original: homePage(); > >>> } > >>> > >>> private Object homePage() { ... code to find the @HomePage object if > >> any ... } } > >>> > >>> This behaviour could be overridden eg to support the aggregate object > >> idea as discussed in [1]. > >>> > >>> So, that's my proposal. > >>> > >>> Cheers > >>> Dan > >>> > >>> > >>> > >>> [1] http://markmail.org/message/xhmeq62ywr2vqvje . > >>> [2] https://issues.apache.org/jira/browse/ISIS-666 > >>> > >>> > >>>> On 21 December 2015 at 14:46, Cesar Lugo <[email protected]> > >> wrote: > >>>> > >>>> Hello. I am just another Isis user like you, but I thought this might > >> help: > >>>> > >>>> Wicket viewer shows what you "return" in your action method, so, > >>>> because you are returning void, Wicket is showing "no results" > >>>> message. Usually, you return the thing you create or update, but you > >>>> can return the parent if that's what you want, or anything else you > >>>> need, just get it in your code and return it. For example, I have a > >>>> method that adds a Deliverer that belongs to a BusinessLocation, and > >>>> after created shows the parent BusinessLocation entity object instead > >>>> of showing the Deliverer object just created (in my case, when showing > >>>> the BusinessLocation parent, the Deliverer just created shows in the > >>>> collection section, which is what I wanted, because Business have that > >>>> collection). If you adapt this code to your deletePerson method I > think > >> it can work. > >>>> > >>>> My sample code is: > >>>> > >>>> @Action( > >>>> domainEvent = CreateDomainEvent.class > >>>> ) > >>>> @MemberOrder(name = "deliverers",sequence = "24") > >>>> public BusinessLocation addDeliverer( > >>>> final @ParameterLayout(named="Business Location") > >>>> BusinessLocation businessLocation, > >>>> final @ParameterLayout(named="Deliverer Id") String > >>>> delivererId, > >>>> final @ParameterLayout(named="First Name") String firstName, > >>>> final @ParameterLayout(named="Middle Name") > >>>> @Parameter(optionality = Optionality.OPTIONAL)String middleName, > >>>> final @ParameterLayout(named="Last Name") String lastName, > >>>> final @ParameterLayout(named="Last Name 2") > >>>> @Parameter(optionality = Optionality.OPTIONAL)String lastName2, > >>>> final @ParameterLayout(named="Contact Phone") > >>>> @Parameter(optionality = Optionality.OPTIONAL)Long contactPhone, > >>>> final @ParameterLayout(named="Delivery Phone") > >>>> @Parameter(optionality = Optionality.OPTIONAL)Long deliveryPhone, > >>>> final @ParameterLayout(named="Deliverer Picture") > >>>> @Parameter(optionality = Optionality.OPTIONAL) Blob delivererPicture > >>>> ) > >>>> { > >>>> final Deliverer obj = > >>>> container.newTransientInstance(Deliverer.class); > >>>> obj.setBusinessLocation(businessLocation); > >>>> obj.setDelivererId(delivererId); > >>>> obj.setFirstName(firstName); > >>>> obj.setMiddleName(middleName); > >>>> obj.setLastName(lastName); > >>>> obj.setLastName2(lastName2); > >>>> obj.setContactPhone(contactPhone); > >>>> obj.setDeliveryPhone(deliveryPhone); > >>>> obj.setDelivererPicture(delivererPicture); > >>>> obj.setCreationTime(clockService.nowAsDateTime()); > >>>> container.persistIfNotAlready(obj); > >>>> return obj.getBusinessLocation(); > >>>> } > >>>> > >>>> If you choose to return the parent of the Person object being deleted, > >>>> make sure you get the parent before you Delete the person. Have fun! > >>>> > >>>> Cesar. > >>>> > >>>> -----Original Message----- > >>>> From: Y.R Tan [mailto:[email protected]] > >>>> Sent: Saturday, December 19, 2015 5:44 AM > >>>> To: users > >>>> Subject: How should we handle void and null results > >>>> > >>>> Hi everyone, > >>>> > >>>> When using a void action, let’s say a remove action, the user is > >>>> redirected to a page "no results". When clicking the back button in > >>>> the browser the user sees "Object not found" (since you’ve just > >>>> deleted this object). > >>>> > >>>> Example: > >>>> > >>>> public class Person { > >>>> .... > >>>> public void remove() { > >>>> ... > >>>> } > >>>> } > >>>> > >>>> You can return a list for example to prevent the user from being > >>>> redirect to a "No results" page, but I think it’s not the > >>>> responsibility of the controllers in the domain model. A solution > >>>> could be that wicket viewer goes back one page when encountering a > >>>> deleted object. And refresh the current page when receiving a null > >> response or invoking a void action. > >>>> > >>>> What do you guys think that is the best solution? Or do you have > >>>> another view on this situation? > >>>> > >>>> Looking forward hearing from you. > >>>> > >>>> Regards, > >>>> > >>>> Yu Ri Tan > >>>> > >>>> > >>>> --- > >>>> This email has been checked for viruses by Avast antivirus software. > >>>> https://www.avast.com/antivirus > >>> > >>> > >>> --- > >>> This email has been checked for viruses by Avast antivirus software. > >>> https://www.avast.com/antivirus > >>> > >> > >
