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.8KB

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