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 <[email protected]>:
> Hi
>
> 2014-04-23 14:16 GMT+02:00 Thomas Andraschko <[email protected]>:
>> 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 <[email protected]>:
>>
>>> Hi
>>>
>>> 2014-04-23 11:54 GMT+02:00 Thomas Andraschko
>>> <[email protected]>:
>>> 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 <[email protected]>:
>>> >
>>> >> 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 <[email protected]>:
>>> >> > +1 To the idea
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> > On 22 April 2014 15:53, Leonardo Uribe <[email protected]> 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
>>> >> >> <[email protected]>:
>>> >> >> > 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 <[email protected]>:
>>> >> >> >
>>> >> >> >> 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
>>> >> >> >
>>> >> >> >
>>> >> >
>>> >> >
>>> >
>>> >
>>
>>

Reply via email to