Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Examples/Eclipse Business Expense Reporting Tool/User State Service"

 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
{{warning2|text=This page is under development}}
 
{{warning2|text=This page is under development}}
Managing the user state in a standalone application is relatively easy. EBERT runs as both a standalone application (RCP, ERCP) and as a multiple-user application (RAP). To support both environments, we have to be careful how we store user state.
+
EBERT runs as both a standalone application (RCP, ERCP) and as a multiple-user application (RAP). To support both environments, we have to be careful how we store user state.
  
EBERT defines an Equinox/OSGi Service of type [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.views/src/org/eclipse/examples/expenses/context/IUserContextService.java?root=Technology_Project&view=markup IUserContextService.java]&mdash;defined in the <code>org.eclipse.examples.expenses.views</code> project&mdash;along with two different implementations. Implementations of this type are responsible for one thing: answer, when asked, the user state (an instance of [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.views/src/org/eclipse/examples/expenses/context/IUserContext.java?root=Technology_Project&view=markuporg.eclipse.examples.expenses.context.IUserContext IUserContext]) for the current user.
+
EBERT defines an Equinox/OSGi Service of type [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.views/src/org/eclipse/examples/expenses/context/IUserContextService.java?root=Technology_Project&view=markup IUserContextService.java] along with two different implementations. Implementations of this type are responsible for one thing: answer, when asked, the user state (an instance of [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.views/src/org/eclipse/examples/expenses/context/IUserContext.java?root=Technology_Project&view=markup IUserContext]) for the current user.
  
The notion of "current user" is pretty simple in the standalone case: there is only one user.
+
{{warning2|text=Note that a notion of user state is being explored by the [[e4]] effort.}}
 +
 
 +
The notion of "current user" is pretty simple in the standalone case: there is only one user. The [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.context.standalone/src/org/eclipse/examples/expenses/context/standalone/StandaloneUserContextService.java?root=Technology_Project&view=markup StandaloneUserContextService] simply returns an instance of [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.context.standalone/src/org/eclipse/examples/expenses/context/standalone/StandaloneUserContext.java?root=Technology_Project&view=markup StandaloneUserContext] that it holds in a field. The [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.context.standalone/src/org/eclipse/examples/expenses/context/standalone/Activator.java?root=Technology_Project&view=markup activator] for the bundle containing these types registers the service on bundle startup and deregisters it on shutdown.
 +
 
 +
The notion of "current user" is more interesting in the multiple-user case of RAP. [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.application.rap/src/org/eclipse/examples/expenses/context/rap/RapUserContextService.java?root=Technology_Project&view=markup RapUserContextService] uses the HTTP Session state, accessible through APIs on RAP's RWT type. This returns for us an instance of [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.application.rap/src/org/eclipse/examples/expenses/context/rap/RapUserContext.java?root=Technology_Project&view=markup RapUserContext] that is specific to the user tied to the current thread. As is the case with the standalone variant, this service is registered and deregistered by the bundle activator.
 +
 
 +
The user context provides a view model for the current user along with other useful information such as the user-specific locale. The current implementations are also responsible for managing CRUD operations on the domain model. This will change with the introduction of the notion of a persistence service.
 +
 
 +
The user context service is obtained by clients using an OSGi ServiceTracker. An example of this can be found in the <code>startUserContextServiceTracker()<code> method in the [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.examples/ebert/org.eclipse.examples.expenses.views/src/org/eclipse/examples/expenses/views/AbstractView.java?root=Technology_Project&view=markup AbstractView] class (which is the superclass for all the EBERT views). ''This code will be greatly simplified when we change it to leverage OSGi Declarative Services.'' The <code>userContextServiceTracker</code> is notified, via the <code>addingService</code> method whenever a service is added or removed. Our implementation is greedy: it takes the first service that it finds. When this first service presents itself, the instance is notified via the <code>connectToUserContext(...)</code> method. Likewise, when the service that we greedily obtained is removed, the instance is notified via the <code>disconnectFromUserContext(...)</code> method. This allows the application to be very dynamic as the state of the services changes; the views dynamically configure themselves based on the availability of a user context service.
 +
 
 +
The <code>syncExec</code> blocks bear some discussion. This ServiceTracker will be invoked by threads other than the UI thread that owns the view instance. Since we may be running in RAP, we need to make sure that when we obtain the user context, we get the right one. By wrapping the call to <code>getUserContext</code> inside a <code>syncExec</code> block, we can be sure that the code that obtains the user context is running in the right user's UI thread. The <code>syncExec</code> method is a convenience method that obtains the receiver's SWT Display and invokes <code>syncExec</code> on it.

Latest revision as of 16:34, 26 February 2009

This page is under development

EBERT runs as both a standalone application (RCP, ERCP) and as a multiple-user application (RAP). To support both environments, we have to be careful how we store user state.

EBERT defines an Equinox/OSGi Service of type IUserContextService.java along with two different implementations. Implementations of this type are responsible for one thing: answer, when asked, the user state (an instance of IUserContext) for the current user.

Note that a notion of user state is being explored by the e4 effort.

The notion of "current user" is pretty simple in the standalone case: there is only one user. The StandaloneUserContextService simply returns an instance of StandaloneUserContext that it holds in a field. The activator for the bundle containing these types registers the service on bundle startup and deregisters it on shutdown.

The notion of "current user" is more interesting in the multiple-user case of RAP. RapUserContextService uses the HTTP Session state, accessible through APIs on RAP's RWT type. This returns for us an instance of RapUserContext that is specific to the user tied to the current thread. As is the case with the standalone variant, this service is registered and deregistered by the bundle activator.

The user context provides a view model for the current user along with other useful information such as the user-specific locale. The current implementations are also responsible for managing CRUD operations on the domain model. This will change with the introduction of the notion of a persistence service.

The user context service is obtained by clients using an OSGi ServiceTracker. An example of this can be found in the startUserContextServiceTracker()<code> method in the AbstractView class (which is the superclass for all the EBERT views). This code will be greatly simplified when we change it to leverage OSGi Declarative Services. The <code>userContextServiceTracker is notified, via the addingService method whenever a service is added or removed. Our implementation is greedy: it takes the first service that it finds. When this first service presents itself, the instance is notified via the connectToUserContext(...) method. Likewise, when the service that we greedily obtained is removed, the instance is notified via the disconnectFromUserContext(...) method. This allows the application to be very dynamic as the state of the services changes; the views dynamically configure themselves based on the availability of a user context service.

The syncExec blocks bear some discussion. This ServiceTracker will be invoked by threads other than the UI thread that owns the view instance. Since we may be running in RAP, we need to make sure that when we obtain the user context, we get the right one. By wrapping the call to getUserContext inside a syncExec block, we can be sure that the code that obtains the user context is running in the right user's UI thread. The syncExec method is a convenience method that obtains the receiver's SWT Display and invokes syncExec on it.

Copyright © Eclipse Foundation, Inc. All Rights Reserved.