123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- ---
- 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.github.io/spring-tutorial/[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.github.io/spring-tutorial/[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. Pick Vaadin as
- a dependency on the site to include all the required Vaadin Spring dependencies
- and auto-configuration.The generated project is a Spring application stub; you
- need to add at least a UI class to the generated project.
-
- See the link:https://vaadin.github.io/spring-tutorial/[Vaadin Spring
- Tutorial] for detailed instructions for using Spring Boot.
-
-
- [[advanced.spring.installation]]
- == Installing Vaadin Spring Add-on
-
- 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 link:https://vaadin.com/directory#addon/vaadin-spring[vaadin.com/directory#addon/vaadin-spring]
- or link:https://vaadin.com/directory#addon/vaadin-spring-boot[vaadin.com/directory#addon/vaadin-spring-boot].
- See <<../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>
- ----
-
- For Vaadin Spring Boot, depending on [literal]#++vaadin-spring-boot-starter++# will
- include all the required Vaadin dependencies.
-
-
- [[advanced.spring.preparing]]
- == Preparing Application for Spring
-
- A Vaadin application that uses Spring must have a file named
- [filename]#applicationContext.xml# in the [filename]#WEB-INF# directory.
- Using Spring Initializr automatically generates a suitable file, but if
- you configure Vaadin Spring manually, you can follow the model below.
-
- [subs="verbatim,replacements,quotes"]
- ----
- <?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]#SpringVaadinServlet# 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
- <<../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 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
- <<advanced-navigator#advanced.navigator,"Navigating
- in an Application">>. It manages Spring views with a special view provider and
- enables view scoping. Furthermore, Vaadin Spring provides a customized navigator class
- [classname]#SpringNavigator# that supports the scope functionality.
-
-
- [[advanced.spring.navigation.ui]]
- === Preparing the UI
-
- You can define navigation for any single-component container, component container or bean
- implementing [classname]#ViewDisplay#, as described in
- <<advanced-navigator#advanced.navigator.navigating,"Setting
- Up for Navigation">>, but typically you set up navigation for the entire UI
- content. The easiest way to set up navigation is to use the annotation
- [classname]#@SpringViewDisplay# on the UI (in which case the whole contents of the UI are
- replaced on navigation) or on any UI scoped bean implementing one of the above mentioned
- interfaces.
-
-
- [source, java]
- ----
- @SpringUI(path="/myspringui")
- @SpringViewDisplay
- public class MySpringUI extends UI {
- @Override
- protected void init(VaadinRequest request) {
- }
- }
- ----
-
- If not using Spring Boot, auto-configuration of navigation can be enabled with the annotation
- @EnableVaadinNavigation on a configuration class.
-
-
- [[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.
-
- +
- You can also navigate to a view 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.
-
- 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
-
- If access to a view is denied by an access control bean, the access denied view
- is shown for it. For non-existing views, the error view is shown. You can set
- up an "Access Denied" view that is shown if the access is denied with
- [methodname]#setAccessDeniedViewClass()# in [classname]#SpringViewProvider#,
- and an error view with [methodname]#setErrorView()# in [classname]#SpringNavigator#.
- The same view can also be used both as an access denied view and as an error
- view to hide the existence of views the user is not allowed to access.
-
-
- [source, java]
- ----
- @Autowired
- SpringViewProvider viewProvider;
- @Autowired
- SpringNavigator navigator;
-
- @Override
- protected void init(VaadinRequest request) {
- // Set up access denied view
- viewProvider.setAccessDeniedViewClass(
- MyAccessDeniedView.class);
- // Set up error view
- navigator.setErrorView(MyErrorView.class);
- ----
-
- Note that the error view can also be a class with which an error view bean is
- found. In this case, the error view must be UI scoped.
-
-
- [[advanced.spring.deployment]]
- == Deploying Spring UIs and Servlets
-
- Vaadin Spring hooks into Vaadin framework by using a special
- [classname]#SpringVaadinServlet#. 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
- <<../application/application-lifecycle#application.lifecycle.servlet-service,"Vaadin
- Servlet, Portlet, and Service">>, you simply need to extend
- [classname]#com.vaadin.spring.server.SpringVaadinServlet# 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
- <<../application/application-environment#application.environment,"Deploying
- an Application">>.
-
-
- [[advanced.spring.deployment.urlmapping]]
- === Defining Servlet Root
-
- Spring UIs are managed by a Spring servlet ( [classname]#SpringVaadinServlet#),
- 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]#SpringVaadinServlet# 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.server.SpringVaadinServlet
- </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")))
|