aboutsummaryrefslogtreecommitdiffstats
path: root/documentation/advanced/advanced-global.asciidoc
diff options
context:
space:
mode:
authorelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
committerelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
commita1b265c318dbda4a213cec930785b81e4c0f7d2b (patch)
treeb149daf5a4f50b4f6446c906047cf86495fe0433 /documentation/advanced/advanced-global.asciidoc
parentb9743a48a1bd0394f19c54ee938c6395a80f3cd8 (diff)
downloadvaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.tar.gz
vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.zip
Framework documentation IN
Change-Id: I767477c1fc3745f9e1f58075fe30c9ac8da63581
Diffstat (limited to 'documentation/advanced/advanced-global.asciidoc')
-rw-r--r--documentation/advanced/advanced-global.asciidoc234
1 files changed, 234 insertions, 0 deletions
diff --git a/documentation/advanced/advanced-global.asciidoc b/documentation/advanced/advanced-global.asciidoc
new file mode 100644
index 0000000000..94b822235a
--- /dev/null
+++ b/documentation/advanced/advanced-global.asciidoc
@@ -0,0 +1,234 @@
+---
+title: Accessing Session-Global Data
+order: 15
+layout: page
+---
+
+[[advanced.global]]
+= Accessing Session-Global Data
+
+__This section is mostly up-to-date with Vaadin 7, but has some information
+which still needs to be updated.__
+
+Applications typically need to access some objects from practically all user
+interface code, such as a user object, a business data model, or a database
+connection. This data is typically initialized and managed in the UI class of
+the application, or in the session or servlet.
+
+For example, you could hold it in the UI class as follows:
+
+
+[source, java]
+----
+class MyUI extends UI {
+ UserData userData;
+
+ public void init() {
+ userData = new UserData();
+ }
+
+ public UserData getUserData() {
+ return userData;
+ }
+}
+----
+
+Vaadin offers two ways to access the UI object: with [methodname]#getUI()#
+method from any component and the global [methodname]#UI.getCurrent()# method.
+
+The [methodname]#getUI()# works as follows:
+
+
+[source, java]
+----
+data = ((MyUI)component.getUI()).getUserData();
+----
+
+This does not, however work in many cases, because it requires that the
+components are attached to the UI. That is not the case most of the time when
+the UI is still being built, such as in constructors.
+
+
+[source, java]
+----
+class MyComponent extends CustomComponent {
+ public MyComponent() {
+ // This fails with NullPointerException
+ Label label = new Label("Country: " +
+ getUI().getLocale().getCountry());
+
+ setCompositionRoot(label);
+ }
+}
+----
+
+The global access methods for the currently served servlet, session, and UI
+allow an easy way to access the data:
+
+
+[source, java]
+----
+data = ((MyUI) UI.getCurrent()).getUserData();
+----
+
+[[advanced.global.passing.problem]]
+== The Problem
+
+The basic problem in accessing session-global data is that the
+[methodname]#getUI()# method works only after the component has been attached to
+the application. Before that, it returns [parameter]#null#. This is the case in
+constructors of components, such as a [classname]#CustomComponent#:
+
+Using a static variable or a singleton implemented with such to give a global
+access to user session data is not possible, because static variables are global
+in the entire web application, not just the user session. This can be handy for
+communicating data between the concurrent sessions, but creates a problem within
+a session.
+
+The data would be shared by all users and be reinitialized every time a new user
+opens the application.
+
+
+[[advanced.global.passing.solutions-overview]]
+== Overview of Solutions
+
+To get the application object or any other global data, you have the following
+solutions:
+
+* Pass a reference to the global data as a parameter
+
+* Initialize components in [methodname]#attach()# method
+
+* Initialize components in the [methodname]#enter()# method of the navigation view
+(if using navigation)
+
+* Store a reference to global data using the __ThreadLocal Pattern__
+
+
+Each solution is described in the following sections.
+
+
+[[advanced.global.passing]]
+== Passing References Around
+
+You can pass references to objects as parameters. This is the normal way in
+object-oriented programming.
+
+
+[source, java]
+----
+class MyApplication extends Application {
+ UserData userData;
+
+ public void init() {
+ Window mainWindow = new Window("My Window");
+ setMainWindow(mainWindow);
+
+ userData = new UserData();
+
+ mainWindow.addComponent(new MyComponent(this));
+ }
+
+ public UserData getUserData() {
+ return userData;
+ }
+}
+
+class MyComponent extends CustomComponent {
+ public MyComponent(MyApplication app) {
+ Label label = new Label("Name: " +
+ app.getUserData().getName());
+
+ setCompositionRoot(label);
+ }
+}
+----
+
+If you need the reference in other methods, you either have to pass it again as
+a parameter or store it in a member variable.
+
+The problem with this solution is that practically all constructors in the
+application need to get a reference to the application object, and passing it
+further around in the classes is another hard task.
+
+
+[[advanced.global.attach]]
+== Overriding [methodname]#attach()#
+
+The [methodname]#attach()# method is called when the component is attached to
+the UI through containment hierarchy. The [methodname]#getUI()# method always
+works.
+
+
+[source, java]
+----
+class MyComponent extends CustomComponent {
+ public MyComponent() {
+ // Must set a dummy root in constructor
+ setCompositionRoot(new Label(""));
+ }
+
+ @Override
+ public void attach() {
+ Label label = new Label("Name: " +
+ ((MyUI)component.getUI())
+ .getUserData().getName());
+
+ setCompositionRoot(label);
+ }
+}
+----
+
+While this solution works, it is slightly messy. You may need to do some
+initialization in the constructor, but any construction requiring the global
+data must be done in the [methodname]#attach()# method. Especially,
+[classname]#CustomComponent# requires that the
+[methodname]#setCompositionRoot()# method is called in the constructor. If you
+can't create the actual composition root component in the constructor, you need
+to use a temporary dummy root, as is done in the example above.
+
+Using [methodname]#getUI()# also needs casting if you want to use methods
+defined in your UI class.
+
+
+[[advanced.global.threadlocal]]
+== ThreadLocal Pattern
+
+((("ThreadLocal pattern", id="term.advanced.global.threadlocal", range="startofrange")))
+
+
+Vaadin uses the ThreadLocal pattern for allowing global access to the
+[classname]#UI#, and [classname]#Page# objects of the currently processed server
+request with a static [methodname]#getCurrent()# method in all the respective
+classes. This section explains why the pattern is used in Vaadin and how it
+works. You may also need to reimplement the pattern for some purpose.
+
+The ThreadLocal pattern gives a solution to the global access problem by solving
+two sub-problems of static variables.
+
+As the first problem, assume that the servlet container processes requests for
+many users (sessions) sequentially. If a static variable is set in a request
+belonging one user, it could be read or re-set by the next incoming request
+belonging to another user. This can be solved by setting the global reference at
+the beginning of each HTTP request to point to data of the current user, as
+illustrated in Figure <<figure.advanced.global.threadlocal.sequentiality>>.
+
+[[figure.advanced.global.threadlocal.sequentiality]]
+.Switching a static (or ThreadLocal) reference during sequential processing of requests
+image::img/threadlocal-sequentiality-hi.png[]
+
+The second problem is that servlet containers typically do thread pooling with
+multiple worker threads that process requests. Therefore, setting a static
+reference would change it in all threads running concurrently, possibly just
+when another thread is processing a request for another user. The solution is to
+store the reference in a thread-local variable instead of a static. You can do
+so by using the [classname]#ThreadLocal# class in Java for the switch reference.
+
+[[figure.advanced.global.threadlocal.concurrency]]
+.Switching [classname]#ThreadLocal# references during concurrent processing of requests
+image::img/threadlocal-concurrency-hi.png[]
+
+(((range="endofrange", startref="term.advanced.global.threadlocal")))
+
+
+