Hi, sounds good enough for a first prototype -> +1
Regards, Thomas 2014-04-25 15:23 GMT+02:00 Leonardo Uribe <lu4...@gmail.com>: > Hi > > There are different things we would like to include in this module. For > now, let's focus on rethink how "actions" should be processed in JSF. > > To make things easier, let's start with a comparison between f:viewAction > and > a solution that involves a front controller and some actions defines using > annotations in a CDI bean. > > In the first case, the developer defines the action in the page using a > tag: > > SOLUTION 1: > > <f:metadata> > <f:viewParam name="id" value="#{personPage.id}"/> > <f:viewAction action="#{personPage.loadPerson}"/> > </f:metadata> > > The alternative approach to discuss here is use a managed bean that defines > a path that will work as an starting point: > > SOLUTION 2: > > @Named("myBean") > @ActionController > @RequestScoped > public class MyBean > { > @Action("/actions/do/something") > // userId param with automatic converter lookup > public View myAction() > { > return new View("/views/registration/startRegistration.xhtml"); > } > } > > There are multiple differences between both solutions: > > * <f:viewAction> requires a view to be defined, so when the f:viewAction > is > processed, there is a FacesContext, a client window set (if any) and > there > is a view context too. With the annotations there is no associated view, > so it can't be a valid UIViewRoot at that moment. > > * The annotation approach allows navigation without being in a view. With > f:viewAction it is possible to cause a navigation like with a > h:commandButton. > > * f:viewAction still requires a managed bean to handle the action. The > syntax > using annotations is more compact, because requires only the managed > bean. > > * f:viewAction is activated every time the page is loaded by first time > (in practice, every time a GET is processed), but with the annotations > it is necessay to define the conditions under the action is activated. > > I think f:viewAction and the annotation approach are different things, even > if they share some similarities. > > JSF has been always a "page centric" framework. The developer write some > pages, but to define the navigation, the developer has the option of write > some navigation rules or he/she can also use an implicit navigation. > > f:viewAction design fits really well with JSF, as long as you are dealing > with > "view actions". But in some cases, the action doesn't have any relationship > with any view. That's the case where an action defined into a managed bean > has > sense. > > For example, when the user want to verify a condition for all pages inside > a folder. If the condition is not valid, an specified page should be > rendered. > Some solutions for that problem are: > > 1. Create a filter and handle the logic there > 2. Create a ViewHandler wrapper, override createView(...) and handle the > logic > there. > > But it would be nice to have something like this: > > @Named("myBean") > @ActionController > @RequestScoped > public class CheckUserBean > { > @Priority(Priorities.USER) > @Action("/registration/*") > // userId param with automatic converter lookup > public View myAction() > { > if (the current flow is not active) > { > return new Navigation("registration"); > } > // Otherwise continue to the expected page > return null; > } > } > > In this case we have an action that is executed based on a pattern, in a > specified moment, for a set of pages, and that could cause a navigation > to another page or could not affect the navigation and JSF lifecycle takes > place as usual. > > The other kind of action proposed: > > @Action("/actions/do/something") > // userId param with automatic converter lookup > public View myAction() > { > return new View("/views/registration/startRegistration.xhtml"); > } > > It can be something like this too: > > @Action("/actions/do/something") > // userId param with automatic converter lookup > public void myAction() > { > FacesContext facesContext = FacesContext.getCurrentInstance(); > > /* ... generate text, pdf, xml or whatever ...*/ > > facesContext.responseComplete(); > } > > the responseComplete() cause the lifecycle to be skipped. > > I think these ideas does not overlap or replace the utility of > f:viewAction, > and instead the aim is solve a different problem. I'll try to make a > prototype with the ideas exposed here. I have some more ideas for the other > requeriments we have, but for now the idea is focus on what looks more > important or useful. > > Suggestions are welcome. > > regards, > > Leonardo > > 2014-04-23 15:45 GMT+02:00 Leonardo Uribe <lu4...@gmail.com>: > > Hi > > > > 2014-04-23 14:16 GMT+02:00 Thomas Andraschko < > andraschko.tho...@gmail.com>: > >> LU>> 4) Allow action rendering in in a normal lifecycle: > >> LU>> > >> LU>> <ui:renderAction action="#{myBrean.myAction( > >> LU>bean.value, 1)}" /> > >> LU>> > >> LU> > >> LU>Could you please describe better this case? So you execute the > action, > >> LU> but the lifecycle goes on as usual? > > > > > > TA> It's just a component, which renders the returned html string from > the > > TA> action into the ResponseWriter. > > TA> Something like a include for the action return value. > > TA> > > TA> > > TA> This would be also helpful if we combine facelet rendering + actions. > > TA> In ASP.NET MVC, the action could also return a View/PartialView: > > TA> > > TA> > > TA>> @Named("myBean") > > TA>> @RequestScoped > > TA>> public class MyBean { > > TA>> @Action > > TA>> // userId param with automatic converter lookup > > TA>> public PartialView myAction(String myUrlParam, User > userId) { > > TA>> return new > > TA>> PartialView("/META-INF/mylib/myincludes/myfile.xhtml"); > > TA>> } > > TA>> } > > TA> > > TA> It would load the xhtml, renders the xhtml and return the rendered > html > > TA> string - called via ui:renderAction or via URL. > > TA> > > > > So you mean use JSF as a template engine to render some html fragments. > > I think it can be done. > > > > This feature is something controversial, because it could be used > wrongly. > > For example, you have a page fragment and you want to update it using > > this stuff and some javascript. Since you are bypassing JSF, the results > > can be unexpected, because JSF is no longer in control of the view state > > anymore. The right way is affect the component state (or the model > state), > > so when it is rendered it gets updated. The best way to do it, is with > ajax, > > because ajax knows about the relationship between different components. > > > > Also, you could have situations when the ids are not correctly generated, > > and at the end have duplicate ids. Again, the solution is add or remove > the > > component from the component tree programmatically, so JSF can have > > the change to deal with this problem properly. > > > > More than a PartialView, I think in this case JSF is used as a raw html > or > > xml generator. For example, the html in this case could be a formatted > > message and so on. > > > > I think it is better if we avoid the term "PartialView" and instead we > provide > > something more abstract like "Response" or "MarkupFragment" or > > something like that. Something that indicates that this is not part of > the > > view itself, and instead is part of the "client state". > > > >> > >> > >> I think we could also completely rebuild the GET functionality for > actions. > >> Maybe could just render the startRegistration.xhtml via a normal JSF > >> lifecycle after the action call. > >> > >>> @Named("myBean") > >>> @RequestScoped > >>> public class MyBean { > >>> @Action(mapping = "/actions/do/something") > >> > >>> // userId param with automatic converter lookup > >>> public View myAction() { > >>> return new > >>> View("/views/registration/startRegistration.xhtml"); > >>> } > >>> } > >> > > > > It can be done. In fact, it works like a url rewriting. Maybe it is more > > straighforward for users after all, because with f:viewAction, you can't > > control the page, but with this, you can add some logic before the > > final page is processed, like for example a conditional and so on. > > > >> Just some ideas for a more complete add-on. > >> That would cover the "view" and "controller". The "model" are actually > the > >> beans via EL. > >> > >> Don't know if it really fits JSF or if there are better concepts - but > that > >> are almost all core features of ASP.NET MVC. > >> > >> > > > > I think what we are doing here instead is take the best we found from the > > things we know that works. The challenge is integrate in a coherent way. > > > > For example, JSF as a component oriented framework has the concept > > of clientIds associated with components. This is very helpful when you > > move code from one place to another, because the generated ids on > > the client side are updated properly. In an action oriented framework, > that's > > a complete mess. The idea is preserve the JSF abstraction, that means > > components that can be assembled in a hierarchical way, and that also > > means this tree has a similar structure on the client. > > > > We can find workarounds. For example, bind the html generation to > > a component, so we say "... generate an html fragment, but keep in mind > > that chunk will be used in this component or a component with this > > client id ..." So, the fragment is encapsulated in a jsf component that > > implements NamingContainer and generates the specified clientId. > > That could work. But I suppose it should be MyFaces Core implementation > > specific, because we need to indicate to facelets the way how the ids > > should be generated. > > > > regards, > > > > Leonardo Uribe > > > >> > >> 2014-04-23 13:40 GMT+02:00 Leonardo Uribe <lu4...@gmail.com>: > >> > >>> Hi > >>> > >>> 2014-04-23 11:54 GMT+02:00 Thomas Andraschko > >>> <andraschko.tho...@gmail.com>: > >>> TA> Hi, > >>> TA> > >>> TA> the most important question for me is actually: > >>> TA> > >>> TA> 1) How much should we really mix actions with facelets rendering? > >>> TA> > >>> TA> There are soooo many things to consider. As you already said in > your > >>> specs > >>> TA> post: viewstate, windowid, viewscoped, .... > >>> TA> > >>> > >>> I think the best way to deal with facelets rendering is use the > standard > >>> ajax. > >>> I know in an action source framework people have to do the ajax stuff > >>> "by hand", which means use the template framework to calculate a > fragment > >>> of the response. That's a step back. > >>> > >>> Instead, this is for the case when you have a page in the client and > you > >>> need > >>> to communicate with the server to get some information, but the page > >>> structure > >>> does not change. For example, an autocomplete component or a datatable > >>> component. In that case, you only need the data usually in json format, > >>> and > >>> there is a javascript already in place to deal with that data and > change > >>> the > >>> state of the client. > >>> > >>> The point is deal with the context in general. So if you send a POST > from > >>> the > >>> client, and you provide the windowid and the viewstate token, it > should be > >>> processed, and the response should update the viewstate if necessary. > >>> That's why we need some javascript on the client to wire things up. > >>> > >>> It could be possible a complex case, where we need a json response but > >>> the response triggers an ajax update from the server. It can be done, > with > >>> some javascript code. > >>> > >>> > > >>> > For me the most important things are actually: > >>> > > >>> > 1) possibility to use a normal JSF lifecycle for the first GET > request > >>> > >>> I agree with you, because in the first request you are just building > the > >>> view, > >>> no special things there. > >>> > >>> > 2) allow action handling and custom response for POST actions > >>> > >>> Yes. > >>> > >>> > 3) normal action handling like in asp.net MVC + a EL util function > to > >>> > generate the action URL > >>> > > >>> > $('#input').autocomplete({ > >>> > source: "#{action('myBean', 'myAction', params...)}" > >>> > }); > >>> > > >>> > @Named("myBean") > >>> > @RequestScoped > >>> > public class MyBean { > >>> > @Action > >>> > // userId param with automatic converter lookup > >>> > public String myAction(String myUrlParam, User userId) { > >>> > return response; > >>> > } > >>> > } > >>> > > >>> > >>> > >>> Yes, that's one good point. I have seen too. It could be good to have > >>> an EL function that renders the endpoint url automatically. In this > case, > >>> you don't really care how the endpoind url is generated, as long as > >>> when the javascript on the client side invokes the url you get the > >>> pointed method executed. > >>> > >>> You could also want to bind the url to the component itself. The case > is > >>> you are writing a composite component and the component requires > >>> the url, so you annotate a method in the base component class to > >>> deal with this. In the GET case you don't have the view state, so the > >>> component state is not restored, but in the POST case you can > >>> submit the view state (for example calling a defined javascript > function) > >>> and the code will execute an invokeOnComponent call on the server. > >>> > >>> > 4) Allow action rendering in in a normal lifecycle: > >>> > > >>> > <ui:renderAction action="#{myBrean.myAction(bean.value, 1)}" /> > >>> > > >>> > >>> Could you please describe better this case? So you execute the action, > >>> but the lifecycle goes on as usual? > >>> > >>> > 5) Action + facelets rendering -> question 1 > >>> > Currently no idea how a integration should look like. > >>> > > >>> > > >>> > >>> I still don't have clear this point, but I can imagine you can return > >>> XML from the server and parse it on the client somehow. Obviously > >>> we need to find out how to do it. > >>> > >>> regards, > >>> > >>> Leonardo Uribe > >>> > >>> > >>> > >>> > > >>> > > >>> > 2014-04-22 18:24 GMT+02:00 Leonardo Uribe <lu4...@gmail.com>: > >>> > > >>> >> Hi > >>> >> > >>> >> In few word, the difficulty in this stuff is the context. If you > take a > >>> >> look > >>> >> at the example proposed: > >>> >> > >>> >> @Named("myBean") > >>> >> @RequestScoped > >>> >> public class MyBean implements Serializable { > >>> >> > >>> >> @RequestMapping(value = "/form1b.xhtml") > >>> >> public String form1() { > >>> >> String inputText1 = (String) > FacesContext.getCurrentInstance(). > >>> >> > >>> >> getExternalContext().getRequestParameterMap().get("inputText1"); > >>> >> setValue("We set inputText1 manually to - " + inputText1); > >>> >> return "/form1b.xhtml"; > >>> >> } > >>> >> > >>> >> } > >>> >> > >>> >> To call the method you need to restore the context first of the > parent > >>> >> bean and also there is a call to FacesContext.getCurrentInstance(), > >>> >> so at that point it should be a valid FacesContext instance. > >>> >> > >>> >> In JSF 2.2 the lifecycle has 3 methods: > >>> >> > >>> >> //JSF 2.2: attach window > >>> >> _lifecycle.attachWindow(facesContext); > >>> >> // If this returns false, handle as follows: > >>> >> // call > >>> >> Lifecycle.execute(javax.faces.context.FacesContext) > >>> >> _lifecycle.execute(facesContext); > >>> >> // followed by > >>> >> Lifecycle.render(javax.faces.context.FacesContext). > >>> >> _lifecycle.render(facesContext); > >>> >> > >>> >> The idea is create a LifecycleWrapper that on lifecycle.execute() > >>> >> implements a front controller pattern, doing the necessary steps to > >>> >> get the bean from the underlying CDI container and call the method. > >>> >> If no method is called, continue as usual. > >>> >> > >>> >> The idea is not replicate all the features that an action source > >>> >> framework > >>> >> provides, just the important ones to deal with the cases we have > found > >>> >> where this can be useful for JSF, or try to reutilize what's already > >>> >> available in JSF. It will take some time to get it out, but I think > if > >>> >> we can solve the use cases proposed, the final result will be > something > >>> >> valuable. > >>> >> > >>> >> regards, > >>> >> > >>> >> Leonardo > >>> >> > >>> >> 2014-04-22 16:03 GMT+02:00 Karl Kildén <karl.kil...@gmail.com>: > >>> >> > +1 To the idea > >>> >> > > >>> >> > > >>> >> > > >>> >> > > >>> >> > On 22 April 2014 15:53, Leonardo Uribe <lu4...@gmail.com> wrote: > >>> >> >> > >>> >> >> Hi Thomas > >>> >> >> > >>> >> >> Yes, the idea is do something similar. The only thing we need to > >>> >> >> find > >>> >> >> out is how to do it in a way that fits better with JSF. > >>> >> >> > >>> >> >> There are different people interested in this: > >>> >> >> > >>> >> >> - Some people wants to use JSF as a template engine, because > >>> >> >> Facelets with JSF 2 Resource Handling and JSF 2.2 Resource > Library > >>> >> >> Contracts can be an effective solution for server side > templating. > >>> >> >> > >>> >> >> - Some people want to use a JSF component library but they need > to > >>> >> >> fill some gaps, like for example create a custom component and on > >>> >> >> the way they need to create a JSON endpoint. An mixed JSF-MVC > >>> >> >> approach can be an effective solution. > >>> >> >> > >>> >> >> I think the mentioned example is just half of the solution. > That's > >>> >> >> the reason why I'm gathering the use cases where this can be > >>> >> >> useful. The plan is write a prototype and discuss it, to see how > far > >>> >> >> can we go with this. > >>> >> >> > >>> >> >> regards, > >>> >> >> > >>> >> >> Leonardo > >>> >> >> > >>> >> >> 2014-04-22 15:21 GMT+02:00 Thomas Andraschko > >>> >> >> <andraschko.tho...@gmail.com>: > >>> >> >> > Hi Leo, > >>> >> >> > > >>> >> >> > +1 for the idea. > >>> >> >> > Would it be similiar to: > >>> >> >> > > >>> >> >> > > >>> >> >> > > >>> >> >> > > https://weblogs.java.net/blog/mriem/archive/2014/01/13/jsf-tip-56-using-action-based-prototype-mojarra > >>> >> >> > ? > >>> >> >> > > >>> >> >> > Regards, > >>> >> >> > Thomas > >>> >> >> > > >>> >> >> > > >>> >> >> > 2014-04-22 15:13 GMT+02:00 Leonardo Uribe <lu4...@gmail.com>: > >>> >> >> > > >>> >> >> >> Hi > >>> >> >> >> > >>> >> >> >> Over the time, with the new javascript libraries out there > that > >>> >> >> >> makes > >>> >> >> >> easier to make reliable code on the client side, there are > more > >>> >> >> >> and > >>> >> >> >> more people interested in an approach that can take advantage > of > >>> >> >> >> the good parts that JSF 2.2 already has, but without get into > the > >>> >> >> >> JSF > >>> >> >> >> lifecycle complexities. It could be good if we provide a new > >>> >> >> >> module > >>> >> >> >> inside MyFaces Commons that allow to do things like in Spring > MVC > >>> >> >> >> or > >>> >> >> >> JAX-RS but also integrated with JSF. > >>> >> >> >> > >>> >> >> >> For example: > >>> >> >> >> > >>> >> >> >> - Create a JSON response from a managed bean and bind it to a > >>> >> >> >> component > >>> >> >> >> using javascript. > >>> >> >> >> - Define REST endpoints into CDI beans. > >>> >> >> >> - Provide javascript functions that can invoke a JSF POST or a > >>> >> >> >> GET. > >>> >> >> >> ... > >>> >> >> >> > >>> >> >> >> I have sended already an email to the EG list related to this > >>> >> >> >> stuff, > >>> >> >> >> indicating some use cases where this can be useful. See: > >>> >> >> >> > >>> >> >> >> > >>> >> >> >> > >>> >> >> >> > >>> >> >> >> > >>> >> >> >> > https://java.net/projects/javaserverfaces-spec-public/lists/users/archive/2014-04/message/5 > >>> >> >> >> > >>> >> >> >> CASE 1: Autocomplete component > >>> >> >> >> CASE 2: Captcha component > >>> >> >> >> CASE 3: Excel/PDF/Text/CSV export > >>> >> >> >> CASE 4: REST > >>> >> >> >> CASE 5: Websockets > >>> >> >> >> > >>> >> >> >> The idea is create two things: > >>> >> >> >> > >>> >> >> >> - An extension from the JSF lifecycle. > >>> >> >> >> - A javascript library that can be called from the client > side to > >>> >> >> >> invoke > >>> >> >> >> JSF on the server. > >>> >> >> >> > >>> >> >> >> The final result will look similar to an action source > framework, > >>> >> >> >> some annotations that can be parsed to define a controller > >>> >> >> >> algorithm, > >>> >> >> >> use JSF as template framework and CDI as the model. > >>> >> >> >> > >>> >> >> >> In these moments I'm trying to imagine what can we do in this > >>> >> >> >> case, > >>> >> >> >> so > >>> >> >> >> any suggestion or comment about what people feel missing and > in > >>> >> >> >> that > >>> >> >> >> sense needs to be done is most welcome. > >>> >> >> >> > >>> >> >> >> regards, > >>> >> >> >> > >>> >> >> >> Leonardo Uribe > >>> >> >> > > >>> >> >> > > >>> >> > > >>> >> > > >>> > > >>> > > >> > >> >