How to use the new Vaadin Spring Boot addon together with Vaadin4Spring EventBus - spring

The Vaadin team has currently released an addon which is as I understood based on the unofficial Vaadin4Spring addon:
Vaadin Spring Boot:
https://vaadin.com/directory#addon/vaadin-spring-boot
Vaadin4Spring:
https://github.com/peholmst/vaadin4spring
Please note! As of February 2015, Vaadin is working on an official
Spring add-on which will be a small subset of Vaadin4Spring. Once the
official add-on is released, Vaadin4Spring will be converted into a
set of add-ons that provide features that the official add-on does not
have. You can follow the progress of the official add-on here:
https://github.com/vaadin/spring
However, the Vaadin Spring Boot is missing some cool features which Vaadin4Spring has (like said above by Petter Holmström, the author of Vaadin4Spring), like the EventBus framework, which is really useful.
Now I have set up a Maven project both with the Vaadin Spring Boot addon and the Vaadin4Spring addon:
<!-- Vaadin Spring Boot -->
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot</artifactId>
<version>${vaadin.spring.boot.version}</version>
</dependency>
Basically, I would like to use the features of both the frameworks (or better, I would like to use Vaadin Spring Boot as the main framework and use the Vaadin4Spring EventBus features together with it). The problem I have noticed, however, is that it seems that both the frameworks cannot coexist with each other yet.
If I add both the addons as above, when I run the application, no views and no UIs are found (below the log showing what I mean):
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
But the Views and the UI do exist! They are managed by the Vaadin Spring Boot addon (here is some sample code):
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;
}
}
A view annotated with #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"));
}
}
The same goes for other views. And everything works, when these two dependencies are removed from the 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>
Not allowing me to use the EventBus framework. Did anyone already explore the new addon too and had the same need? Did you find out how to integrate the two worlds? Or is it still early to use Vaadin4Spring tools into Vaadin Spring Boot and we should wait that the Vaadin4Spring features get converted into a set of addons which will complete Vaadin Spring Boot as is said in the first block I posted?
EDIT: I also tried to add a #ComponentScan annotation to the Spring Boot application class while having the three dependencies together, didn't help...
If I add spring-vaadin instead of 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>
Views and UIs are loaded and I can see them in the browser, but as soon as I want to start using an event bus, I get the following exception:
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
It seems that the EventBus.* beans don't get registered inside the Spring IoC container. What to do?

The problem is that VaadinSessionScope is not implemented yet in official spring4vaadin. You need to create that bean thought the unofficial spring4vaadin.
Your pom file:
<!-- 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>
UI example:
#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);
}
}
Application main class
#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);
}
}

I think that you can have both. Try to include "org.vaadin.spring:spring-vaadin:0.0.5-SNAPSHOT" since VaadinEventbusConfiguration relies on internal classes.
Why do you need to include "org.vaadin.spring:spring-boot-vaadin:0.0.5-SNAPSHOT" ? If you really need it try to exclude org.vaadin.spring.boot.VaadinAutoConfiguration from #EnableAutoConfiguration.
EDIT:
You can get the addons with the official spring4vaadin in this branch:
https://github.com/peholmst/vaadin4spring/tree/feature/official_spring_support

As an update to the accepted answer: the modules of the unofficial vaadin4spring add-on were renamed. Now one has to add this dependency:
<dependency>
<groupId>org.vaadin.spring.extensions</groupId>
<artifactId>vaadin-spring-ext-core</artifactId>
<version>${vaadin4spring.version}</version>
</dependency>

Related

Start Springboot without any Undertow Configuration

I have a project which mixes 2 dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-installed-adapter</artifactId>
<version>11.0.2</version>
</dependency>
I'm getting a transitiv dependency for Undertow, which comes from
keycloak-installed-adapter
As far as I understood, Undertow is used internally within the KeyCloak libraries.
I don't want my Springboot Application to start with Undertow, nor I want that anything related with Undertow gets configured at Springboot level.
I can't find to completely exclude any Undertow configuration for Springboot. Does anyone have an idea?
Update
I now have the following:
#SpringBootApplication
#EnableAutoConfiguration(exclude = {EmbeddedUndertow.class})
public class SpringbootTest {
public static void main(String[] args) {
SpringApplication.run(SpringbootTest.class, args);
}
}
But i'm getting following exception when starting my service:
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'undertowEmbeddedServletContainerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration$EmbeddedUndertow.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory]: Factory method 'undertowEmbeddedServletContainerFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: io/undertow/servlet/api/SessionPersistenceManager
Knowing that the EmbeddedUndertow Class lokks like:
#Configuration
#ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
#ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
#Bean
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory();
}
}
How would you ignore this calss from the scanning?

