Grails

BeanBuilder doesn't work from Groovy script

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: 0.4
  • Fix Version/s: 0.6-RC1
  • Component/s: Configuration
  • Labels:
    None

Description

Bean properties aren't set when using BeanBuilder from within a Groovy script. BeanBuilder seems to work fine when used within a class (as in http://svn.grails.codehaus.org/browse/grails/trunk/grails/test/groovy/grails/spring/BeanBuilderTests.groovy?r=2213), but fails when used in a standalone script.

For example, I'm trying to recreate the Spring configuration from listing 1.8 of "Spring in Action" using the BeanBuilder. Here's the script:

package com.springinaction.chapter01.knight;
import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder()

bb.beans {
quest(HolyGrailQuest) {}

knight(KnightOfTheRoundTable, "Bedivere") { quest = quest }
}

ApplicationContext ctx = bb.createApplicationContext()
Knight knight = ctx.getBean("knight")
knight.embarkOnQuest()

The quest property never gets set. Consequently, a NPE is thrown when trying to call the embark() method (within embarkOnQuest()).

Activity

Hide
Paul King added a comment -

Changing:

knight(KnightOfTheRoundTable, "Bedivere") { quest = quest }

to:

knight(KnightOfTheRoundTable, "Bedivere") { delegate.quest = quest }

Seemed to work for me (on a similar example, didn't actually try this one) using the latest version of Spring (2.1m2) and Grails head.

Show
Paul King added a comment - Changing:
knight(KnightOfTheRoundTable, "Bedivere") { quest = quest }
to:
knight(KnightOfTheRoundTable, "Bedivere") { delegate.quest = quest }
Seemed to work for me (on a similar example, didn't actually try this one) using the latest version of Spring (2.1m2) and Grails head.
Hide
Matthew Corby-Eaglen added a comment -

I have a similar (related?) issue:

in a script, the bean builder does not seem to set properties that reference beans in the parent context:

package a

public class ABean{
    int i = 0
    public void myMethod(){
         System.out.println("hello world")
    }
}
...
package b

import a.ABean

public class B{
    ABean myABean;

    public void setMyABean(ABean myA){
        this.myABean = myA;
    }
    public void getMyABean(){
        return myABean;
    }
}
{/code}

spring context xml

..
<bean id="beanA" class="a.ABean"/>
..

{/code}

calling a script with springs application context bound to parentContext



package my.package

import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder(parentContext)

bb.beans {
myB(B.class){ a = ref("beanA", true) }
}

def ctx = bb.createApplicationContext()

assert(ctx.getBean("myB").a != null){/code}

when i check myB.a it is null.

Show
Matthew Corby-Eaglen added a comment - I have a similar (related?) issue: in a script, the bean builder does not seem to set properties that reference beans in the parent context:
package a

public class ABean{
    int i = 0
    public void myMethod(){
         System.out.println("hello world")
    }
}
...
package b

import a.ABean

public class B{
    ABean myABean;

    public void setMyABean(ABean myA){
        this.myABean = myA;
    }
    public void getMyABean(){
        return myABean;
    }
}
{/code}

spring context xml
.. <bean id="beanA" class="a.ABean"/> .. {/code} calling a script with springs application context bound to parentContext

package my.package import org.springframework.context.ApplicationContext; def bb = new grails.spring.BeanBuilder(parentContext) bb.beans { myB(B.class){ a = ref("beanA", true) } } def ctx = bb.createApplicationContext() assert(ctx.getBean("myB").a != null){/code} when i check myB.a it is null.
Hide
Matthew Corby-Eaglen added a comment -

btw i am working with 1.1

Show
Matthew Corby-Eaglen added a comment - btw i am working with 1.1
Hide
Matthew Corby-Eaglen added a comment -

i think actually I must have something else wrong...

please ignore me.

thx

Show
Matthew Corby-Eaglen added a comment - i think actually I must have something else wrong... please ignore me. thx
Hide
Matthew Corby-Eaglen added a comment -

sigh

i figured out why I was getting null. Its a bit more complicated than i thought:

// this is a java object
package a

public class ABean{
    int i = 0
    public void myMethod(){
         System.out.println("hello world")
    }
}

package b

import a.ABean

public class B{
    String name
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name
    }
}

springContext.xml loaded by a ClasspathApplicationContext

...
<bean id="beanA" class="a.ABean" />
...
// a groovy object
public class C extends B{
   int power

   ABean myABean;
}
package my.package

import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder(parentContext) // parent context is passed into the script

bb.beans {
    myAbstractB(B.class){ bean ->
        bean.'abstract' = true
        name= "wombat"
    }
    
    myAbstractChildC(C.class){ bean ->
         bean.'abstract' = true
         bean.parent = myAbstractB
         power = 20
    }
    myConcreateB(C.class){   bean ->
        bean.parent = myAbstractChildB
        myABean = ref("beanA", true)
    }
}

def ctx = bb.createApplicationContext()

assert(ctx.getBean("myConcreateB").myABean  != null) // fails!!! should be a reference to the parent contexts beanA bean
Show
Matthew Corby-Eaglen added a comment - sigh i figured out why I was getting null. Its a bit more complicated than i thought:
// this is a java object
package a

public class ABean{
    int i = 0
    public void myMethod(){
         System.out.println("hello world")
    }
}

package b

import a.ABean

public class B{
    String name
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name
    }
}
springContext.xml loaded by a ClasspathApplicationContext
...
<bean id="beanA" class="a.ABean" />
...
// a groovy object
public class C extends B{
   int power

