For normal requests we can simple register an <error-page> in web.xml. However, this does not apply to Ajax-requests. By default errors during an Ajax-request will result in a little pop-window in the browser that shows the exception.
The main example I am struggling with is handling a ViewExpiredException in a uniform way. For standard requests, I redirect to a page that explains that the user is not logged in and provides a link to the login-page. I would like to do the same for Ajax-requests. There seem to be several ways:
I could write a javascript function that handles the error on the client-side and redirects to the error-page. I would then have to add this function every <f:ajax>-tag on all pages using the onerror-attribute. Is there a way to tell JSF that I want to have this javascript-function as the default error-handler for all <f:ajax>-tags?
I could use a custom exception-handler, as described in this blog. This seems to do what I want, but I wonder if it is overkill. Is there no simpler solution?
So my question is, how is this supposed to be solved? Which of the approaches I listed should be used? Is there another approach that I do not know of?
You can use jsf.ajax.addOnError() to set the default error handler. E.g.
jsf.ajax.addOnError(function(data) {
alert(data.responseText);
});
See also chapter 13.3.6.2 of the JSF2 spec. You can find all properties of data object in table 14-4 of the JSF2 spec.
Related
I have been using thymeleaf th:onclick attribute to call javascript function with parameters as below
th:onclick="|myFunction('${parameter1}')|"
But with thymeleaf 3.1.10 this has been removed. and they are suggesting to use th:data attribute.
I however found workaround on as below and both of them are working perfectly.
th:attr="onclick=|myFunction('${parameter1}')|"
th:onclick="#{myFunction('${parameter1}')}">
Now i am not sure if these workarounds are correct way to do things and if yes which one is the better way.
The first will work like you want -- however, you are bypassing the the security restriction and now your pages are vulnerable to javascript injection (which is the original reason this change was made).
The second one just plain doesn't work. It doesn't expand out the variable ${parameter1}, instead just encoding it as a url like this:
onclick="myFunction?$%7Bparameter1%7D"
You really should be doing it as shown on the page.
th:data-parameter1="${parameter1}" onclick="myFunction(this.getAttribute('data-parameter1'));"
Could somebody please suggest me a good beginner tutorial of using Ajax with Zend 1.I have been searching the net for some of this tutorials, but couldn't find an understandable one.In some they say you have to create a .json.phtml file for json response, the others don't.I am very confused about all these ajax calls with Zend Framework 1. Would be very grateful.
Well there really are some basic things.
Get your data (from DB, file, in-code array, whatever)
Get the controller helper
Send the JSON response
And that's it. OK, not exactly but basically yes!
Provided you have the data in $data:
$this->_helper->json($data, true);
will return a JSON response. The documentation is here.
Now there is the other notion of a Context Switch and AjaxContentHelper which:
The ContextSwitch action helper is intended for facilitating returning different response formats on request. The AjaxContext helper is a specialized version of ContextSwitch that facilitates returning responses to XmlHttpRequests.
To enable either one, you must provide hinting in your controller as to what actions can respond to which contexts. If an incoming request indicates a valid context for the given action, the helper will then:
Disable layouts, if enabled.
Set an alternate view suffix, effectively requiring a separate view script for the context.
Send appropriate response headers for the context desired.
Optionally, call specified callbacks to setup the context and/or perform post-processing.
Something like this:
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->setDefaultContext('json');
$contextSwitch->addActionContext('index', array('xml','json'))->initContext();
$contextSwitch->addActionContext('get', array('xml','json'))->initContext();
$contextSwitch->addActionContext('post', array('xml','json'))->initContext();
$contextSwitch->addActionContext('put', array('xml','json'))->initContext();
$contextSwitch->addActionContext('delete', array('xml','json'))->initContext();
$contextSwitch->addActionContext('head', array('xml','json'))->initContext();
You don't really need a tutorial I think. All you need is a good basic knowledge of how the web works internally and to read the Zend Documentation. Anyway here is some tutorial on ContextSwitch.
We are extensively using Dojo's xhrGet and xhrPost in our application. This has been used across multiple JavaScript files. Now we need a uniform way in which we handle the exceptions that are returned from the server in case of an AJAX call. We don't want to handle this in all places where we are using Dojo's xhrGet or xhrPost. Is it possible to do that without disturbing any of the existing code? For example, when some exception is sent from the server as part of the ajax response, I need to display some message in a consistent way across the application.
Could you please suggest me a solution for this? Kindly let me know if any more information is required.
Use IO Pipeline Topics as I described in Generic Loading Icon in Dojo and you won't have to change your code at all.
did you look at the dojo/aspect or dojo/on ? You can define functions that get executed after a function was called (or before) with aspect.
Take a look at that:
http://dojotoolkit.org/reference-guide/1.8/dojo/aspect.html#dojo-aspect-after
Why dont you create a custom xhrArgs class using dojo/declare that has the same error function for all his children ?
http://dojotoolkit.org/reference-guide/1.8/dojo/_base/declare.html#dojo-base-declare
Lucian
The specific case I've got in mind is as follows: an AjaxFormComponentUpdatingBehavior("onchange") is added to a TextField in a form. The behavior verifies the text for certain conditions (either the model object or the form component model, doesn't matter), based on which it might display a message (or hide it, if it has already been shown).
The problem is, there are also validators added to the TextField. One of the possible (and likely) scenarios consists of the user typing in, first, a value that causes the message to be displayed by the AJAX request. If, then, he/she types in a value that doesn't pass validation, the message should disappear, but it does not.
Apparently, either the onUpdate() method for the AJAX behavior is not called at all, or I am failing in my attempts to insert a check for non-validated entries (I have tried to test for both null values and empty strings, to no avail; I have no idea what exactly Wicket's validators do to models when data is invalid).
I am wondering if someone who actually understands validators (or AJAX, actually) has any ideas on where the problem could be.
I can post edit and post code if someone tells me this is not a general issue tying validators and AJAX, but most likely a programming mistake. I still believe the former and thus I'll refrain from posting code sections, in order to keep the discussion on an API/theoretical frame.
Thanks.
When using an AjaxFormComponentUpdatingBehavior, if any of the IValidators fail their validation, onError() will be called instead of onUpdate(). Wicket will effectively prevent invalid user input from reaching the IModels in your components, so the component's ModelObject will not be changed at all. The invalid input will probably remain available by means of getInput()/getConvertedInput() (not sure if it will in an AJAX scenario, it sure is in a traditional form submission).
However, take into account that IFormValidators are not executed when using this mechanism. If you've got any, you might be interested in overriding getUpdateModel() so that AjaxFormComponentUpdatingBehavior will not bring maybe-invalid user input into your IModels, and set modelobjects manually when you're certain user input is valid.
Regarding your specific case, you could perform all the required logic in onError() (or rely on Models that will grab data from somewhere else), and just add the components that need refreshing to the AjaxRequestTarget. This is probably what's missing in your scenario.
I want to use Wicket to build an application, but I have some designers that would like to write/maintain the javascript, and they basically expect 1 JS-segment per page, and a global JS-file.
I think the most natural way to add javascript in wicket is to add it per component (not per page), which would create problems for those designers (fractioned javascript, and having to write it in java-files). Is there a better way to solve this?
(of course, I expect things to work after a partial refresh.)
And a second (related) thing they'd like (and I'd like actually) is the possibility to request information in JSON-format through a static link , is this possible in Wicket?
I started with JSON by making my wicket pages return the JSON, but quickly realized there are better tools for the job, especially if you will have a full web services layer. If you just need a little JSON here and there, always via a GET, then sure, just make a Wicket page.
I ended up using Jersey with Jackson alongside of Wicket. Jersey simplifies the configuration of URLs that can do different things with different http methods (GET/POST/PUT/DELETE), as well as easily parsing query strings, etc. I'd consider going this route for heavier JSON needs.
You can easily run both Wicket and Jersey in the same web application with a little web.xml configuration.
Wicket's built in AJAX support is always stateful and thus accessed with changing URLs. If your designers aren't planning to use Wicket's JS library, it's pretty straightforward to mount a JSON page:
public class JsonReturningPage extends WebPage {
public JsonReturningPage(PageParameters params) {
String json = "{foo: 4711}";
IRequestTarget t = new StringRequestTarget("application/json", "UTF-8", json);
getRequestCycle().setRequestTarget(t);
}
}
Alternatively, you could also implement your own AbstractRequestTargetUrlCodingStrategy to directly return an IRequestTarget from IRequestTarget decode(RequestParameters params) and mount it in your application.
Regarding JS files, I'd try to educate them to use one file per component. This certainly has the advantage of less copy-paste code and simpler maitenance. Additionally, I'd certainly discourage JS in Java code. It's normally only needed to pass data or config to JS , either as variable definitions or method calls. As this data is typically in Java and JS is written by designers, it's time for designers and programmers to team up.
Quick answer to your second question is yes it is possible. Use bookmarkable links to access a resource that returns JSON data.
You can easily use the following code to dynamically communicate with Wicket:
AbstractDefaultAjaxBehavior callme = new AbstractDefaultAjaxBehavior(){
#Override
protected void respond(AjaxRequestTarget target) {
}
};
page.add(callme);
//From any ajaxrequesttarget you can simply append the following code:
target.appendJavascript("wicketAjaxGet('"+callme.getCallbackUrl()+");");
This way you can have an ajaxlink etc... that will transfer the ajaxrequest to the Wicket side. If you want to pass data (though a static link doesn't sound like that) do the following:
"wicketAjaxGet('"+callme.getCallbackUrl()+"&x='+value_to_pass_back''";
//to Read the value in the respond:
String x = RequestCycle.get().getRequest().getParameter("x");
So the url to the callback is dynamically generated (as the callback url is specific to the session) but it is formed like any other url....
To me this is 10 times simpler than building a JSON system on top of wicket instead of using the one built into it.... I use this all the time and it works great for me at least. If your solution is different/better I would like to know why perhaps.