Spring-boot vaadin converted to war file

Hi,
Referring to the webinar on spring-vaadin last month, I found the topic about the “spring-boot vaadin” very interesting. I tried to use this spring-boot-vaadin program with mysql and bonecp included. It worked.

I tired to convert it to war filile. I modified the Spring application minus spring-boot. I lincluded @VaadinUI. Compile went well and I exported war file to Tomcat. The error came outas below;

Vaadin is running in DEBUG MODE.
Add productionMode=true to web.xml to disable debug features.
To show debug window, add ?debug to your application URL.

10-Feb-2014 09:57:50.718 SEVERE [http-nio-8085-exec-3]
null.null
java.lang.NullPointerException
at za.co.bcx.SecurityApplication.refresh(SecurityApplication.java:92)
at za.co.bcx.SecurityApplication.init(SecurityApplication.java:87)
at com.vaadin.ui.UI.doInit(UI.java:614)
at com.vaadin.server.communication.UIInitHandler.getBrowserDetailsUI(UIInitHandler.java:223)
at com.vaadin.server.communication.UIInitHandler.synchronizedHandleRequest(UIInitHandler.java:73)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:37)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1382)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:238)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:221)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:107)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:76)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:934)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:90)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:646)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1576)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1534)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)

It appeared that the spring did not talk to vaadin. I have highlighted the prgram which returned NullPionterException below. What did I miss?

Regards,

Michael

Here is the programs as below;

File: SecurityApplication.java

@VaadinUI
public class SecurityApplication extends UI {

public static final String BEAN_ID = "idxId";

public static final Object NATURAL_COL_ORDER = new Object {BEAN_ID, "username", "enabled", "createdD"};

public static final String COL_HEADERS_ENGLISH = new String {"User Id", "Username", "Enabled", "Created date"};

@Autowired
UsersRepository repository;
private BeanItemContainer<Users> usersContainer;
private Table usersTable;
private Button refresh;
private Button add;

private Users users = new Users();

@Override
protected void init(VaadinRequest request) {
    VerticalLayout layout = new VerticalLayout();
    layout.setSizeFull();
    layout.setMargin(true);
    layout.setSpacing(true);
    setContent(layout);

    Label title = new Label("Users");
    title.addStyleName(Reindeer.LABEL_H1);
    layout.addComponent(title);
    usersContainer = new BeanItemContainer<>(Users.class);
    usersTable = new Table();
    usersTable.setSizeFull();
    usersTable.setContainerDataSource(usersContainer);
    usersTable.setVisibleColumns(NATURAL_COL_ORDER);
    usersTable.setColumnHeaders(COL_HEADERS_ENGLISH);

    layout.addComponent(usersTable);
    layout.setExpandRatio(usersTable, 1f);

    HorizontalLayout toolbar = new HorizontalLayout();
    toolbar.setSpacing(true);
    layout.addComponent(toolbar);

    refresh = new Button("Refresh", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            refresh();
        }
    });
    toolbar.addComponent(refresh);

    add = new Button("Add...", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            addWindow(new NewUsersWindow());
        }
    });
    toolbar.addComponent(add);

    refresh();
}

private void refresh() {
    usersContainer.removeAllItems();


usersContainer.addAll(repository.findAll()); //Return java.lang.NullPointerException

}

class NewUsersWindow extends Window {

    private TextField firstName = new TextField("User name");
    private TextField lastName = new TextField("Enabled");

    private Button commit = new Button("Save & Close", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            repository.saveAndFlush(newUsers);
            close();
            refresh();
        }
    });

    private Users newUsers = new Users();

    public NewUsersWindow() {
        setCaption("Add new users");
        setModal(true);
        setResizable(false);

        // Build layout containing fields and button
        FormLayout form = new FormLayout(firstName, lastName);
        VerticalLayout verticalLayout = new VerticalLayout(form, commit);
        verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
        setContent(verticalLayout);

        // Bind fields to entity properties by naming convention
        BeanFieldGroup<Users> binder = new BeanFieldGroup<>(Users.class);
        binder.setBuffered(false);
        binder.bindMemberFields(NewUsersWindow.this);
        binder.setItemDataSource(newUsers);

        // Automatically focus the firsName field
        firstName.focus();

    }

}

}

File: DataConfiguration.java

