2

Vaadin 团队目前发布了一个插件,据我了解,它基于非官方的 Vaadin4Spring 插件:

Vaadin Spring Boot: https ://vaadin.com/directory#addon/vaadin-spring-boot

Vaadin4Spring: https ://github.com/peholmst/vaadin4spring

请注意!截至 2015 年 2 月,Vaadin 正在开发一个官方 Spring 附加组件,该附加组件将是 Vaadin4Spring 的一个小子集。官方插件发布后,Vaadin4Spring 将转换为一组插件,提供官方插件不具备的功能。你可以在这里关注官方插件的进度: https ://github.com/vaadin/spring

然而,Vaadin Spring Boot 缺少 Vaadin4Spring 所具有的一些很酷的特性(就像上面 Vaadin4Spring 的作者 Petter Holmström 所说的那样),比如非常有用的 EventBus 框架。

现在我已经使用 Vaadin Spring Boot 插件和 Vaadin4Spring 插件建立了一个 Maven 项目:

    <!-- Vaadin Spring Boot -->
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-spring-boot</artifactId>
        <version>${vaadin.spring.boot.version}</version>
    </dependency>

基本上,我想使用这两个框架的功能(或者更好,我想用Vaadin Spring Boot作主框架并Vaadin4Spring EventBus与它一起使用这些功能)。然而,我注意到的问题是,这两个框架似乎还不能相互共存。

如果我像上面一样添加两个插件,当我运行应用程序时,找不到任何视图和 UI(在日志下方显示我的意思):

2015-03-01 22:07:22.001... SpringViewProvider: Looking up VaadinViews 
2015-03-01 22:07:22.006  WARN SpringViewProvider: No VaadinViews found ... 
...
2015-03-01 22:12:12.584  INFO: Checking the application context for Vaadin UIs 
2015-03-01 22:12:12.594  WARN: Found no Vaadin UIs in the application context

但是视图和用户界面确实存在!它们由Vaadin Spring Boot插件管理(这里是一些示例代码):

用户界面:

@SpringUI("")
@Theme("valo")
public class DemoUI extends UI {

    private static final long serialVersionUID = 193481619798227053L;

    @Autowired
    private Greeter greeter;

    @Autowired
    private ApplicationContext applicationContext;

    private final SpringViewProvider viewProvider;

    private VerticalLayout layout;

    @Autowired
    public DemoUI(SpringViewProvider viewProvider) {
        this.viewProvider = viewProvider;
    }

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

        Label greetings = new Label(greeter.getGreeting());
        layout.addComponent(greetings);

        final CssLayout navigationBar = new CssLayout();
        navigationBar.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
        navigationBar.addComponent(createNavigationButton("View Scoped View", ViewScopedView.VIEW_NAME));
        navigationBar.addComponent(createNavigationButton("UI Scoped View", UIScopedView.VIEW_NAME));
        navigationBar.addComponent(createNavigationButton("Another UI Scoped View", AnotherUIScopedView.VIEW_NAME));
        layout.addComponent(navigationBar);     

        final Panel viewContainer = new Panel();
        viewContainer.setSizeFull();
        layout.addComponent(viewContainer);
        layout.setExpandRatio(viewContainer, 1.0f);

        Navigator navigator = new Navigator(this, viewContainer);
        navigator.addProvider(viewProvider);



    }

    private Button createNavigationButton(String caption, String viewName) {
        Button button = new Button(caption);
        button.addStyleName(ValoTheme.BUTTON_SMALL);
        button.addClickListener(event -> { 
            try {
                getUI().getNavigator().navigateTo(viewName);
            }
            catch (IllegalArgumentException e) {
                // view with the given name is not mapped
                System.out.println("Not mapped view with name: " + viewName);
            }
        });
        return button;
    }

}

使用@SpringView 注释的视图:

@SpringView(DefaultView.VIEW_NAME)
public class DefaultView extends VerticalLayout implements View {

    private static final long serialVersionUID = -2052937117362922764L;

    public static final String VIEW_NAME = "";

    @Override
    public void enter(ViewChangeEvent event) {
         // the view is constructed in the init() method()      
    }

    @PostConstruct
    void init() {
        addComponent(new Label("This is the default view"));
    }

}

其他观点也是如此。当从 pom.xml 中删除这两个依赖项时,一切正常:

    <!-- Vaadin4Spring addon, the EventBus framework needs this addon -->
    <dependency>
        <groupId>org.vaadin.spring</groupId>
        <artifactId>spring-boot-vaadin</artifactId>
        <version>0.0.5-SNAPSHOT</version>
    </dependency>
    <!-- Vaadin4Spring EventBus feature I would like to use with Vaadin Spring Boot -->
    <dependency>
        <groupId>org.vaadin.spring</groupId>
        <artifactId>spring-vaadin-eventbus</artifactId>
        <version>0.0.5-SNAPSHOT</version>
    </dependency>

