Uploaded image for project: 'Isis'
  1. Isis
  2. ISIS-1401

NPE when wrapping call to FixtureScripts#runFixtureScript for a newly instantiated FixtureScript

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Won't Fix
    • Affects Version/s: 1.12.1
    • Fix Version/s: 1.13.0
    • Component/s: Core
    • Labels:
      None

      Description

      The FixtureScripts#runFixtureScript action is marked as "Prototyping", and basically there's no need to invoke it wrapped, but perhaps is relevant for other use cases.

      When executing something like:
      this.wrap(this.fixtureScripts).runFixtureScript(
      new MyFixtureScript(), null);

      A NullPointerException is thrown, as for the execution on DomainObjectInvokationHandler#handleActionMethod requires to create an adapter for the contributee (line 590):
      [java]
      contributeeAdapter = adapterFor(contributed);
      [/java]

      As the MyFixtureScript is a ViewModel, this will be delegated to FixtureScript#viewModelMemento() which in fact will contain:

      [java]
      @Programmatic
      @Override
      public String viewModelMemento()

      { return fixtureScripts.mementoFor(this); }

      [/java]

      Being "fixtureScripts" null.

      Not sure how to solve this, as basically the FixtureScript requires to be injected before executing it.
      As perhaps this will be the only method that can potentially been invoked before the FixtureScript being wrapped on the "FixtureScripts" service, an easy solution would be to check if the "fixtureScript" variable is null and, in that case, inject its own instance on this same method.

        Activity

        Hide
        danhaywood Dan Haywood added a comment -

        To reproduce, I've added:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
        

        to KitchensinkFixturesService in the kitchensink app.

        One solution is to manually inject services into the fixture script beforehand:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                serviceRegistry2.injectServicesInto(fixtureScript);
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
            @Inject
            ServiceRegistry2 serviceRegistry2;
        

        An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.

        Show
        danhaywood Dan Haywood added a comment - To reproduce, I've added: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; to KitchensinkFixturesService in the kitchensink app. One solution is to manually inject services into the fixture script beforehand: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); serviceRegistry2.injectServicesInto(fixtureScript); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; @Inject ServiceRegistry2 serviceRegistry2; An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.
        Hide
        danhaywood Dan Haywood added a comment -

        To reproduce, I've added:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
        

        to KitchensinkFixturesService in the kitchensink app.

        One solution is to manually inject services into the fixture script beforehand:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                serviceRegistry2.injectServicesInto(fixtureScript);
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
            @Inject
            ServiceRegistry2 serviceRegistry2;
        

        An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.

        Show
        danhaywood Dan Haywood added a comment - To reproduce, I've added: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; to KitchensinkFixturesService in the kitchensink app. One solution is to manually inject services into the fixture script beforehand: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); serviceRegistry2.injectServicesInto(fixtureScript); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; @Inject ServiceRegistry2 serviceRegistry2; An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.
        Hide
        danhaywood Dan Haywood added a comment -

        To reproduce, I've added:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
        

        to KitchensinkFixturesService in the kitchensink app.

        One solution is to manually inject services into the fixture script beforehand:

            @Action(
                    restrictTo = RestrictTo.PROTOTYPING
            )
            @MemberOrder(sequence = "499.10.2")
            public Object test() {
                final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture();
                serviceRegistry2.injectServicesInto(fixtureScript);
                return wrapperFactory.wrap(this).runFixtureScript(fixtureScript, null);
            }
        
            @Inject
            WrapperFactory wrapperFactory;
            @Inject
            ServiceRegistry2 serviceRegistry2;
        

        An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.

        Show
        danhaywood Dan Haywood added a comment - To reproduce, I've added: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; to KitchensinkFixturesService in the kitchensink app. One solution is to manually inject services into the fixture script beforehand: @Action( restrictTo = RestrictTo.PROTOTYPING ) @MemberOrder(sequence = "499.10.2" ) public Object test() { final BusRulesObjectsFixture fixtureScript = new BusRulesObjectsFixture(); serviceRegistry2.injectServicesInto(fixtureScript); return wrapperFactory.wrap( this ).runFixtureScript(fixtureScript, null ); } @Inject WrapperFactory wrapperFactory; @Inject ServiceRegistry2 serviceRegistry2; An alternative would be to refactor the FixtureScript superclass to use @ViewModel or @XmlRootElement. However, this could, perhaps, have unexpected side-effects, so I'd rather leave things as they are for now.

          People

          • Assignee:
            danhaywood Dan Haywood
            Reporter:
            oscarbou Oscar Bou
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development