diff options
Diffstat (limited to 'documentation/advanced/advanced-spring.asciidoc')
-rw-r--r-- | documentation/advanced/advanced-spring.asciidoc | 696 |
1 files changed, 0 insertions, 696 deletions
diff --git a/documentation/advanced/advanced-spring.asciidoc b/documentation/advanced/advanced-spring.asciidoc deleted file mode 100644 index 7f83b864fd..0000000000 --- a/documentation/advanced/advanced-spring.asciidoc +++ /dev/null @@ -1,696 +0,0 @@ ---- -title: Vaadin Spring Add-on -order: 18 -layout: page ---- - -[[advanced.spring]] -= Vaadin Spring Add-on - -((("Vaadin Spring", id="term.advanced.spring.springlong", range="startofrange"))) - - -((("Spring", id="term.advanced.spring.spring", range="startofrange"))) - - -Vaadin Spring and Vaadin Spring Boot add-ons make it easier to use Spring in -Vaadin applications. Vaadin Spring enables Spring dependency injection with -custom UI and view providers, and provides three custom scopes: -[classname]#UIScope#, [classname]#ViewScope#, and -[classname]#VaadinSessionScope#. - -API documentation for add-ons is available at: - -* Vaadin Spring API at link:https://vaadin.com/api/vaadin-spring[vaadin.com/api/vaadin-spring] -* Vaadin Spring Boot API at link:https://vaadin.com/api/vaadin-spring-boot[vaadin.com/api/vaadin-spring-boot] - -To learn more about Vaadin Spring, the -link:https://vaadin.com/wiki/-/wiki/Main/Vaadin+Spring[Vaadin Spring Tutorial] -gives a hands-on introduction. The source code of the Spring Tutorial demo is -available for browsing or cloning at -link:https://github.com/Vaadin/spring-tutorial[github.com/Vaadin/spring-tutorial]. - -[[advanced.spring.spring]] -== Spring Overview - -__Spring Framework__ is a Java application framework that provides many useful -services for building applications, such as authentication, authorization, data -access, messaging, testing, and so forth. In the Spring core, one of the central -features is dependency injection, which accomplishes inversion of control for -dependency management in managed beans. Other Spring features rely on it -extensively. As such, Spring offers capabilities similar to CDI, but with -integration with other Spring services. Spring is well-suited for applications -where Vaadin provides the UI layer and Spring is used for other aspects of the -application logic. - -__Spring Boot__ is a Spring application development tool that allows creating -Spring applications easily. __Vaadin Spring Boot__ builds on Spring Boot to -allow creating Vaadin Spring applications easily. It starts up a servlet, -handles the configuration of the application context, registers a UI provider, -and so forth. - -Regarding general Spring topics, we recommend the following Spring -documentation: - -ifdef::web[] -* link:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/[Spring -Framework Reference Documentation]. - -* link:http://projects.spring.io/spring-framework/[Spring Project] - -* link:https://vaadin.com/wiki/-/wiki/Main/Vaadin+Spring[Vaadin Spring Tutorial] - -endif::web[] - -[[advanced.spring.spring.injection]] -=== Dependency Injection - -__Dependency injection__ is a way to pass dependencies (service objects) to -dependent objects (clients) by injecting them in member variables or initializer -parameters, instead of managing the lifecycle in the clients or passing them -explicitly as parameters. In Spring, injection of a service object to a client -is configured with the [classname]#@Autowired# annotation. - -For a very typical example in a web application, you could have a user data -object associated with a user session: - - -[source, java] ----- -@SpringComponent -@VaadinSessionScope -public class User implements Serializable { - private String name; - - public void setName(String name) {this.name = name;} - public String getName() {return name;} -} ----- - -The [classname]#@SpringComponent# annotation allows for automatic detection of -managed beans by Spring. (The annotation is exactly the same as the regular -Spring [classname]#@Component#, but has been given an alias, because Vaadin has -a [interfacename]#Component# interface, which can cause trouble.) - -Now, if we have a UI view that depends on user data, we could inject the data in -the client as follows: - - -[source, java] ----- -public class MainView extends CustomComponent implements View { - User user; - Label greeting = new Label(); - - @Autowired - public MainView(User user) { - this.user = user; - ... - } - - ... - @Override - public void enter(ViewChangeEvent event) { - // Then you can use the injected data - // for some purpose - greeting.setValue("Hello, " + user.getName()); - } -} ----- - -Here, we injected the user object in the constructor. The user object would be -created automatically when the view is created, with all such references -referring to the same shared instance in the scope of the Vaadin user session. - - -[[advanced.spring.spring.contexts]] -=== Contexts and Scopes - -__Contexts__ in Spring are services that manage the lifecycle of objects and -handle their injection. Generally speaking, a context is a situation in which an -instance is used with a unique identity. Such objects are essentially -"singletons" in the context. While conventional singletons are application-wide, -objects managed by a Spring container can be "singletons" in a more narrow -__scope__: a user session, a particular UI instance associated with the session, -a view within the UI, or even just a single request. Such a context defines the -lifecycle of the object: its creation, use, and finally its destruction. - -Earlier, we introduced a user class defined as session-scoped: - - -[source, java] ----- -@SpringComponent -@VaadinSessionScope -public class User { ----- - -Now, when you need to refer to the user, you can use Spring injection to inject -the session-scoped "singleton" to a member variable or a constructor parameter; -the former in the following: - - -[source, java] ----- -public class MainView extends CustomComponent implements View { - @Autowired - User user; - - Label greeting = new Label(); - ... - - @Override - public void enter(ViewChangeEvent event) { - greeting.setValue("Hello, " + user.getName()); - } -} ----- - - - -[[advanced.spring.boot]] -== Quick Start with Vaadin Spring Boot - -The Vaadin Spring Boot is an add-on that allows for easily creating a project -that uses Vaadin Spring. It is meant to be used together with Spring Boot, which -enables general Spring functionalities in a web application. - -You can use the Spring Initializr at -link:https://start.spring.io/[start.spring.io] website to generate a project, -which you can then download as a package and import in your IDE. The generated -project is a Spring application stub; you need to add at least Vaadin -dependencies ( [literal]#++vaadin-spring-boot++#, [literal]#++vaadin-themes++#, -and [literal]#++vaadin-client-compiled++#) and a UI class to the generated -project, as well as a theme, and so forth. - -See the link:https://vaadin.com/wiki/-/wiki/Main/Vaadin+Spring[Vaadin Spring -Tutorial] for detailed instructions for using Spring Boot. - - -[[advanced.spring.installation]] -== Installing Vaadin Spring Add-on - -Vaadin Spring requires a Java EE 7 compatible servlet container, such as -Glassfish or Apache TomEE Web Profile, as mentioned for the reference toolchain -in -<<dummy/../../../framework/getting-started/getting-started-environment#getting-started.environment,"Setting -up the Development Environment">>. - -To install the Vaadin Spring and/or Vaadin Spring Boot add-ons, either define -them as an Ivy or Maven dependency or download from the Vaadin Directory add-on -page at <<,vaadin.com/directory#addon/vaadin-spring>> or -<<,vaadin.com/directory#addon/vaadin-spring-boot>>. See -<<dummy/../../../framework/addons/addons-overview.asciidoc#addons.overview,"Using -Vaadin Add-ons">> for general instructions for installing and using Vaadin -add-ons. - -The Ivy dependency is as follows: - -[subs="normal"] ----- - <dependency org="com.vaadin" name="vaadin-spring" - rev="[replaceable]#latest.release#"/> ----- -The Maven dependency is as follows: - -[subs="normal"] ----- - <dependency> - <groupId>com.vaadin</groupId> - <artifactId>vaadin-spring</artifactId> - <version>[replaceable]#LATEST#</version> - </dependency> ----- - -[[advanced.spring.peparing]] -== Preparing Application for Spring - -A Vaadin application that uses Spring must have a file named -[filename]#applicationContext.xml# in the [filename]#WEB-INF# directory. - -[subs="normal"] ----- -<?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-4.1.xsd"> - - //Configuration object - - <bean class="[replaceable]#com.example.myapp.MySpringUI.MyConfiguration#" /> - - //Location for automatically scanned beans - - <context:component-scan - base-package="[replaceable]#com.example.myapp.domain#" /> -</beans> ----- -The application should not have a servlet extending [classname]#VaadinServlet#, -as Vaadin servlet has its own [classname]#VaadinSpringServlet# that is deployed -automatically. If you need multiple servlets or need to customize the Vaadin -Spring servlet, see <<advanced.spring.deployment>>. - -You can configure managed beans explicitly in the file, or configure them to be -scanned using the annotations, which is the preferred way described in this -section. - - -[[advanced.spring.springui]] -== Injecting a UI with [classname]#@SpringUI# - -((("[classname]#@SpringUI#", id="term.advanced.spring.springui", range="startofrange"))) - - -Vaadin Spring offers an easier way to instantiate UIs and to define the URL -mapping for them than the usual ways described in -<<dummy/../../../framework/application/application-environment#application.environment,"Deploying -an Application">>. It is also needed for enabling Spring features in the UI. To -define a UI class that should be instantiated for a given URL, you simply need -to annotate the class with [classname]#@SpringUI#. It takes an optional path as -parameter. - - -[source, java] ----- -@SpringUI(path="/myniceui") -@Theme("valo") -public class MyNiceUI extends UI { - ... ----- - -The path in the URL for accessing the UI consists of the context path of the -application and the UI path, for example, [literal]#++/myapp/myniceui++#. Giving -empty UI path maps the UI to the root of the application context, for example, -[literal]#++/myapp++#. - - -[source, java] ----- -@SpringUI ----- - -See <<advanced.spring.deployment>> for how to handle servlet URL mapping of -Spring UIs when working with multiple servlets in the same web application. - -(((range="endofrange", startref="term.advanced.spring.springui"))) - -[[advanced.spring.scopes]] -== Scopes - -((("Spring", "scopes", id="term.advanced.spring.scopes", range="startofrange"))) - - -As in programming languages, where a variable name refers to a unique object -within the scope of the variable, an object has unique identity within a scope -in Spring. However, instead of identifying the objects by variable names, they -are identified by their type (object class) and any qualifiers they may have. - -The scope of an object can be defined with an annotation to the class as -follows: - - -[source, java] ----- -@VaadinSessionScope -public class User { - ... ----- - -Defining a scope in Spring is normally done with the [classname]#@Scope# -annotation. For example, [literal]#++@Scope("prototype")++# creates a new -instance every time one is requested/auto-wired. Such standard scopes can be -used with some limitations. For example, Spring session and request scopes do -not work in background threads and with certain push transport modes. - -Vaadin Spring provides three scopes useful in Vaadin applications: a session -scope, a UI scope, a view scope, all defined in the -[package]#com.vaadin.spring.annotation# package. - -[[advanced.spring.scopes.session]] -=== [classname]#@VaadinSessionScope# - -The session scope is the broadest of the custom scopes defined in Vaadin Spring. -Objects in the Vaadin session scope are unique in a user session, and shared -between all UIs open in the session. This is the most basic scope in Vaadin -applications, useful for accessing data for the user associated with the -session. It is also useful when updating UIs from a background thread, as in -those cases the UI access is locked on the session and also data should be in -that scope. - - -[[advanced.spring.scopes.ui]] -=== [classname]#@UIScope# - -UI-scoped beans are uniquely identified within a UI instance, that is, a browser -window or tab. The lifecycle of UI-scoped beans is bound between to the -initialization and closing of a UI. Whenever you inject a bean, as long as you -are within the same UI, you will get the same instance. - -Annotating a Spring view (annotated with [classname]#@SpringView# as described -later) also as [classname]#@UIScoped# makes the view retain the same instance -when the user navigates away and back to the view. - - -[[advanced.spring.scopes.view]] -=== [classname]#@ViewScope# - -The annotation enables the view scope in a bean. The lifecycle of such a bean -starts when the user navigates to a view referring to the object and ends when -the user navigates out of the view (or when the UI is closed or expires). - -Views themselves are by default view-scoped, so a new instance is created every -time the user navigates to the view. - - -(((range="endofrange", startref="term.advanced.spring.scopes"))) - -ifdef::web[] -[[advanced.spring.navigation]] -== View Navigation - -Vaadin Spring extends the navigation framework in Vaadin, described in -<<dummy/../../../framework/advanced/advanced-navigator#advanced.navigator,"Navigating -in an Application">>. It manages Spring views with a special view provider and -enables view scoping. - -[[advanced.spring.navigation.ui]] -=== Preparing the UI - -You can define navigation for any single-component container, as described in -<<dummy/../../../framework/advanced/advanced-navigator#advanced.navigator.navigating,"Setting -Up for Navigation">>, but typically you set up navigation for the entire UI -content. To use Vaadin Spring views, you need to inject a -[classname]#SpringViewProvider# in the UI and add it as a provider for the -navigator. - - -[source, java] ----- -@SpringUI(path="/myspringui") -public class MySpringUI extends UI { - @Autowired - SpringViewProvider viewProvider; - - @Override - protected void init(VaadinRequest request) { - Navigator navigator = new Navigator(this, this); - navigator.addProvider(viewProvider); - - // Navigate to start view - navigator.navigateTo(""); - } -} ----- - - -[[advanced.spring.navigation.view]] -=== The View - -A view managed by Vaadin Spring only needs to have the [classname]#@SpringView# -annotation, which registers the view in the [classname]#SpringViewProvider#. The -annotation is also necessary to enable Spring features in the view, such as -injection. - - -[source, java] ----- -@SpringView(name=MainView.NAME) -public class MainView extends CustomComponent implements View { - public static final String NAME = "main"; - ... ----- - -The annotation can have the following optional paramers: - -name (optional):: Specifies the path by which the view can be accessed programmatically and by the -URI fragment. - - -+ -[source, java] ----- -@SpringView(name="main") ----- -+ -If the view name is not given, it is derived from the class name by removing a -possible "View" suffix, making it lower case, and using a dash ("-") to separate -words originally denoted by capital letters. Thereby, a view class such as -[classname]#MyFunnyView# would have name " [literal]#++my-funny++#". - -+ -It is a recommended pattern to have the view name in a static member constant in -the view class, as was done in the example previously, so that the name can be -referred to safely. - -supportsParameters:: Specifies whether view parameters can be passed to the view as a suffix to the -name in the navigation state, that is, in the form of -[literal]#++viewname+viewparameters++#. The view name is merely a prefix and -there is no separator nor format for the parameters, but those are left for the -view to handle. The parameter support mode is disabled by default. - - -+ -[source, java] ----- -@SpringView(name="myview", supportsParameters=true) ----- -+ -You could then navigate to the state with a URI fragment such as -[literal]#++#!myview/someparameter++# or programmatically with: - - -+ -[source, java] ----- -getUI().getNavigator().navigateTo("myview/someparameter"); ----- -+ -The [methodname]#enter()# method of the view gets the URI fragment as parameter -as is and can interpret it in any application-defined way. - -+ -Note that in this mode, matching a navigation state to a view is done by the -prefix of the fragment! Thereby, no other views may start with the name of the -view as prefix. For example, if the view name is " [literal]#++main++#", you -must not have a view named " [literal]#++maintenance++#". - -uis:: If the application has multiple UIs that use [classname]#SpringViewProvider#, -you can use this parameter to specify which UIs can show the view. - - -+ -[source, java] ----- -@SpringView(name="myview", uis={MySpringUI.class}) ----- -+ -If the list contains [parameter]#UI.class#, the view is available to all UIs. - - -+ -[source, java] ----- -@SpringView(name="myview", uis={UI.class}) ----- - - -In the following, we have a login view that accesses a session-scoped user -object. Here, we use a constant to define the view name, so that we can use the -constant when navigating to it. - - -[source, java] ----- -@SpringView(name=LoginView.NAME) -public class LoginView extends CustomComponent - implements View { - public final static String NAME = ""; - - // Here we inject to the constructor and actually do - // not store the injected object to use it later - @Autowired - public LoginView(User user) { - VerticalLayout layout = new VerticalLayout(); - - // An input field for editing injected data - BeanItem<User> item = new BeanItem<User>(user); - TextField username = new TextField("User name", - item.getItemProperty("name")); - username.setNullRepresentation(""); - layout.addComponent(username); - - // Login button (authentication omitted) / Java 8 - layout.addComponent(new Button("Login", e -> - getUI().getNavigator(). - navigateTo(MainView.VIEWNAME))); - - setCompositionRoot(layout); - } - - @Override - public void enter(ViewChangeEvent event) {} -} ----- - -You could now navigate to the view from any other view in the UI with: - - -[source, java] ----- -getUI().getNavigator().navigateTo(LoginView.VIEWNAME); ----- - - -endif::web[] - -[[advanced.spring.accesscontrol]] -== Access Control - -Access control for views can be implemented by registering beans implementing -[interfacename]#ViewAccessControl# or -[interfacename]#ViewInstanceAccessControl#, which can restrict access to the -view either before or after a view instance is created. - -Integration with authorization solutions, such as Spring Security, is provided -by additional unofficial add-ons on top of Vaadin Spring. - -[[advanced.spring.accesscontrol.accessdenied]] -=== Access Denied View - -By default, the view provider acts as if a denied view didn't exist. You can set -up an "Access Denied" view that is shown if the access is denied with -[methodname]#setAccessDeniedView()# in [classname]#SpringViewProvider#. - - -[source, java] ----- -@Autowired -SpringViewProvider viewProvider; - -@Override -protected void init(VaadinRequest request) { - Navigator navigator = new Navigator(this, this); - navigator.addProvider(viewProvider); - - // Set up access denied view - viewProvider.setAccessDeniedViewClass( - MyAccessDeniedView.class); ----- - - - -[[advanced.spring.deployment]] -== Deploying Spring UIs and Servlets - -Vaadin Spring hooks into Vaadin framework by using a special -[classname]#VaadinSpringServlet#. As described earlier, you do not need to map -an URL path to a UI, as it is handled by Vaadin Spring. However, in the -following, we go through some cases where you need to customize the servlet or -use Spring with non-Spring servlets and UIs in a web application. - -[[advanced.spring.servlets.custom]] -=== Custom Servlets - -When customizing the Vaadin servlet, as outlined in -<<dummy/../../../framework/application/application-lifecycle#application.lifecycle.servlet-service,"Vaadin -Servlet, Portlet, and Service">>, you simply need to extend -[classname]#com.vaadin.spring.internal.VaadinSpringServlet# instead of -[classname]#com.vaadin.servlet.VaadinServlet#. - -[subs="normal"] ----- -@WebServlet(value = "[replaceable]#/*#", asyncSupported = true) -public class [replaceable]#MySpringServlet# extends SpringVaadinServlet { -} ----- -The custom servlet must not have [classname]#@VaadinServletConfiguration#, as -you would normally with a Vaadin servlet, as described in -<<dummy/../../../framework/application/application-environment#application.environment,"Deploying -an Application">>. - - -[[advanced.spring.deployment.urlmapping]] -=== Defining Servlet Root - -Spring UIs are managed by a Spring servlet ( [classname]#VaadinSpringServlet#), -which is by default mapped to the root of the application context. For example, -if the name of a Spring UI is " [literal]#++my-spring-ui++#" and application -context is [literal]#++/myproject++#, the UI would by default have URL " -[literal]#++/myproject/my-spring-ui++#". If you do not want to have the servlet -mapped to context root, you can use a [classname]#@WebServlet# annotation for -the servlet or a [filename]#web.xml# definition to map all Spring UIs to a -sub-path. - -For example, if we have a root UI and another: - -[subs="normal"] ----- -@SpringUI(path=[replaceable]#""#) // At Spring servlet root -public class [replaceable]#MySpringRootUI# extends UI {...} - -@SpringUI("[replaceable]#another#") -public class [replaceable]#AnotherUI# extends UI {...} ----- -Then define a path for the servlet by defining a custom servlet: - -[subs="normal"] ----- -@WebServlet(value = "[replaceable]#/myspringuis/*#", asyncSupported = true) -public class [replaceable]#MySpringServlet# extends SpringVaadinServlet { -} ----- -These two UIs would have URLs /myproject/myspringuis and -/myproject/myspringuis/another, respectively. - -You can also map the Spring servlet to another URL in servlet definition in -[filename]#web.xml#, as described the following. - - -[[advanced.spring.servlets.mixing]] -=== Mixing With Other Servlets - -The [classname]#VaadinSpringServlet# is normally used as the default servlet, -but if you have other servlets in the application, such as for non-Spring UIs, -you need to define the Spring servlet explicitly in the [filename]#web.xml#. You -can map the servlet to any URL path, but perhaps typically, you define it as the -default servlet as follows, and map the other servlets to other URL paths: - -[subs="normal"] ----- -<web-app> - ... - - <servlet> - <servlet-name>Default</servlet-name> - <servlet-class> - com.vaadin.spring.internal.VaadinSpringServlet - </servlet-class> - </servlet> - - <servlet-mapping> - <servlet-name>Default</servlet-name> - <url-pattern>[replaceable]#/myspringuis/*#</url-pattern> - </servlet-mapping> - - <servlet-mapping> - <servlet-name>Default</servlet-name> - <url-pattern>/VAADIN/*</url-pattern> - </servlet-mapping> -</web-app> ----- -With such a setting, paths to Spring UIs would have base path -[filename]#/myapp/myspringuis#, to which the (optional) UI path would be -appended. The [filename]#/VAADIN/*# only needs to be mapped to the servlet if -there are no other Vaadin servlets. - - - -(((range="endofrange", startref="term.advanced.spring.springlong"))) -(((range="endofrange", startref="term.advanced.spring.spring"))) - - |