myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leonardo Uribe <lu4...@gmail.com>
Subject Re: [proposal] A new module for improved JSF-MVC inside MyFaces Project
Date Wed, 23 Apr 2014 13:45:18 GMT
Hi

2014-04-23 14:16 GMT+02:00 Thomas Andraschko <andraschko.thomas@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 <lu4242@gmail.com>:
>
>> Hi
>>
>> 2014-04-23 11:54 GMT+02:00 Thomas Andraschko
>> <andraschko.thomas@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 <lu4242@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.kilden@gmail.com>:
>> >> > +1 To the idea
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > On 22 April 2014 15:53, Leonardo Uribe <lu4242@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.thomas@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 <lu4242@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
>> >> >> >
>> >> >> >
>> >> >
>> >> >
>> >
>> >
>
>

Mime
View raw message