0

NOTE: This issue may or may not be Vaadin related, depending on wether there is a "better" solution to "resetting" the bean or not.

Background scenario

I am building a wizard for entering some values that, when finished, is sent to a table (using Vaadin and the add-on "Wizards for Vaadin").

The add-on does not provide a way to reset the Wizard (i.e. go back to step 1) without a forced call to the current steps (overridden) onAdvance() and onBack() methods, which will return false in some of my steps because I'm using logic in those methods in case the use for example haven't filled in all required data.

I cannot simple create a new instance of the Wizard, because I'm using Spring to manage this @Component.

So, this leaves me with actually resetting the bean in order to reset the wizard correctly.

My question is

How do I "reset" a Spring managed Bean (@Component)? I should add that this Bean also has some dependencies injected to it.

or... (for the Vaadin people):

Is there another way of resetting this wizard other than creating a new Wizard?

Some code

@Component
@Scope("session")
public class MyWizard extends Wizard {

    @Inject
    private MyWizardContainer myWizardContainer;
    @Inject
    private MyService myService;
    @Inject
    private MyWizardStep1 myWizardStep1;
    @Inject
    private MyWizardStep2 myWizardStep2;
    @Inject
    private MyWizardStep3 myWizardStep3;
    @Inject
    private MyMainTableContainer myMainTableContainer;

    final static Logger logger = LoggerFactory.getLogger(MyWizard.class);

    private static final long serialVersionUID = 1L;

    public MyWizard() {
        setupListener();
    }

    public void addSteps() {
        this.addStep(myWizardStep1);
        this.addStep(myWizardStep2);
        this.addStep(myWizardStep3);
        this.mainLayout.setComponentAlignment(this.footer, Alignment.BOTTOM_LEFT);
    }

    private void setupListener() {

        this.addListener(new WizardProgressListener() {

            @Override
            public void wizardCompleted(WizardCompletedEvent event) {
                endWizard("Wizard Finished Successfully!");
            }

            @Override
            public void wizardCancelled(WizardCancelledEvent event) {
                endWizard("Wizard Cancelled!");
            }

            @Override
            public void stepSetChanged(WizardStepSetChangedEvent event) {
                // TODO Auto-generated method stub
            }

            @Override
            public void activeStepChanged(WizardStepActivationEvent event) {
                // TODO Auto-generated method stub
            }
        });
    }

    private void resetWizard() {
        myWizardContainer.removeAll(); //here I'm simply resetting all data that the user generated thus far in the wizard
        this.activateStep(myWizardStep1); //this will not work, as some steps will not always return true on onBack() and/or onAdvance()
    }

    private void endWizard(String message) {
        resetWizard();
        this.setVisible(false);
        Notification.show(message);
    }
}
Roger
  • 2,684
  • 4
  • 36
  • 51

1 Answers1

2

SpringVaadinIntegration, that you probably use, does not require all elements to be @Components, only UI has to be annotated.

Your wizard and it's steps should not be components in this case, if you really need to inject dependencies into them you can use @Configurable annotation, which allowes to inject dependencies to classes not managed by Spring (some more configuration needed to make it work). Just create wizard and steps as new objects when you need them.

dzezzz
  • 985
  • 7
  • 17
  • Your suggestion sounds sensible and you're correct in your assumption that I'm using SVI. I had a feeling I was doing something wrong here, also I didn't know about the @Configuration annotation. I will try this first thing tomorrow and get back with results! Thanks! – Roger Jan 07 '14 at 22:06
  • I don't understand how to configure the `@Configuration` to make the `Wizard` (POJO) accept `@Inject`s. I created a simple example after reading up on the Spring documentation of `@Configuration`, using a `@Configuration` annotated AppConfig-class that creates a `new Wizard` and a simple `@Component` that the `Wizard` should be able to use (`MyService`). However, the documentation doesn't mention anything (that I could find) on actually injecting a bean (eg. `MyService`) into the "POJO-ized" `Wizard`. When I try, I get a `BeanCreationException`. Any clues? – Roger Jan 08 '14 at 10:55
  • Thanks a bunch for your help, @dzezzz. However, the hassle of using AspectJ LTW finally got to me. I couldn't get it to play with Tomcat. I do believe that your solution could work, but we're still creating a new Wizard here, making the answer invalid and I cannot accept it. I solved it in a similiar way, by using @Scope("prototype") on the Wizard component and creating a new Wizard by getting the Wizard object from ApplicationContext. It works like a charm. – Roger Jan 09 '14 at 09:16