0

I'm having some trouble integrating Vaadin with my Spring application. I have all my beans in the "rootcontext.xml" file. I can call the beans by instantiating the "rootcontext.xml" then calling the bean for one of my service classes.

I can populate the table this way but is this the right way of calling the service class? Because I have more tables that have to call this.

public final class TestTable extends Table {

private ApplicationContext applicationContext = (ApplicationContext) VaadinServlet.getCurrent().getServletContext()
        .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

private Service service = this.applicationContext.getBean("service",
        Service.class);

public TestTable() {
    service.findAll()
}

Here is my UI class:

@SpringUI
@Theme("dashboard")
@Widgetset("vaadin.DashboardWidgetSet")
public class TestUI extends UI {

/**
 * 
 */
private static final long serialVersionUID = -620721219079395670L;

private final DashboardEventBus dashboardEventbus = new DashboardEventBus();

@Override
protected void init(VaadinRequest request) {

    setLocale(Locale.US);

    DashboardEventBus.register(this);
    Responsive.makeResponsive(this);
    addStyleName(ValoTheme.UI_WITH_MENU);

    updateContent();

    // Some views need to be aware of browser resize events so a
    // BrowserResizeEvent gets fired to the event bus on every occasion.
    Page.getCurrent().addBrowserWindowResizeListener(new BrowserWindowResizeListener() {
        @Override
        public void browserWindowResized(final BrowserWindowResizeEvent event) {
            DashboardEventBus.post(new BrowserResizeEvent());
        }
    });
}

private void updateContent() {
    setContent(new MainView());
}

@WebServlet(urlPatterns = { "/TestUI/*", "/VAADIN/*" }, name = "TestUIServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = TestUI.class, productionMode = false)
public static class TestUIServlet extends VaadinServlet {

}
}

My root-context.xml file is in the directory /WEB-INF/spring/root-context.xml.

The applicationContext.xml for the Vaadin servlet is in the directory /WEB-INF/spring/vaadin/applicationContext.xml.

And here is my web.xml. The Vaadin Spring tutorial says to use the context loader to initialize 'applicationContext.xml'. I could add its path to the contextConfigLocation param but there should only be one root context.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
</web-app>

Vaadin Configuration class:

import org.springframework.context.annotation.Configuration;

import com.vaadin.spring.annotation.EnableVaadin;

@Configuration
@EnableVaadin
public class VaadinConfiguration {

@Autowired
private Service service;

@Bean
public UI ui() {
    System.out.println(service.findAll().size());

    TestUI testUI = new TestUI();

    testUI.setService(service);

    return testUI;
}
}
codeCooker
  • 145
  • 2
  • 14
  • 1
    Did you get the chance to go over the newer [Vaadin-spring tutorial](http://vaadin.github.io/spring-tutorial/) or the older [wiki section](https://vaadin.com/wiki/-/wiki/Spring+Vaadin/I+-+Getting+Started+with+Vaadin+Spring+and+Spring+Boot)? To keep it clean the table should just display data, _someone_ else should call the service and provide (populate) the information to the table – Morfic May 18 '17 at 21:40
  • @Morfic Hey thanks for the response. I did go through the tutorial. If I already had a rootcontext.xml, do i still need to create an applicationContext.xml like the tutorial says? – codeCooker May 24 '17 at 15:59
  • Any spring or vaadin experts out there? – codeCooker May 25 '17 at 20:31
  • 1
    `applicationContext.xml` is a common name used for XML-defined spring context, but you can name it whatever you want, so no, if you already have your `rootcontext.xml` you don't need to create the other one. One thing you could try, is to migrate to annotation based contexts. By no means that's necessary and it's a personal preference, but I find it more helpful to view info while writing my code than having to go to the XML definition, even if nowadays IDEs have good spring support for such things. – Morfic May 29 '17 at 08:08
  • @Morfic I would like to separate the configuration. Use the root-context.xml as my datasource configurations and have my vaadin configuration in its own xml. But when I try to autowire the service classes from the root I just keep getting null pointer exceptions. – codeCooker May 30 '17 at 15:37
  • 1
    From your comment I assume you're instantiating 2 different spring contexts. Usually there's one such context that contains all the bean definitions so it can inject them properly when required (unless you need a [hierarchy](https://stackoverflow.com/questions/43452644/what-is-the-difference-between-spring-parent-context-and-child-context)). With 2 distinct contexts, one won't know about what's in the other. What you could do, is to [split it into smaller parts and import them in your root context](https://stackoverflow.com/questions/600095/splitting-applicationcontext-to-multiple-files). – Morfic May 30 '17 at 15:51
  • @Morfic I appreciate the help. In my configuration class which is use Java based configuration like the Vaadin spring tutorial. If I autowire one of my service classes from the root context and create a bean inside of the configuration class it works. I do a system out and I see a value. But when I actually inject it and do the system out from the created bean I get a null pointer exception. It's really frustrating. – codeCooker May 30 '17 at 18:11
  • @Morfic I updated the question to show my configuration class. Thanks again for the help – codeCooker May 30 '17 at 18:14
  • 1
    Leave it as it is, with `root-context` referenced in `web.xml`, and import your `applicationContext` in your `root-context` as described in the [previous link about splitting a context](https://stackoverflow.com/questions/600095/splitting-applicationcontext-to-multiple-files). If I were you, I'd fully migrate to an annotation-based context (you already have a few such beans and configs), and not worry about XMLs any more. Spring boot or not it's up to you, and the [vaadin tutorial](http://vaadin.github.io/spring-tutorial) should offer sufficient info about how to bootstrap it and use it. – Morfic May 31 '17 at 07:23
  • 1
    You can also get some inspiration from their simple [vaadin-spring integration demo app](https://github.com/vaadin/spring-tutorial), based on spring boot. – Morfic May 31 '17 at 07:28
  • @Morfic OK, I think that's the annotation based is the route I'll go. Thanks again! – codeCooker May 31 '17 at 17:09

1 Answers1

1

One of the issues I realized was that I was using the wrong version for Vaadin Spring. I was using Vaadin Spring 2.0 but it doesn't work with Vaadin 7. So I switched it to 1.2.

    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-spring</artifactId>
        <version>1.2.0</version>
    </dependency>

And I moved the Spring Vaadin Servlet configuration to my web.xml

<servlet>
    <servlet-name>UIServlet</servlet-name>
    <servlet-class>com.vaadin.spring.server.SpringVaadinServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>UIServlet</servlet-name>
    <url-pattern>/UI/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>UIServlet</servlet-name>
    <url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>

I also had to add some Vaadin Spring annotations to the configuration class and UI class.

@Configuration
@EnableVaadin
@EnableVaadinNavigation
public class VaadinConfiguration {

}

@EnableVaadinNavigation is needed to enable Navigation for Spring Views.

@SpringUI
@Theme("dashboard")
public class UI extends UI {

@Autowired
private SpringViewProvider viewProvider;

private final HorizontalLayout root = new HorizontalLayout();
private ComponentContainer content;
private Navigator navigator;

@Override
protected void init(VaadinRequest request) {

    setLocale(Locale.US);

    Responsive.makeResponsive(this);
    addStyleName(ValoTheme.UI_WITH_MENU);

    root.setSizeFull();
    root.addStyleName("mainview");
    setContent(root);

    root.addComponent(new DashboardMenu());

    content = new CssLayout();
    content.addStyleName("view-content");
    content.setSizeFull();
    root.addComponent(content);
    root.setExpandRatio(content, 1.0f);

    navigator = new Navigator(this, content);
    navigator.addProvider(viewProvider);
    navigator.navigateTo(DashboardView.NAME);
}
}

I autowired SpringViewProvider in the UI which is also needed to recognize your classes that are annotated with Spring View.

All the configuration can be found here:

https://vaadin.com/wiki/-/wiki/Spring+Vaadin/I+-+Getting+Started+with+Vaadin+Spring+and+Spring+Boot

codeCooker
  • 145
  • 2
  • 14