JavaMailSender error - NoSuchBeanDefinitionException: No qualifying bean of type

I am developing Java web with JDK 1.6 .
Project that I develop is copied from previous out project which is developed with JDK 1.8 .
So I modified many maven dependencies's version.
And now, most of them work well.
But there is a problem that makes tomcat can't run web.
Whenever I start tomcat(version is 6.0.53), I face an error like this ↓
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.mail.javamail.JavaMailSender' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I did search about 'No qualifying bean of type' error via google. People who faced 'No qualifying bean of type' error said "you should check whether you missed annotation service, repository or other".
But I can't add any annotation on JavaMailSender because it is in jar.
↓ These are dependencies I added into pom.xml .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
</dependency>
How can I solve this problem?
I need your help.
Thank you.
You need to create a bean in your config package(if u have it). You are probably having spring security in your dependencies.
Your can create a bean as given below:
#Configuration
public class MailConfiguration {
#Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("my#gmail.com");
mailSender.setPassword("mypassword");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
return mailSender;
}
}

Spring Boot test tries to initialize cache2k for the 2nd time and fails

After adding cache2k to my project some #SpringBootTest's stopped working with an error:
java.lang.IllegalStateException: Cache already created: 'cache'
Below I provide the minimal example to reproduce:
Go to start.spring.io and create a simplest Maven project with Cache starter, then add cache2k dependencies:
<properties>
<java.version>1.8</java.version>
<cache2k-version>1.2.2.Final</cache2k-version>
</properties>
<dependencies>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-api</artifactId>
<version>${cache2k-version}</version>
</dependency>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-core</artifactId>
<version>${cache2k-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-spring</artifactId>
<version>${cache2k-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Now configure the simplest cache:
#SpringBootApplication
#EnableCaching
public class CachingDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CachingDemoApplication.class, args);
}
#Bean
public CacheManager springCacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager();
cacheManager.addCaches(b -> b.name("cache"));
return cacheManager;
}
}
And add any service (which we will #MockBean in one of our tests:
#Service
public class SomeService {
public String getString() {
System.out.println("Executing service method");
return "foo";
}
}
Now two #SpringBootTest tests are required to reproduce the issue:
#SpringBootTest
#RunWith(SpringRunner.class)
public class SpringBootAppTest {
#Test
public void getString() {
System.out.println("Empty test");
}
}
#RunWith(SpringRunner.class)
#SpringBootTest
public class WithMockedBeanTest {
#MockBean
SomeService service;
#Test
public void contextLoads() {
}
}
Notice that the 2nd test has mocked #MockBean. This causes an error (stacktrace below).
Caused by: java.lang.IllegalStateException: Cache already created: 'cache'
at org.cache2k.core.CacheManagerImpl.newCache(CacheManagerImpl.java:174)
at org.cache2k.core.InternalCache2kBuilder.buildAsIs(InternalCache2kBuilder.java:239)
at org.cache2k.core.InternalCache2kBuilder.build(InternalCache2kBuilder.java:182)
at org.cache2k.core.Cache2kCoreProviderImpl.createCache(Cache2kCoreProviderImpl.java:215)
at org.cache2k.Cache2kBuilder.build(Cache2kBuilder.java:837)
at org.cache2k.extra.spring.SpringCache2kCacheManager.buildAndWrap(SpringCache2kCacheManager.java:205)
at org.cache2k.extra.spring.SpringCache2kCacheManager.lambda$addCache$2(SpringCache2kCacheManager.java:143)
at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
at org.cache2k.extra.spring.SpringCache2kCacheManager.addCache(SpringCache2kCacheManager.java:141)
at org.cache2k.extra.spring.SpringCache2kCacheManager.addCaches(SpringCache2kCacheManager.java:132)
at com.example.cachingdemo.CachingDemoApplication.springCacheManager(CachingDemoApplication.java:23)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca.CGLIB$springCacheManager$0(<generated>)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca$$FastClassBySpringCGLIB$$bbd240c0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca.springCacheManager(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 52 more
If you remove #MockBean, both tests will pass.
How can I avoid this error in my test suite?
Your second test represents a different ApplicationContext altogether so the test framework will initiate a dedicated one for it. If cache2k is stateful (for instance sharing the CacheManager for a given classloader if it already exists), the second context will attempt to create a new CacheManager while the first one is still active.
You either need to flag one of the test as dirty (see #DirtiesContext) which will close the context and shut down the CacheManager, or you can replace the cache infrastructure by an option that does not require all that, see #AutoConfigureCache.
If cache2k works in such a way that it requires you to dirty the context, I'd highly recommend to swap it using the later options.
Since I do not want any custom behavior in test, but just want to get rid of this error, the solution is to create CacheManager using unique name like this:
#Bean
public CacheManager springCacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager("spring-" + hashCode());
cacheManager.addCaches(b -> b.name("cache"));
return cacheManager;
}
I encountered the same error when using cache2k with Spring Dev Tools, and ended up with the following code as the solution:
#Bean
public CacheManager cacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager();
// To avoid the "Caused by: java.lang.IllegalStateException: Cache already created:"
// error when Spring DevTools is enabled and code reloaded
if (cacheManager.getCacheNames().stream()
.filter(name -> name.equals("cache"))
.count() == 0) {
cacheManager.addCaches(
b -> b.name("cache")
);
}
return cacheManager;
}

Spring Integration Java DSL problems at startup with Http Outbound Gateway

I'm new to Spring Integration and am trying to develop an application which simply (1) polls a folder for new files with extension .dat containing data in csv format (2) initialize for each line a domain POJO object of class RecordDTO and finally (3) sends this object as payload to a REST service with a POST.
For this I'm trying to use Java DSL for Spring Integration.
The problem I'm getting is the following VerifyError / HttpRequestExecutingMessageHandler overrides final method onInit. exception.
2016-07-22 10:01:38.965 ERROR 4460 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'upcase' defined in eu.softeco.examples.SpringBootIntegrationTestApplication: Initialization of bean failed; nest
ed exception is java.lang.VerifyError: class org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler overrides final method onInit.()V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
...
Caused by: java.lang.VerifyError: class org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler overrides final method onInit.()V
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_45]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_45]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_45]
...
Below are relevant details concerning my code and maven configuration. Please not that
1) the problem is at startup, before any data is put in the input folder
2) if I replace the final Http outboundGateway step with the simple (commented) System.out.println, everything works fine.
Following are code/config details. This is my main Spring Boot application class with Spring Integration Flow definition:
#SpringBootApplication
#EnableIntegration
#IntegrationComponentScan
public class SpringBootIntegrationTestApplication {
...
public static void main(String[] args) {
SpringApplication.run(SpringBootIntegrationTestApplication.class, args);
}
/**
* Inbound FileReadingMessageSource
*/
#Bean
#InboundChannelAdapter(channel = "upcase.input", poller = #Poller(fixedDelay = "4000"))
public MessageSource<File> fileReadingMessageSource() {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(INBOUND_PATH));
source.setFilter(new SimplePatternFileListFilter("*.dat"));
return source;
}
/**
* Spring Integration Java DSL Flow
*/
#Bean
public IntegrationFlow upcase() {
FileToStringTransformer fileToStringTranformer = Transformers.fileToString();
fileToStringTranformer.setDeleteFiles(true);
return flow -> flow
// get string contents from fie
.transform(fileToStringTranformer)
// split into individual lines
.split( s -> s.applySequence(true).get().getT2().setDelimiters("\n"))
// cleanup lines from trailing returns
.transform( (String s) -> s.replace("\n", "").replace("\r", "") )
// convert csv string to RecordDTO object
.transform("#recordFromCsvTransformer.transform(payload)")
// print on System.out
// .handle(m -> System.out.println(m.getPayload()))
// send to
.handle(Http.outboundGateway("http://localhost:8080/records")
.httpMethod(HttpMethod.POST)
.expectedResponseType(RecordDTO.class));
}
}
Below the RecordFromCsvTransformer class
#Component
public class RecordFromCsvTransformer
{
#Transformer
public RecordDTO transform(String csvline) throws Exception {
RecordDTO record = new RecordDTO();
... parse csv and initialize record's fields...
return record;
}
}
And Finally the relevant parts of pom.xml (dependencies);
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RC1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
...
</dependencies>
...
As a side question in general, can someone suggest me some good tutorial / getting started guide to learn Spring Integration with Java Annotation/Java DSL? So far I've only found either introductory guide based on Spring Integration XML configuration or material about Java Annotations/DSL but that already requires prior knowledge of Spring Integration.
<version>2.1.0.RELEASE</version>
That version of Spring Integration is mismatched with the spring-integration-core version brought in transitively by maven.
You need to use the same version of all spring-integration-* files - check which version of spring-integration-file is being pulled in by boot and use the same version.