@Configuration
@ComponentScan(basePackages = “za.co.bcx”)
@EnableJpaRepositories(basePackages = “za.co.bcx.repositories”)
@EnableTransactionManagement
@PropertySource(“classpath:database.properties”)
public class DataConfiguration {

@Autowired
private Environment env;

@Bean
public BoneCPDataSource dataSource() {
    BoneCPDataSource dataSource = new BoneCPDataSource();
    dataSource.setDriverClass(env.getRequiredProperty("database.driverClassName"));
    dataSource.setJdbcUrl(env.getRequiredProperty("database.url"));
    dataSource.setUsername(env.getRequiredProperty("database.username"));
    dataSource.setPassword(env.getRequiredProperty("database.password"));

    dataSource.setAcquireIncrement(Integer.parseInt(env.getRequiredProperty("bone.acquireIncrement")));
    dataSource.setCloseConnectionWatch(Boolean.parseBoolean(env.getRequiredProperty("bone.closeConnectionWatch")));
    dataSource.setMaxConnectionsPerPartition(Integer.parseInt(env.getRequiredProperty("bone.maxConnectionsPerPartition")));
    dataSource.setMinConnectionsPerPartition(Integer.parseInt(env.getRequiredProperty("bone.minConnectionsPerPartition")));
    dataSource.setPartitionCount(Integer.parseInt(env.getRequiredProperty("bone.partitionCount")));

    return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setDatabase(Database.valueOf(env.getRequiredProperty("jpa.dialect")));
    //vendorAdapter.setGenerateDdl(Boolean.parseBoolean(env.getRequiredProperty("jpa.setgeneratedll")));

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("za.co.bcx");
    factory.setDataSource(dataSource());

    Properties jpaProperty = new Properties();
    jpaProperty.put("hibernate.archive.autodetection", env.getRequiredProperty("hibernate.archive.autodetection"));
    jpaProperty.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
    jpaProperty.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
    jpaProperty.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
    jpaProperty.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
    jpaProperty.put("hibernate.use_sql_comments", env.getRequiredProperty("hibernate.use_sql_comments"));

    factory.setJpaProperties(jpaProperty);

    factory.afterPropertiesSet();

    return factory;
}

@Bean
public PlatformTransactionManager transactionManager() {
    return new JpaTransactionManager();
}

}

File: SecurityDashboardWebApplication.java

public class SecurityDashboardWebApplication implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext();
    rootCtx.register(DataConfiguration.class);
    rootCtx.refresh();

    servletContext.addListener(new ContextLoaderListener(rootCtx));

    ServletRegistration.Dynamic vaadinServlet = servletContext.addServlet("SecurityApplication", new VaadinServlet());
    vaadinServlet.addMapping("/*");
    vaadinServlet.setInitParameter("UI", "za.co.bcx.SecurityApplication");
    vaadinServlet.setInitParameter("productionMode", "false");

    servletContext.addListener(new RequestContextListener());
  }

}

Hi,

First, I think in order to use Spring Boot you have to enable @EnableAutoConfiguration as described here :

@EnableAutoConfiguration
@ComponentScan
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

Anyway there’s a problem with your configuration. Your SecurityDashboardWebApplication is using VaadinServlet, but you need to use SpringAwareVaadinServlet.

Finally, if you enable VaadinAutoConfiguration, your servlet is already self-registered so you don’t need to do this :

ServletRegistration.Dynamic vaadinServlet = servletContext.addServlet("SecurityApplication", new VaadinServlet());
        vaadinServlet.addMapping("/*");
        vaadinServlet.setInitParameter("UI", "za.co.bcx.SecurityApplication");
        vaadinServlet.setInitParameter("productionMode", "false");

You can find an example without Spring Boot (if you want to keep control on your config.) here :
https://github.com/peholmst/vaadin4spring/issues/19


Problem solved.

I read the article on “Converting a Spring Boot JAR Application to a WAR”. (http://spring.io/guides/gs/convert-jar-to-war/)

I decided to follow what the above article described

First, I ran the program with the spring-boot and the thymleaf to make sure it worked. When I compiled the program into the war file and deployed to Tomcat server, it would not work. It complained about tomcat-embedded clashing with the tomcat server. Note that I used a gradle script to compile into the war file;
compile(“org.springframework.boot:spring-boot-starter-web:1.0.0.RC1”) {
exclude group: ‘org.springframework.boot’, module: ‘spring-boot-starter-tomcat’
}
Remember that it would not work without the javax.servlet e.g. compile(“javax.servlet:javax.servlet-api:3.1.0”).
I deployed to the tomcat server and it worked.

Then I added spring-boot-vaadin and spring-vaadin plugin to the spring-boot program minus thymleaf. It also worked well as well. Please have a look at files as below; (Note that I have highlighted in bold letters)

Application.java


@Configuration
@EnableAutoConfiguration
@ComponentScan

public class Application {

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

}


@VaadinUI

class SecurityVaadin extends UI {

public static final String BEAN_ID = "idxId";

public static final Object[] NATURAL_COL_ORDER = new Object[]

{BEAN_ID, “username”, “enabled”, “createdD”};

public static final String[] COL_HEADERS_ENGLISH = new String[]

{“User Id”, “Username”, “Enabled”, “Created date”};

@Autowired
UsersRepository usersService;

private BeanItemContainer<Users> usersContainer;
private Table usersTable;
private Button refresh;
private Button add;

private Users users = new Users();

@Override
protected void init(VaadinRequest request) {
    VerticalLayout layout = new VerticalLayout();
    layout.setSizeFull();
    layout.setMargin(true);
    layout.setSpacing(true);
    setContent(layout);

    Label title = new Label("Users");
    title.addStyleName(Reindeer.LABEL_H1);
    layout.addComponent(title);
    usersContainer = new BeanItemContainer<>(Users.class);
    usersTable = new Table();
    usersTable.setSizeFull();
    usersTable.setContainerDataSource(usersContainer);
    usersTable.setVisibleColumns(NATURAL_COL_ORDER);
    usersTable.setColumnHeaders(COL_HEADERS_ENGLISH);

    layout.addComponent(usersTable);
    layout.setExpandRatio(usersTable, 1f);

    HorizontalLayout toolbar = new HorizontalLayout();
    toolbar.setSpacing(true);
    layout.addComponent(toolbar);

    refresh = new Button("Refresh", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            refresh();
        }
    });
    toolbar.addComponent(refresh);

    add = new Button("Add...", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            addWindow(new NewUsersWindow());
        }
    });
    toolbar.addComponent(add);

    refresh();
}

