Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. ---
  2. title: Injection And Scopes
  3. order: 48
  4. layout: page
  5. ---
  6. [[ii-injection-and-scopes]]
  7. II - Injection and scopes
  8. -------------------------
  9. In this tutorial we'll take a closer look at the @CDIUI annotation and
  10. use CDI to inject some beans to our application.
  11. [[cdiui]]
  12. @CDIUI
  13. ~~~~~~
  14. The @CDIUI annotation is the way in which you let the Vaadin CDI plugin
  15. know which UI's should be accessible to the user and how they should be
  16. mapped. It accepts one optional String parameter indicating the UI path.
  17. If an explicit path is not provided the class name of the UI will be
  18. used to construct a pathname by the following convention: any trailing
  19. "UI" will be truncated and camelcase will be converted to hyphenated
  20. lowercase. Some examples of the convention:
  21. ....
  22. HelloWorldUI → hello-world
  23. ExampleUI → example
  24. VisualEditor → visual-editor
  25. ....
  26. Passing an empty String as the path will cause the UI to be mapped to
  27. the root of the deployment. Most single UI applications will probably
  28. want to do this.
  29. [[injecting-beans]]
  30. Injecting beans
  31. ~~~~~~~~~~~~~~~
  32. Now that the UI itself has been injected, we can use the @Inject
  33. annotation to further inject beans to it. Let's create something for us
  34. to actually inject.
  35. We'll define the following interface, and an implementation for it.
  36. [source,java]
  37. ....
  38. package com.vaadin.cdi.tutorial;
  39. public interface Greeting {
  40. public String getText();
  41. }
  42. ....
  43. [source,java]
  44. ....
  45. package com.vaadin.cdi.tutorial;
  46. import java.io.Serializable;
  47. public class SimpleGreetingImpl implements Greeting, Serializable {
  48. @Override
  49. public String getText() {
  50. return "Hello, World!";
  51. }
  52. }
  53. ....
  54. So far so good, now we'll inject it into our UI. You'll need to add the
  55. CDI API as a dependency in your pom.xml. (Group id: javax.enterprise,
  56. artefact id: cdi-api, version: 1.2)
  57. [source,java]
  58. ....
  59. package com.vaadin.cdi.tutorial;
  60. import javax.inject.Inject;
  61. import com.vaadin.annotations.Theme;
  62. import com.vaadin.cdi.CDIUI;
  63. import com.vaadin.server.VaadinRequest;
  64. import com.vaadin.ui.Button;
  65. import com.vaadin.ui.Button.ClickEvent;
  66. import com.vaadin.ui.Label;
  67. import com.vaadin.ui.UI;
  68. import com.vaadin.ui.VerticalLayout;
  69. @SuppressWarnings("serial")
  70. @CDIUI("")
  71. @Theme("valo")
  72. public class HelloWorldUI extends UI {
  73. @Inject
  74. private Greeting greeting;
  75. @Override
  76. protected void init(VaadinRequest request) {
  77. final VerticalLayout layout = new VerticalLayout();
  78. layout.setMargin(true);
  79. setContent(layout);
  80. Button button = new Button("Click Me");
  81. button.addClickListener(new Button.ClickListener() {
  82. public void buttonClick(ClickEvent event) {
  83. layout.addComponent(new Label(greeting.getText()));
  84. }
  85. });
  86. layout.addComponent(button);
  87. }
  88. }
  89. ....
  90. Let's run that and see.
  91. image:img/hello-world.png[Injection seems to be working]
  92. So far so good. Suppose we want to say hello to the user by name. We'll
  93. create a class to store our user data in. For now it's a simple POJO
  94. just for storing the name in a single string.
  95. [source,java]
  96. ....
  97. package com.vaadin.cdi.tutorial;
  98. import java.io.Serializable;
  99. public class UserInfo implements Serializable {
  100. private String name;
  101. public UserInfo() {
  102. this.name = "stranger";
  103. }
  104. public UserInfo(String name) {
  105. this.name = name;
  106. }
  107. public String getName() {
  108. return name;
  109. }
  110. public void setName(String name) {
  111. this.name = name;
  112. }
  113. }
  114. ....
  115. We'll inject that to the UI and assign the user some name during
  116. initialization (for now)
  117. [source,java]
  118. ....
  119. @Inject
  120. private UserInfo user;
  121. @Override
  122. protected void init(VaadinRequest request) {
  123. ...
  124. user.setName("Ernest");
  125. }
  126. ....
  127. Then we'll create a new implementation of the Greeting and inject the
  128. user there as well.
  129. [source,java]
  130. ....
  131. package com.vaadin.cdi.tutorial;
  132. import javax.inject.Inject;
  133. public class UserGreetingImpl implements Greeting {
  134. @Inject
  135. private UserInfo user;
  136. @Override
  137. public String getText() {
  138. return "Hello, " + user.getName() + "!";
  139. }
  140. }
  141. ....
  142. Now, it would be easy to think that that's all you need but we're not
  143. quite there. There are two issues with this that need to be addressed.
  144. The first one will become immediately obvious when you try to deploy the
  145. application. The deployment will fail as the injection in HelloWorldUI
  146. is ambiguous, that is CDI doesn't know which implementation of Greeting
  147. we want. +
  148. There are three annotations that are useful in situations like this:
  149. @Default, @Alternative and @Specializes. Giving a bean any of these
  150. annotations will affect it's preference order when the CDI container is
  151. looking for which implementation to inject. Unless otherwise specified,
  152. beans will be considered to have the @Default annotation. Beans with the
  153. @Alternative annotation will only be injected if that particular bean is
  154. named in the beans.xml file (TODO: add link). Beans with the
  155. @Specializes annotation will be considered a drop-in replacement for
  156. it's superclass, and will be used over any implementations it extends. +
  157. In our case, we'll want to give SimpleGreetingImpl the @Default
  158. annotation and UserGreetingImpl the @Alternative annotation.
  159. [source,java]
  160. ....
  161. @Default
  162. public class SimpleGreetingImpl implements Greeting {
  163. ....
  164. [source,java]
  165. ....
  166. @Alternative
  167. public class UserGreetingImpl implements Greeting {
  168. ....
  169. After that the application could actually be deployed. To tell CDI we'll
  170. want to use our alternative implementation we need to create the
  171. beans.xml in our WEB-INF folder, and add the following declaration to
  172. it:
  173. [source,xml]
  174. ....
  175. <beans>
  176. <alternatives>
  177. <class>com.vaadin.cdi.tutorial.UserGreetingImpl</class>
  178. </alternatives>
  179. </beans>
  180. ....
  181. Let's try that out:
  182. image:img/hello-stranger.png[Something's not right]
  183. Better, but not quite there yet. We're getting the wrong username,
  184. despite the fact that we set the username to "Earnest" in the UI. The
  185. problem here is the scope of the bean. If you don't specify a scope for
  186. your bean either in the bean class itself or at the injection point,
  187. it'll default to using the dependent scope. Every time you inject a
  188. dependent bean you'll get a new instance, which is clearly not what we
  189. want here. Let's go back to our UserInfo class and assign it an explicit
  190. scope.
  191. [source,java]
  192. ....
  193. import com.vaadin.cdi.UIScoped;
  194. @UIScoped
  195. public class UserInfo {
  196. ...
  197. ....
  198. The @UIScoped annotation is specific to Vaadin CDI. Anything injected
  199. with that annotation will get the same instance while within the same
  200. UI. Load a different UI and you'll get a different instance. If the
  201. session expires or the UI is closed the instances will be cleaned up. +
  202. Let's see if it worked.
  203. image:img/hello-earnest.png[Something IS right]
  204. Looks like we're making progress.