0. Introduction
We need to store information in sessions. This can be achieved basically in 2 ways:
- Adding attributes to the session. The session has a map of attributes.
- Using session-scoped beans. Using CDI is a good choice.
1. Adding parameters to the Session.
As seen in the previous post, the session can be accessed. Here is an example of accessing the session and getting or setting an attribute. The utility class "VaadinUtils" is used. The attribute has a name and an object type value.
1 2 3 4 5 6 7 8 9 10 11 | package stuff; import openadmin.utils.VaadinUtils; public class TestAttributes { public static void main(String[] args) { VaadinUtils.setSessionAttribute("CONNECTED_USER", "Ximo"); System.out.println(VaadinUtils.getSessionAttribute("CONNECTED_USER").toString()); } } |
It is necessary knowing who is the connected user. So a session attribute whose name is "CONNECTED_USER" will be created. This attribute will be used to allow or deny the user to use the application.
2. Using CDI and session-scoped beans
To use CDI in Vaadin let's follow these 4 steps:
2.1 Create a class that extends CdiVaadinServlet
This class is informing about:
- The use of CDI (as it extends CdiVaadinServlet instead of VaadinServlet)
- The class that manages the i18n (internationalization) of the application. We will review this step later in another post.
- If the production mode is activated (by means of annotations)
Her is the code (in the "openadmin.listeners" package)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package openadmin.listeners; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import com.vaadin.cdi.CdiVaadinServlet; import com.vaadin.flow.server.Constants; //import com.vaadin.flow.server.VaadinServlet; import com.vaadin.flow.server.VaadinServletConfiguration; /** * Information about app servlet * * Necessary for defining i18n Provider * @author ximo * */ @SuppressWarnings("serial") @WebServlet( urlPatterns = "/*", name = "slot", asyncSupported = true, initParams = { // I18N Provider for translation of labels @WebInitParam( name = Constants.I18N_PROVIDER, value = "openadmin.i18n.MyI18nProvider") }) @VaadinServletConfiguration(productionMode = false) //public class ApplicationServlet extends VaadinServlet { public class ApplicationServlet extends CdiVaadinServlet { } |
Note that:
- The class only informs. No procedures are defined.
- The class "openadmin.i18n.MyI18nProvider" is the class that manages "i18n".
- The @VaadinServletConfiguration annotations is used to inform that we are not in production mode.
- If no CDI is used, then this class should extend "VaadinServlet".
2.2 Create a the session-scoped bean
Now a simple class with only one attribute is created as an example. Note that attributes will be added in the future. Note that:- CDI specific annotations (@Named and @SessionScoped) are no longer compatible. The @VaadinSessionScoped is used instead!
- To avoid "NullPointerException" when accessing the injected instance of this class, a method annotated with @PostConstruct and this method should initialize information of the class. This method is used to remove the "CONNECTED_USER" attribute from the session.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package openadmin.session; import javax.annotation.PostConstruct; //import javax.enterprise.context.SessionScoped; //import javax.inject.Named; import com.vaadin.cdi.annotation.VaadinSessionScoped; import openadmin.utils.VaadinUtils; import lombok.Getter; import lombok.Setter; //@Named @SessionScoped @VaadinSessionScoped public class SessionData { @Getter @Setter private String something=null; @PostConstruct private void init() { something="something else!"; System.out.println("SessionData.init() called."); // Remove the session attribute that informs the user, if exists VaadinUtils.getWrappedSession().removeAttribute("CONNECTED_USER"); } } |
2.3 Inject the session bean into another class
Here is the sample code using the @Inject annotation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package openadmin.ui; import javax.inject.Inject; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; import com.vaadin.flow.server.PWA; import openadmin.session.SessionData; /** * The main view contains a button and a click listener. */ @SuppressWarnings("serial") @Route("") @PWA(name = "Project Base for Vaadin Flow", shortName = "Project Base") public class MainForm extends VerticalLayout { @Inject private SessionData mySesData; public MainForm() { mySesData.setSomething("Something again"); var button = new Button("Click me. Right Now!", event -> Notification.show("Clicked! Silly Boy v.04.1" + mySesData.getSomething())); add(button); } } |
2.4 Create the file beans.xml
Follow these steps:
- In Eclipse go to "Deployed Resources" folder
- Go to "webapp" folder
- Create the "WEB-INF" folder if not exists
- Create the empty file beans.xml
Hello.
ResponderEliminarThanks for the article.
Using Vaadin 14 with spring boot, SessionData class annotations only worked with @Named and @VaadinSessionScope, without @Named spring returns error.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'br.com.....view.ListaTrabalhosView': Unsatisfied dependency expressed through field 'mySesData'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'br.com....spring.SessionData' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.inject.Inject()}
I am not very good at this matter. I am avoiding to use Spring as it has too many dependencies. So I use Vaadin with a simple Tomcat and WELD CDI as CDI provider and it works. Now I am migrating to Vaadin 14 and there are some changes. I will get you informed.
ResponderEliminar