private void refresh() {
    usersContainer.removeAllItems();
    usersContainer.addAll(usersService.findAll());
}

class NewUsersWindow extends Window {

    private TextField firstName = new TextField("User name");
    private TextField lastName = new TextField("Enabled");

    private Button commit = new Button("Save & Close", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            //usersService.saveAndFlush(newUsers);
            close();
            refresh();
        }
    });

    private Users newUsers = new Users();

    public NewUsersWindow() {
        setCaption("Add new users");
        setModal(true);
        setResizable(false);

        // Build layout containing fields and button
        FormLayout form = new FormLayout(firstName, lastName);
        VerticalLayout verticalLayout = new VerticalLayout(form, commit);
        verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
        setContent(verticalLayout);

        // Bind fields to entity properties by naming convention
        BeanFieldGroup<Users> binder = new BeanFieldGroup<>(Users.class);
        binder.setBuffered(false);
        binder.bindMemberFields(NewUsersWindow.this);
        binder.setItemDataSource(newUsers);

        // Automatically focus the firsName field
        firstName.focus();

    }

}

}

HelloWebXml.java

public class HelloWebXml extends SpringBootServletInitializer {

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
}

}

DataConfiguration.java

@Configuration

@EnableVaadin

@ComponentScan(basePackages = “za.co.bcx”)
@EnableJpaRepositories(basePackages = “za.co.bcx.repositories”)
@EnableTransactionManagement
@PropertySource(“classpath:database.properties”)
public class DataConfiguration {

@Autowired
private Environment env;

@Bean
public BoneCPDataSource dataSource() {
    BoneCPDataSource dataSource = new BoneCPDataSource();
    dataSource.setDriverClass(env.getRequiredProperty("database.driverClassName"));
    dataSource.setJdbcUrl(env.getRequiredProperty("database.url"));
    dataSource.setUsername(env.getRequiredProperty("database.username"));
    dataSource.setPassword(env.getRequiredProperty("database.password"));

    dataSource.setAcquireIncrement(Integer.parseInt(env.getRequiredProperty("bone.acquireIncrement")));
    dataSource.setCloseConnectionWatch(Boolean.parseBoolean(env.getRequiredProperty("bone.closeConnectionWatch")));
    dataSource.setMaxConnectionsPerPartition(Integer.parseInt(env.getRequiredProperty("bone.maxConnectionsPerPartition")));
    dataSource.setMinConnectionsPerPartition(Integer.parseInt(env.getRequiredProperty("bone.minConnectionsPerPartition")));
    dataSource.setPartitionCount(Integer.parseInt(env.getRequiredProperty("bone.partitionCount")));

    return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setDatabase(Database.valueOf(env.getRequiredProperty("jpa.dialect")));
    //vendorAdapter.setGenerateDdl(Boolean.parseBoolean(env.getRequiredProperty("jpa.setgeneratedll")));

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("za.co.bcx");
    factory.setDataSource(dataSource());

    Properties jpaProperty = new Properties();
    jpaProperty.put("hibernate.archive.autodetection", env.getRequiredProperty("hibernate.archive.autodetection"));
    jpaProperty.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
    jpaProperty.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
    jpaProperty.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
    jpaProperty.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
    jpaProperty.put("hibernate.use_sql_comments", env.getRequiredProperty("hibernate.use_sql_comments"));

    factory.setJpaProperties(jpaProperty);

    factory.afterPropertiesSet();

    return factory;
}

@Bean
public PlatformTransactionManager transactionManager() {
    return new JpaTransactionManager();
}

}

Hi,

This branch of the example has a setup that makes deployable war files:
https://github.com/peholmst/vaadin4spring/tree/war-file-for-servletcontainers

As above, the trick is to have SpringBootServletInitializer and exclude some embedded tomcat/jetty jar files.

cheers,
matt

Thanks. It looks much better. Less hard coding.

I am testing your vaadin-spring security. Will let you know if there are any errors,bugs,etc.

Looking forward to the final release.

Michael