不允许我使用 EventBus 框架。有没有人也已经探索过这个新插件并且有同样的需求?你有没有发现如何整合这两个世界?还是将 Vaadin4Spring 工具用于 Vaadin Spring Boot 还为时过早,我们应该等待 Vaadin4Spring 功能转换为一组插件,这些插件将Vaadin Spring Boot按照我发布的第一个块中所述完成?

编辑:我还尝试在将@ComponentScan三个依赖项放在一起的同时向 Spring Boot 应用程序类添加注释,但没有帮助......

如果我添加spring-vaadin而不是spring-boot-vaadin

        <!-- Vaadin4Spring -->
        <dependency>
            <groupId>org.vaadin.spring</groupId>
            <artifactId>spring-vaadin</artifactId>
            <version>${vaadin4spring.version}</version>
        </dependency>
        <!-- Vaadin4Spring EventBus framework -->
        <dependency>
            <groupId>org.vaadin.spring</groupId>
            <artifactId>spring-vaadin-eventbus</artifactId>
            <version>${vaadin4spring.version}</version>
        </dependency>

视图和 UI 已加载,我可以在浏览器中看到它们,但是一旦我想开始使用事件总线,就会出现以下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'vaadinSpringBootDemoApplication': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.vaadin.spring.events.EventBus$ApplicationEventBus demo.VaadinSpringBootDemoApplication.applicationEventBus; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.vaadin.spring.events.EventBus$ApplicationEventBus] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at demo.VaadinSpringBootDemoApplication.main(VaadinSpringBootDemoApplication.java:21)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.vaadin.spring.events.EventBus$ApplicationEventBus demo.VaadinSpringBootDemoApplication.applicationEventBus; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.vaadin.spring.events.EventBus$ApplicationEventBus] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 16 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.vaadin.spring.events.EventBus$ApplicationEventBus] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 18 common frames omitted

似乎 EventBus.* bean 没有在 Spring IoC 容器中注册。该怎么办?

4

3 回答 3

2

问题是VaadinSessionScope尚未在官方 spring4vaadin 中实现。您需要创建非官方 spring4vaadin 的 bean。

你的 pom 文件:

<!-- Official Vaadin4Spring -->
<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-spring</artifactId>
    <version>${vaadin.spring.version}</version>
</dependency>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-spring-boot</artifactId>
    <version>${vaadin.spring.boot.version}</version>
</dependency>
<!-- Unofficial Vaadin4Spring -->
<dependency>
    <groupId>org.vaadin.spring</groupId>
    <artifactId>spring-vaadin</artifactId>
    <version>${vaadin4spring.version}</version>
</dependency>
<!-- Vaadin4Spring EventBus Addon -->
<dependency>
    <groupId>org.vaadin.spring</groupId>
    <artifactId>spring-vaadin-eventbus</artifactId>
    <version>${vaadin4spring.version}</version>
</dependency>

用户界面示例:

@SpringUI("/ui")
@Title("Test")
@Theme("valo")
public class MainUI extends UI {

    private final Logger log = LoggerFactory.getLogger(MainUI.class);

    @Inject
    EventBus.UIEventBus eventBus;

    @Override
    protected void init(VaadinRequest request) {
        eventBus.subscribe(this);

        setContent(new Button("Create event", (e) -> {
            eventBus.publish(EventScope.UI, "Payload string.");
        }));
    }

    @EventBusListenerMethod
    public void onEvent(String str) {
        log.debug("Event received: {}", str);
    }
}

应用主类

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableVaadinEventBus
public class Application {

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    @Bean
    static VaadinSessionScope vaadinSessionScope() {
        return new VaadinSessionScope();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
于 2015-03-02T23:21:55.817 回答
1

我认为你可以两者兼得。尝试包含"org.vaadin.spring:spring-vaadin:0.0.5-SNAPSHOT",因为VaadinEventbusConfiguration依赖于内部类。

为什么需要包含"org.vaadin.spring:spring-boot-vaadin:0.0.5-SNAPSHOT"?如果您确实需要它,请尝试org.vaadin.spring.boot.VaadinAutoConfiguration从 @EnableAutoConfiguration 中排除。

编辑:您可以在此分支中使用官方 spring4vaadin 获取插件: https ://github.com/peholmst/vaadin4spring/tree/feature/official_spring_support

于 2015-03-01T22:47:55.923 回答
0

作为已接受答案的更新:非官方 vaadin4spring 插件的模块已重命名。现在必须添加此依赖项:

<dependency>
    <groupId>org.vaadin.spring.extensions</groupId>
    <artifactId>vaadin-spring-ext-core</artifactId>
    <version>${vaadin4spring.version}</version>
</dependency>
于 2016-12-01T07:16:03.290 回答