From 28a82e288a9d4dd0d7ecb14f07cd3a64a696e432 Mon Sep 17 00:00:00 2001 From: Erik Lumme Date: Tue, 12 Sep 2017 11:52:14 +0300 Subject: [PATCH] Migrate ExposingServerSideAPIToJavaScript --- ...ExposingServerSideAPIToJavaScript.asciidoc | 134 ++++++++++++++++++ documentation/articles/contents.asciidoc | 1 + 2 files changed, 135 insertions(+) create mode 100644 documentation/articles/ExposingServerSideAPIToJavaScript.asciidoc diff --git a/documentation/articles/ExposingServerSideAPIToJavaScript.asciidoc b/documentation/articles/ExposingServerSideAPIToJavaScript.asciidoc new file mode 100644 index 0000000000..2f41d453a1 --- /dev/null +++ b/documentation/articles/ExposingServerSideAPIToJavaScript.asciidoc @@ -0,0 +1,134 @@ +[[exposing-server-side-api-to-javascript]] +Exposing server-side API to JavaScript +-------------------------------------- + +The new JavaScript integration functionality will allow you to easily +publish methods that can be called with JavaScript on the client side. +In effect, you can publish a JavaScript API for your application. +Although you will probably not find yourself using this very often, it +can be useful when integrating with JavaScript frameworks or embedding +within legacy sites. + +Exposing a `notify()` method that takes a message and displays that as a +notification can be done in one simple block in e.g `UI.init()`: + +[source,java] +.... +JavaScript.getCurrent().addFunction("notify", new JavaScriptFunction() { + public void call(JSONArray arguments) throws JSONException { + Notification.show(arguments.getString(0)); + } +}); +.... + +This will expose the `notify()`{empty}-method globally in the window object. +Technically it's thus `window.notify()`, but you can call it by simply +by `notify()`. Try entering `notify("Hey!")` into the Firebug or +Developler Tools console, or `javascript:notify("Hey!")` into the +address bar. + +You'll notice that this assumes there is a String in the first position +of the array. Also, this will clutter the global namespace, which is +generally not a good idea, unless you really have a specific need for +that. + +Let's make a complete example with two arguments, some simple error +handling, and namespacing: + +[source,java] +.... +JavaScript.getCurrent().addFunction("com.example.api.notify", + new JavaScriptFunction() { + public void call(JSONArray arguments) throws JSONException { + try { + String caption = arguments.getString(0); + if (arguments.length() == 1) { + // only caption + Notification.show(caption); + } else { + // type should be in [1] + Notification.show(caption, + Type.values()[arguments.getInt(1)]); + } + } catch (JSONException e) { + // We'll log in the console, you might not want to + JavaScript.getCurrent().execute( + "console.error('" + e.getMessage() + "')"); + } + } + }); +} +.... + +Using the dotted notation for the method will automatically create those +objects in the browser; you'll call this method like so: +`com.example.api.notify("Hey!")`. You do not have to use a long name +like this, though - it's up to you and your use-case. + +The second thing to notice is that we now wrapped the code in a +try-catch, so that the wrong number or wrong types of arguments does not +cause an ugly stacktrace in our server logs. Again, how you should react +to erroneous use of your exposed API depends on your use-case. We'll log +an error message to the browser console as an example. + +We're now accepting a second (integer) argument, and using that as +_type_ for the `Notification`. + +Finally, we'll add a link that will call the function, and work as a +_Bookmarklet_. You can drag the link to your bookmarks bar, and when you +invoke it when viewing the application with our exposed `notify()`{empty}-method, you will be prompted for a message that will then be sent to +the method. Here is the plain HTML code for creating such a link: + +[source,html] +.... +Send message +.... + +Here is the full source for our application: + +[source,java] +.... +import org.json.JSONArray; +import org.json.JSONException; +import com.vaadin.server.ExternalResource; +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.JavaScript; +import com.vaadin.ui.JavaScriptFunction; +import com.vaadin.ui.Link; +import com.vaadin.ui.Notification; +import com.vaadin.ui.Notification.Type; +import com.vaadin.ui.UI; + +public class JSAPIUI extends UI { + @Override + public void init(VaadinRequest request) { + + JavaScript.getCurrent().addFunction("com.example.api.notify", + new JavaScriptFunction() { + public void call(JSONArray arguments) throws JSONException { + try { + String caption = arguments.getString(0); + if (arguments.length() == 1) { + // only caption + Notification.show(caption); + } else { + // type should be in [1] + Notification.show(caption, + Type.values()[arguments.getInt(1)]); + } + } catch (JSONException e) { + // We'll log in the console, you might not want to + JavaScript.getCurrent().execute( + "console.error('" + e.getMessage() + "')"); + } + } + }); + + + setContent(new Link( + "Send message", + new ExternalResource( + "javascript:(function(){com.example.api.notify(prompt('Message'),2);})();"))); + } +} +.... diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc index 8360662dff..504cdcd33a 100644 --- a/documentation/articles/contents.asciidoc +++ b/documentation/articles/contents.asciidoc @@ -47,4 +47,5 @@ are great, too. - link:IntegratingAJavaScriptComponent.asciidoc[Integrating a JavaScript component] - link:IntegratingAJavaScriptLibraryAsAnExtension.asciidoc[Integrating a JavaScript library as an extension] - link:UsingAJavaScriptLibraryOrAStyleSheetInAnAddOn.asciidoc[Using a JavaScript library or a style sheet in an add-on] +- link:ExposingServerSideAPIToJavaScript.asciidoc[Exposing server-side API to JavaScript] - link:CreatingAUIExtension.asciidoc[Creating a UI extension] -- 2.39.5