   ABean myABean;
}
package my.package

import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder(parentContext) // parent context is passed into the script

bb.beans {
    myAbstractB(B.class){ bean ->
        bean.'abstract' = true
        name= "wombat"
    }
    
    myAbstractChildC(C.class){ bean ->
         bean.'abstract' = true
         bean.parent = myAbstractB
         power = 20
    }
    myConcreateB(C.class){   bean ->
        bean.parent = myAbstractChildB
        myABean = ref("beanA", true)
    }
}

def ctx = bb.createApplicationContext()

assert(ctx.getBean("myConcreateB").myABean  != null) // fails!!! should be a reference to the parent contexts beanA bean
Hide
Matthew Corby-Eaglen added a comment -

sorry that is slightly incorrect, I made a typo:

change the script to:

package my.package

import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder(parentContext) // parent context is passed into the script

bb.beans {
    myAbstractB(B.class){ bean ->
        bean.'abstract' = true
        name= "wombat"
    }
    
    myAbstractChildC(C.class){ bean ->
         bean.'abstract' = true
         bean.parent = myAbstractB         
         myABean = ref("beanA", true)
    }
    myConcreateThingy(C.class){   bean ->
        bean.parent = myAbstractChildB
        power = 20
    }
}

def ctx = bb.createApplicationContext()


assert(ctx.getBean("myConcreateThingy").myABean  != null) // fails!!! should be a reference to the parent contexts beanA bean
Show
Matthew Corby-Eaglen added a comment - sorry that is slightly incorrect, I made a typo: change the script to:
package my.package

import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder(parentContext) // parent context is passed into the script

bb.beans {
    myAbstractB(B.class){ bean ->
        bean.'abstract' = true
        name= "wombat"
    }
    
    myAbstractChildC(C.class){ bean ->
         bean.'abstract' = true
         bean.parent = myAbstractB         
         myABean = ref("beanA", true)
    }
    myConcreateThingy(C.class){   bean ->
        bean.parent = myAbstractChildB
        power = 20
    }
}

def ctx = bb.createApplicationContext()


assert(ctx.getBean("myConcreateThingy").myABean  != null) // fails!!! should be a reference to the parent contexts beanA bean
Hide
Matthew Corby-Eaglen added a comment -

I have created a new issue:

http://jira.codehaus.org/browse/GRAILS-4498

This issue has the code I was trying to express attached as a zip.

Show
Matthew Corby-Eaglen added a comment - I have created a new issue: http://jira.codehaus.org/browse/GRAILS-4498 This issue has the code I was trying to express attached as a zip.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: