You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ExposingServerSideAPIToJavaScript.asciidoc 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. ---
  2. title: Exposing Server Side API To JavaScript
  3. order: 41
  4. layout: page
  5. ---
  6. [[exposing-server-side-api-to-javascript]]
  7. = Exposing server-side API to JavaScript
  8. The new JavaScript integration functionality will allow you to easily
  9. publish methods that can be called with JavaScript on the client side.
  10. In effect, you can publish a JavaScript API for your application.
  11. Although you will probably not find yourself using this very often, it
  12. can be useful when integrating with JavaScript frameworks or embedding
  13. within legacy sites.
  14. Exposing a `notify()` method that takes a message and displays that as a
  15. notification can be done in one simple block in e.g `UI.init()`:
  16. [source,java]
  17. ....
  18. JavaScript.getCurrent().addFunction("notify", new JavaScriptFunction() {
  19. public void call(JSONArray arguments) throws JSONException {
  20. Notification.show(arguments.getString(0));
  21. }
  22. });
  23. ....
  24. This will expose the `notify()`{empty}-method globally in the window object.
  25. Technically it's thus `window.notify()`, but you can call it by simply
  26. by `notify()`. Try entering `notify("Hey!")` into the Firebug or
  27. Developler Tools console, or `javascript:notify("Hey!")` into the
  28. address bar.
  29. You'll notice that this assumes there is a String in the first position
  30. of the array. Also, this will clutter the global namespace, which is
  31. generally not a good idea, unless you really have a specific need for
  32. that.
  33. Let's make a complete example with two arguments, some simple error
  34. handling, and namespacing:
  35. [source,java]
  36. ....
  37. JavaScript.getCurrent().addFunction("com.example.api.notify",
  38. new JavaScriptFunction() {
  39. public void call(JSONArray arguments) throws JSONException {
  40. try {
  41. String caption = arguments.getString(0);
  42. if (arguments.length() == 1) {
  43. // only caption
  44. Notification.show(caption);
  45. } else {
  46. // type should be in [1]
  47. Notification.show(caption,
  48. Type.values()[arguments.getInt(1)]);
  49. }
  50. } catch (JSONException e) {
  51. // We'll log in the console, you might not want to
  52. JavaScript.getCurrent().execute(
  53. "console.error('" + e.getMessage() + "')");
  54. }
  55. }
  56. });
  57. }
  58. ....
  59. Using the dotted notation for the method will automatically create those
  60. objects in the browser; you'll call this method like so:
  61. `com.example.api.notify("Hey!")`. You do not have to use a long name
  62. like this, though - it's up to you and your use-case.
  63. The second thing to notice is that we now wrapped the code in a
  64. try-catch, so that the wrong number or wrong types of arguments does not
  65. cause an ugly stacktrace in our server logs. Again, how you should react
  66. to erroneous use of your exposed API depends on your use-case. We'll log
  67. an error message to the browser console as an example.
  68. We're now accepting a second (integer) argument, and using that as
  69. _type_ for the `Notification`.
  70. Finally, we'll add a link that will call the function, and work as a
  71. _Bookmarklet_. You can drag the link to your bookmarks bar, and when you
  72. 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
  73. the method. Here is the plain HTML code for creating such a link:
  74. [source,html]
  75. ....
  76. <a href="javascript:(function(){com.example.api.notify(prompt('Message'),2);})();">Send message</a>
  77. ....
  78. Here is the full source for our application:
  79. [source,java]
  80. ....
  81. import org.json.JSONArray;
  82. import org.json.JSONException;
  83. import com.vaadin.server.ExternalResource;
  84. import com.vaadin.server.VaadinRequest;
  85. import com.vaadin.ui.JavaScript;
  86. import com.vaadin.ui.JavaScriptFunction;
  87. import com.vaadin.ui.Link;
  88. import com.vaadin.ui.Notification;
  89. import com.vaadin.ui.Notification.Type;
  90. import com.vaadin.ui.UI;
  91. public class JSAPIUI extends UI {
  92. @Override
  93. public void init(VaadinRequest request) {
  94. JavaScript.getCurrent().addFunction("com.example.api.notify",
  95. new JavaScriptFunction() {
  96. public void call(JSONArray arguments) throws JSONException {
  97. try {
  98. String caption = arguments.getString(0);
  99. if (arguments.length() == 1) {
  100. // only caption
  101. Notification.show(caption);
  102. } else {
  103. // type should be in [1]
  104. Notification.show(caption,
  105. Type.values()[arguments.getInt(1)]);
  106. }
  107. } catch (JSONException e) {
  108. // We'll log in the console, you might not want to
  109. JavaScript.getCurrent().execute(
  110. "console.error('" + e.getMessage() + "')");
  111. }
  112. }
  113. });
  114. setContent(new Link(
  115. "Send message",
  116. new ExternalResource(
  117. "javascript:(function(){com.example.api.notify(prompt('Message'),2);})();")));
  118. }
  119. }
  120. ....