Closed ray-mints closed 4 years ago
I've tried to create in another project - the result is the same. Here is the code:
@Route("test")
@SpringComponent
public class Test extends VerticalLayout {
public Test(){
add(new Label("label"));
Upload upload = new Upload();
}
}
Here is the error:
rg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'test' defined in file [/home/username/work/flow-spring-tutorial-master/target/classes/org/vaadin/spring/tutorial/Test.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.vaadin.spring.tutorial.Test]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1236) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1135) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.vaadin.spring.tutorial.TutorialApplication.main(TutorialApplication.java:17) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.vaadin.spring.tutorial.Test]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:182) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1228) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
... 17 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.vaadin.flow.server.communication.StreamRequestHandler.generateURI(StreamRequestHandler.java:135) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.server.StreamResourceRegistry.getURI(StreamResourceRegistry.java:131) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.server.StreamResourceRegistry.getURI(StreamResourceRegistry.java:126) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.internal.nodefeature.ElementAttributeMap.setResource(ElementAttributeMap.java:125) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.dom.impl.BasicElementStateProvider.setAttribute(BasicElementStateProvider.java:316) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.dom.Element.setAttribute(Element.java:343) ~[flow-server-1.0.0.rc1.jar:na]
at com.vaadin.flow.component.upload.Upload.<init>(Upload.java:75) ~[vaadin-upload-flow-1.0.0.rc1.jar:na]
at org.vaadin.spring.tutorial.Test.<init>(Test.java:14) ~[classes/:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_171]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_171]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_171]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_171]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
... 19 common frames omitted
Process finished with exit code 1
Everything works fine without Upload. Is there a way to bypass it and use Upload component with Spring Boot?
Ok. I found one cheap and dirty workaround (for those who really stuck and need things to be done). I don't like this solution, but here it is:
@Route("test")
@SpringComponent
public class Test extends VerticalLayout {
public Test(){
Button crapButton = new Button("press to get an upload button");
add(crapButton);
crapButton.addClickListener(buttonClickEvent -> {
addUpload();
crapButton.setVisible(false);
});
}
void addUpload(){
Upload upload = new Upload();
add(upload);
}
}
Seems like the problem is that Element.setAttribute(String, AbstractStreamResource)
assumes UI.getCurrent()
is available. The logic triggered through that method should instead probably defer any logic until the element is attached and explicitly find the UI its attached to instead of relying on getCurrent()
.
Closing. Seems to work on V14.4
I just had the same issue. When you annotate a component just with @SpringComponent
(without a scope), it's a singleton and will be preinitialized by Spring. You need to ensure that Upload
is only used by beans with at least @UIScope
to prevent the NPE caused by UI.getCurrent()
.
According to the documentation, @Route
should imply a prototype scope.
All Flow routing components (
@Route
,RouterLayout
orHasErrorParameter
) are initialized by Spring, even without explicitly adding the@SpringComponent
annotation. Without any annotations, the components act like a bean in prototype scope.
But in my experience, this isn't true (don't know if this is a bug in the documentation or the implementation): You need an explicit @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
if you really want a prototype.
EDIT: Maybe I've missinterpreted "Without any annotations ..." and it means "without @SpringComponent
...".
@chkpnt Could you please submit a new issue?
Mh, I don't think there is a bug with vaadin-upload
. I just wanted to add the hint for other developers stumbling over this issue, that a @SpringComponent
might need a @UIScope
or something else like in this case.
I use Vaadin 10. So I have a MainUI class that extends SplitLayout. Inside I have object of WorkLayout (WorkLayout extends VerticalLayout). WorkLayout has few buttons in a constructor and an Upload. If I write
@SpringComponent
at the top of my MainUI - my spring boot project won't start, unless I delete Upload or put it in try catch. (If I put it in a try catch - it won't create Upload component on the screen at all and will just do whatever is in catch). After trying to change things in my code - I figured that theUpload upload = new Upload();
is causing it. (If i change toUpload upload = new Upload(buffer);
- the problem is the same. In fact, even a single line withnew Upload();
cause the error.) Here is the error: