jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: [jsr372-experts mirror] Shared State between different JSF applications

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Thu, 8 Dec 2016 00:59:14 -0500

Hi

Tough question, because it involves a lot of design considerations.

I think the limitation here is the relationship between the component tree
and the view state management. A component tree generates html markup which
contains an associated a view state token.

JSF doesn't deal with session object, but it handles the view state.

One view state --> One component tree --> One lifecycle

If you have multiple JSF apps composing a web page you should have the same
view states and the page should execute the same ammount of lifecycles over
different applications.

So, the key aspect to keep in mind is how to update the view state and
embed
in the html markup.

The problem is JSF actually encodes the view state at render response phase,
and there is a cooperation between the ViewHandler and the StateManager that
is not easy to override.

As you know there are two state saving modes: "server" and "client". In
MyFaces "server" mode uses a token that can be generated at any time and
then
when the view state is rendered, the token is passed, but at the end of the
request FaceletViewDeclarationLanguage.render(...) calls
StateManager.saveView(...). But in "client" mode, a buffer is created and
a marker is written "<!--@@JSF_FORM_STATE_MARKER@@-->" so
the response is not flushed until this marker is replaced with the final
view state.

In MyFaces there is an class called
org.apache.myfaces.application.StateCache
that encapsulates the view state storage logic. This object is used
internally
by org.apache.myfaces.renderkit.html.HtmlResponseStateManager, but note this
is an implementation detail not covered by the spec.

So, an override of the default ResponseStateManager is not enough, because
there is a colaboration between the default ViewHandler and the VDL that is
not in the spec (and it should be there).

I ignore what's inside Mojarra, but I suppose it should be something
similar.

About your proposal, a combination between an ExternalContext wrapper and a
custom StateCache (in "server" mode) instance that handle the view state
from
outside can do the trick (use the same encryption keys for all apps and
so on). The key method is
StateCache.isWriteStateAfterRenderViewRequired(...)
(you need to set it to false, because the handling will be done later from
outside).

Could StateCache be overriden more easily? There is a StateCacheFactory, but
in MyFaces we have not made it as a service (for example set it up through
META-INF/services). Maybe it is a good idea. See:

http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java?view=markup

I don't know if I'm going too far, or if I'm thinking on the right
direction.

regards,

Leonardo Uribe

2016-12-07 17:39 GMT-05:00 Michael Müller <michael.mueller_at_mueller-bruehl.de
>:

> All,
>
> Although JSF 2.3 finally reaches a complete state, I have a problem:
>
> With JSF we can declare the state saving being on server or client site.
> Usually I do not like to transmit the whole state to the client. But
> keeping the state on server side forces sessions to be sticky. I'm going to
> test a cluster in cooperation with hazelcast within the next few weeks. I
> guess (I hope), this will allow to share the server site state between some
> machines.
>
> But what I really like to do, is to retrieve a session state which is
> shared between different applications: I like to split a big JSF
> application into some smaller parts which might be deployed independently.
> Using JSF navigation, the next dialog might be served from the same
> application or from a different one. This shall be completely transparent
> to the user. The user session is identified by a session id (using cookie)
> which is used for all of these applications. The different applications
> might be deployed to the same machine or to different machines. Thus, the
> state needs to be conserved in some common place, for example a database,
> e.g. a key value store like redis. Because the application should be
> splitted by function, it might be ok just to share the credentials.
>
> Maybe something like this is possible right now? Or might this be an
> option for a future version? Let me know your thoughts! Thanks.
>
> Herzliche Grüße - Best Regards,
>
> Michael Müller
> Brühl, Germany
> blog.mueller-bruehl.de
> it-rezension.de
> @muellermi
>
>
> Read my books
> "Web Development with Java and JSF": <https://leanpub.com/jsf>
> https://leanpub.com/jsf
> "Java Lambdas and Parallel Streams":
> <http://www.apress.com/de/book/9781484224861>
> http://www.apress.com/de/book/9781484224861
> "Visitors" a photographic image book: <https://leanpub.com/visitors>
> https://leanpub.com/visitors
>
>