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
>