vaadin / vaadin-upload

The Web Component for uploading multiple files with progress indication. Part of the Vaadin components.
https://vaadin.com/components
Apache License 2.0
90 stars 63 forks source link

Upload constructor thows an exception nested by NullPointerException #351

Closed ray-mints closed 4 years ago

ray-mints commented 6 years ago

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 the Upload upload = new Upload(); is causing it. (If i change to Upload upload = new Upload(buffer); - the problem is the same. In fact, even a single line with new Upload(); cause the error.) Here is the error:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-06-11 14:20:22.219 ERROR 7985 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainUI' defined in file [/home/username/work/myproject/target/classes/com/example/myproject/frontend/main/MainUI.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.myproject.frontend.main.MainUI]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1236)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)
    at com.example.myproject.MyProjectApplication.main(MyProjectApplication.java:9)
    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.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.myproject.frontend.main.MainUI]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:182)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1228)
    ... 22 common frames omitted
Caused by: java.lang.NullPointerException: null
    at com.vaadin.flow.server.communication.StreamRequestHandler.generateURI(StreamRequestHandler.java:135)
    at com.vaadin.flow.server.StreamResourceRegistry.getURI(StreamResourceRegistry.java:131)
    at com.vaadin.flow.server.StreamResourceRegistry.getURI(StreamResourceRegistry.java:126)
    at com.vaadin.flow.internal.nodefeature.ElementAttributeMap.setResource(ElementAttributeMap.java:124)
    at com.vaadin.flow.dom.impl.BasicElementStateProvider.setAttribute(BasicElementStateProvider.java:316)
    at com.vaadin.flow.dom.Element.setAttribute(Element.java:342)
    at com.vaadin.flow.component.upload.Upload.<init>(Upload.java:75)
    at com.example.myproject.frontend.main.sublayouts.WorkLayout.<init>(WorkLayout.java:51)
    at com.example.myproject.frontend.main.MainUI.<init>(MainUI.java:18)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170)
    ... 24 common frames omitted
ray-mints commented 6 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?

ray-mints commented 6 years ago

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);
  }
}
Legioth commented 6 years ago

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().

tomivirkki commented 4 years ago

Closing. Seems to work on V14.4

chkpnt commented 2 years ago

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 or HasErrorParameter) 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 ...".

web-padawan commented 2 years ago

@chkpnt Could you please submit a new issue?

chkpnt commented 2 years ago

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.