spring boot repository metrics

I am trying to make an object repositoryMetrics in SpringBoot and later I obtained information with this repository. But I create a repository and this always is null.
How I generate a repository and this save the metrics?
I have this code:
public static void stateSist() throws Exception {
InMemoryMetricRepository metricRepository = null;
metricRepository.findAll();
System.out.println(metricRepository.count());
}
EDIT 1:
I do this change in my version and I obtained this error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'actuatorMetricsPrinter' defined in file [ActuatorMetricsPrinter.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.Collection]: : No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1115)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at hello.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
... 18 common frames omitted
Thank you!
In order to access all Public Metrics printed by the Spring Boot actuator framework you need to inject a 'Collection' into your component and then access it to read all the metrics. Here is an example:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.stereotype.Component;
import java.util.Collection;
#Component
public class ActuatorMetricsPrinter {
private static final String TEMPLATE = "Metric: %s [%s]";
private final Collection<PublicMetrics> publicMetrics;
#Autowired
public ActuatorMetricsPrinter(Collection<PublicMetrics> publicMetrics) {
this.publicMetrics = publicMetrics;
}
public String printAllMetrics() {
StringBuilder sb = new StringBuilder();
for (PublicMetrics pm : publicMetrics) {
sb.append("Public Metric: " + pm.getClass().getName());
sb.append("\n\n");
for (Metric<?> m : pm.metrics()) {
sb.append(String.format(TEMPLATE, m.getName(), m.getValue().toString()));
sb.append("\n");
}
}
return sb.toString();
}
}
If you want to reproduce this simple scenario, then:
Go to http://start.spring.io/ and create new project with Actuator and Web checked,
Create a demo project with Build tool of your choice (Gradle, Maven),
Download it and open in your IDE,
Create a new component just like one in my example,
Create a new RestController, like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class DummyController {
private final ActuatorMetricsPrinter metricsPrinter;
#Autowired
public DummyController(ActuatorMetricsPrinter metricsPrinter) {
this.metricsPrinter = metricsPrinter;
}
#RequestMapping(value = "/customMetrics", method = RequestMethod.GET)
public String printMetrics() {
return metricsPrinter.printAllMetrics();
}
}
Then start the application and type in your browser: http://localhost:8080/customMetrics
You should see all the metrics printed by your class in the most messy way possible
If you are using Maven or Gradle for dependency management, then you must make sure these are present in either (from Spring Clouds's Home Page):
Maven:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR4</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
Gradle:
buildscript {
dependencies {
classpath "io.spring.gradle:dependency-management-plugin:0.4.0.RELEASE"
}
}
apply plugin: "io.spring.dependency-management"
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-starter-parent:Angel.SR4'
}
}
dependencies {
compile 'org.springframework.cloud:spring-cloud-starter-config'
compile 'org.springframework.cloud:spring-cloud-starter-eureka'
}
If you omit the parent in Maven or the dependencyManagement in gradle, and try to just import the latest version of each of the dependencies, you will get the runtime error that you are describing.
A similar problem addresses this here on GitHub.

Resources