Как использовать новое дополнение Vaadin Spring Boot вместе с Vaadin4Spring EventBus
В настоящее время команда Vaadin выпустила аддон, который, как я понял, основан на неофициальном аддоне Vaadin4Spring:
Vaadin Spring Boot: https://vaadin.com/directory
Vaadin4Spring: https://github.com/peholmst/vaadin4spring
Пожалуйста, обратите внимание! По состоянию на февраль 2015 года Vaadin работает над официальным дополнением Spring, которое будет небольшим подмножеством Vaadin4Spring. После выпуска официального дополнения Vaadin4Spring будет преобразован в набор дополнений, которые предоставляют функции, которых нет в официальном дополнении. Вы можете следить за ходом официального дополнения здесь: https://github.com/vaadin/spring
Тем не менее, в Vaadin Spring Boot отсутствуют некоторые интересные функции, которыми обладает Vaadin4Spring (как сказано выше Петтером Холмстремом, автором Vaadin4Spring), например, фреймворк EventBus, который действительно полезен.
Теперь я настроил проект Maven с помощью дополнения Vaadin Spring Boot и дополнения Vaadin4Spring:
<!-- 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
особенности вместе с этим). Однако проблема, которую я заметил, заключается в том, что обе платформы пока не могут сосуществовать друг с другом.
Если я добавлю оба дополнения, как указано выше, при запуске приложения не будет найдено ни одного представления и пользовательского интерфейса (под журналом, показывающим, что я имею в виду):
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
аддон (вот пример кода):
UI:
@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>
Представления и пользовательские интерфейсы загружены, и я вижу их в браузере, но как только я хочу начать использовать шину событий, я получаю следующее исключение:
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.* Не регистрируются внутри контейнера IoC Spring. Что делать?
3 ответа
Проблема в том, что VaadinSessionScope
пока не реализовано в официальном spring4vaadin. Вам нужно создать этот боб, подумал неофициальный spring4vaadin.
Ваш файл 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);
}
}
Я думаю, что вы можете иметь оба. Попробуй включить "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
В качестве обновления к принятому ответу: модули неофициального дополнения vaadin4spring были переименованы. Теперь нужно добавить эту зависимость:
<dependency>
<groupId>org.vaadin.spring.extensions</groupId>
<artifactId>vaadin-spring-ext-core</artifactId>
<version>${vaadin4spring.version}</version>
</dependency>