Why do I keep obtaining a NotSerializableException for UI$Servlet class?

Why do I keep getting this NotSerializedException:

WARNING: Error in serialization of the application: Class com.example.application_lifecycle_chapter_4_7.ApplicationLifecycleUI$Servlet must implement serialization.

Dec 10, 2014 12:55:05 PM org.apache.catalina.session.StandardSession doWriteObject

WARNING: Cannot serialize session attribute com.vaadin.server.VaadinSession.AppLifeServlet for session …

Here is the code for the UI (which contains the static Servlet class):

@Theme("application_lifecycle_chapter_4_7")
@Push // setting this UI as pushable
public class ApplicationLifecycleUI extends VaadinAbstractMappableUI {




/**

     * 

     */

private static final long serialVersionUID = 1L;




@WebServlet(value = {"/AppLife/*", "/VAADIN/*"}, asyncSupported = true)

@VaadinServletConfiguration(productionMode = false, ui = ApplicationLifecycleUI.class)

public static class Servlet extends VaadinServlet 

     implements SessionInitListener, SessionDestroyListener, BootstrapListener {

        

        /**

         * 

         */

        private static final long serialVersionUID = 1L;







        // Handling Session Initialization and Destruction

        @Override 

        protected void servletInitialized() throws ServletException {

            super.servletInitialized();

            getService().addSessionInitListener(this);

            getService().addSessionDestroyListener(this);

        }

        

        

        @Override

        public void sessionInit(SessionInitEvent event) throws ServiceException {

            // Do session start stuff here

            

            // Adding the bootstrap listener to the Session

            VaadinSession.getCurrent().addBootstrapListener(this);

        }




        @Override

        public void sessionDestroy(SessionDestroyEvent event) {

            // Do session end stuff here

        }







        // Customizing the Loader Page

        @Override

        public void modifyBootstrapFragment(BootstrapFragmentResponse response) {

            

        }







        @Override

        public void modifyBootstrapPage(BootstrapPageResponse response) {

            

        }




    }




@SuppressWarnings("serial")

@Override

protected void init(VaadinRequest request) {

        final VerticalLayout layout = new VerticalLayout();

        layout.setMargin(true);

        setContent(layout);

        Button button = new Button("Click Me");

        button.addClickListener(new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {

                layout.addComponent(new Label("Thank you for clicking"));

            }

        });

        layout.addComponent(button);


        Button logoutButton = new Button("Logout");

        logoutButton.addClickListener(e -> {

            getPage().setLocation("/Application_Lifecycle_Chapter_4.7/VAADIN/logout.html");

            getSession().close();

        });

        // Setting a faster heartbeat

        //setPollInterval(3000);

        layout.addComponent(logoutButton);

    }


}

Is it because of the Button.ClickListener inside the init() UI method? Then why the exception says “ApplicationLifecycleUI$Servlet must implement serialization” and not “ApplicationLifecycleUI must implement serialization”?

Shouldn’t Vaadin handle serialization automatically as is said in the Book?

Anyway, how can I get rid of this exception?

Thank you for the attention!

Your servlet class adds itself as a BootstrapListener to the VaadinSession. This means the container will attempt to serialize it along with the session, but serializing a servlet does not really make any sense, at least not in this context. I’d advice using inner classes instead of implementing the listener interfaces directly - as it seems you’re using Java 8 you can just write the listeners as lambdas.

Thank you for answering Johannes!

I can do the inner class implementation like this:

@Override

        public void sessionInit(SessionInitEvent event) throws ServiceException {

            // Do session start stuff here

            

            // Adding the bootstrap listener to the Session

            VaadinSession.getCurrent().addBootstrapListener(new BootstrapListener() {

                

                /**

                 * 

                 */

                private static final long serialVersionUID = 1L;




                // Customizing the Loader Page

                @Override

                public void modifyBootstrapPage(BootstrapPageResponse response) {

                    // TODO Auto-generated method stub

                    

                }

                

                @Override

                public void modifyBootstrapFragment(BootstrapFragmentResponse response) {

                    // TODO Auto-generated method stub

                    

                }

            });

        }

Will it be enough to avoid the NotSerializableException?

Anyway, how can I implement BootstrapListener with lambdas expressions? It is not a functional interface (it has two methods)

Right, sorry, forgot that BootstrapListener is “special”. Also, I think that a (nonstatic) inner class, anonymous or not, won’t actually work due to the implicit reference to the containing instance, so you’ll probably need a static nested class instead.

That made it! Thanks!