myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stan Carney <stan.java....@moohoffa.com>
Subject Re: JSF and AJAX without custom components?
Date Thu, 14 Jun 2007 17:40:01 GMT
Yeah, we actually make use of Springs ServletWrappingController class 
when we don't need JSF. i.e. no forms etc...

 From a performance standpoint you do have a good point actually. So 
rather than a phase listener that is hit on every single JSF request 
just use a Servlet that mimics FacesServlet but just performs the task 
that you need done when called directly.

Looking at the source code of FacesServlet it seems pretty straight 
forward. What would I have to do to get JSF to complete the RESTORE_VIEW 
phase and stop without a phase listener? Won't I also have problems with 
the pesky javax.faces.ViewState containing the wrong viewId and not 
restoring state?

i.e.
Servlet URL: /path/to/servlet.foo
viewId: /my/page.xhtml


Thanks,
Stan


Werner Punz wrote:
> For specialized cases it might be better to use servlets or servlet
> filters as callback points.
> The problem with phase listeners is they are called every time a request
> is triggered.
> The + side is, that you do not have to initialize jsf it is
> preinitialized for you if you need access to the jsf inastructure
>
> (which in many cases you wont need anyway, especially if you are on ejb3
> or spring for providing the backend beans)
> The other + side is, phase listeners are deployed more easily as we all
> know.
>
> So either way has its ups and downs, but if speed is a concern than
> going the servlet route really might be better!
>
>
>
> Stan Carney schrieb:
>   
>> Thanks for your response Ernst!
>>
>> Yeah, I have looked around at pretty much every JSF AJAX framework out
>> there and it isn't that I'm not impressed. There are definitely some
>> smart people working to create generic components to be consumed by the
>> masses. In our current position though I don't think these frameworks
>> make a lot of sense for us to use. We have an extremely strong UI
>> developer and we just want to be able to expose his talents, and in our
>> current circumstance having to use pre-built AJAX components or having
>> to create our own would severely hamper his abilities.
>>
>> So anyway I have solved my problem via the following process. It allows
>> us to interact with JSF, i.e. forms, via AJAX without having to write
>> components. It has some significant short comings if it was going to be
>> used for general consumption by the JSF community (i.e. lacking
>> configuration, you can shoot your foot off easily, etc...) but works for
>> us. So keeping with good list etiquette I'm posting my solution below
>> for those, if any, that get a hit on my initial question.
>>
>>
>> I have created a PhaseListener that runs after the RESTORE_VIEW phase
>> and checks for the presence of a known parameter. Every parameter on
>> every request is checked which I'm not a fan of but from what I have
>> seen most other JSF/AJAX solutions do the same and it appears to run
>> super fast. If a 'known' parameter exists the PhaseListener instantiates
>> the class associated with the parameter for processing. In my case all
>> of these 'processor' classes implement a simple interface with one
>> method, process(), that takes a CaseInsensitiveMap as an argument. This
>> map contains the map returned value from the getParameterMap() method on
>> HttpServletRequest:
>>
>> HttpServletRequest req = (HttpServletRequest)
>> event.getFacesContext().getExternalContext().getRequest();
>> CaseInsensitiveMap map = new CaseInsensitiveMap();
>> map.putAll(req.getParameterMap());
>>
>> The process() method then does what it needs to do. Typically finding
>> components by their ids in the restored view, that are either known by
>> the class or sent as parameters, and updating their values accordingly.
>> Then the class composes an XML document that our client side JavaScript
>> (taconite and/or JQuery) understands and returns this XML string. The
>> PhaseListener then determines if the returned string contains a
>> javax.faces.ViewState placeholder we came up with and substitutes the
>> placeholder with the new ViewState value generated below. If there is no
>> placeholder, i.e. not interacting with a JSF form, we can omit the
>> updating of the ViewState value. In that case though we typically do
>> straight HTTP and bypass JSF completely.
>>
>>    try {
>>            UIViewRoot viewRoot = context.getViewRoot();
>>
>>            StateManager stateMgr =
>> context.getApplication().getStateManager();
>>            ComponentSupport.removeTransient(viewRoot);
>>
>>            SerializedView serializedView =
>> stateMgr.saveSerializedView(context);
>>
>>            Object[] savedState = new Object[3];
>>            Object treeStruct = serializedView.getStructure();
>>            if (treeStruct != null) {
>>                if (treeStruct instanceof String) {
>>                    savedState[0] = treeStruct;
>>                }
>>            }
>>            savedState[2] = viewRoot.getViewId();
>>            String viewState = StateUtils.construct(savedState,
>> context.getExternalContext());
>>
>>            return viewState;
>>        } catch (Exception e) {
>>            throw new RuntimeException(e);
>>        }
>>
>> The PhaseListener writes out the string to the response stream and marks
>> the response as complete. The client JavaScript interprets the XML and
>> updates the DOM. The DOM should now match the DOM stored on the server.
>>
>> It works well for us and results in the creation of only one class,
>> after the initial PhaseListener creation, per Ajaxable event. The above
>> code does tinker with the internal workings of MyFaces which may/will
>> cause us issues on an upgrade. I haven't tested it for thread-safety yet
>> but everything I have seen with other frameworks leads me to believe all
>> is well.
>>
>> Thanks,
>> Stan
>>
>>
>> Ernst Fastl wrote:
>>     
>>> Hi,
>>>
>>> I can understand you don't like to write your own component for
>>> soving this problem (although seeing the stuff you posted I guess
>>> you are skilled enough for that).
>>>
>>> Anyway, have you tried the
>>> existing solutions like PPRPanelGroup from the tomahawk sandbox
>>> or Ajax4JSF?
>>>
>>> regards
>>>
>>> Ernst
>>>       


Mime
View raw message