2012-05-25 3 views
1

는 설정의이 크게 단순화 된 연주를 감안할 때 :Grails :이 서비스 클래스가 null이되는 이유는 무엇입니까?

package net.myexample.plugin 

class MyExampleService { 
    Map doMunge(Map m) { 
    // do stuff to 'm' 
    return m 
    } 
} 

/****************************** BREAK: NEXT FILE ******************************/ 

package net.myexample.plugin 

class MyTagLib { 
    static namespace = 'p' 

    def myExampleService 

    def tag = { attrs, body -> 
    def m = doMungeAndFilter(attrs.remove('m')) 

    out << g.render(template: '/template', plugin: 'my-example-plugin', model: m) 
    } 

    Map doMungeAndFilter(def m) { 
    def mm = myExampleService.doMunge(m) 
    // do stuff to 'm' 
    return mm 
    } 
} 

/****************************** BREAK: NEXT FILE ******************************/ 

package net.myexample.app 

import net.myexample.plugin.MyExampleService 

class MyExampleService extends net.myexample.plugin.MyExampleService { 
    def doMunge(def m) { 
    def mm = super.doMunge(m) 
    // do more stuff to 'mm' 
    return mm 
    } 
} 

/****************************** BREAK: NEXT FILE ******************************/ 

package net.myexample.app 

import net.myexample.plugin.MyTagLib 

class MyTagLib extends net.myexample.plugin.MyTagLib { 
    static namespace = 'a' 

    def myExampleService 

    def tag = { attrs, body -> 
    def m = doMungeAndFilter(attrs.remove('m')) 

    out << g.render(template: '/template', plugin: 'my-example-plugin', model: m) 
    } 

    Map doMungeAndFilter(def m) { 
    def mm = super.doMungeAndFilter(m) 
    // do more stuff to 'mm' 
    return mm 
    } 
} 

/** 
* But we get an exception that cites that it cannot call 'doMunge' on a null 
* object -- which could only be 'myExampleService' 
*/ 

이유는 서비스 앱의 태그 라이브러리에 방법이 차례로 메소드를 호출하여 수퍼 클래스 (플러그인에 태그 라이브러리)를 호출 할 때 null을 것으로 나타납니다 서비스에?

가장 좋은 이론은 def을 제외하고는 명시적인 참조가 없으므로 서비스가 실제로 앱의 taglib 클래스에서 인스턴스화되지 않는다는 것입니다. 나는 이것이 모든 로직을 서비스 클래스의 메소드에서 taglib의 메소드로 옮기면 예상대로 작동하기 때문에이 경우라고 생각한다.

: 또는 (완전한 그림을 그림을 위해서. MyTagLib.doMungeAndFilter의 후속 필터링()에만 태그 라이브러리에 필요한 반면 MyExampleService.doMunge가 다른 장소에서라고합니다)

: 나는에 doMungeAndFilter를 이동하는 경우 다른 서비스 클래스, 플러그인에서 기본 버전을 생성하고 응용 프로그램에서 확장, 잘 작동합니다. 나는 그것이 받아 들일 만 한 결론이라고 생각하지만, 그처럼 taglib를 지원하기 위해 또 다른 서비스 클래스를 만드는 것이 부 풀리는 것처럼 느껴진다.

생각하십니까? 팁? 눈부신 오류 또는 누락?

+0

Grails 버그 인 경우 놀랄 일이 아닙니다. 나는 Flow 내에서 서비스 또는 다른 Grails 클래스를 호출하면 클래스에 서비스를 인스턴스화하고 삽입 할 수 없다는 것을 알고있었습니다. 이것은 비슷한 문제 일 수 있습니다. Grails는 훌륭하고 유용하지만 완벽하지는 않습니다. – billjamesdev

+0

@BillJames - 흥미 롭다. 나는 그것에 대해 몰랐다. 더 많은 것을 찾을 수 있는지 더 깊게 파고들 것 같은데. – founddrama

답변

1

서브 클래스 taglib에서 def myExampleService을 제거하십시오. 그루비에서 같은 속성은 private 필드 플러스 공공 getter와 setter로 컴파일, 그래서 당신은 하위 클래스에서 다시 myExampleService를 선언 할 때 슈퍼 클래스에 당신이 서브 클래스는 자신의 개인 필드를 얻을 암시

private Object myExampleService; 

public void setMyExampleService(Object svc) { 
    this.myExampleService = svc; 
} 
// getter similar 

이 태그 라이브러리 (같은 이름), setter는 슈퍼 클래스가 아닌이 서브 클래스 필드에 제공된 값을 저장하도록 재정의됩니다. Spring은 setter를 호출하여 서비스를 삽입하므로 결과적으로 수퍼 클래스 private myExampleService이 설정되지 않으므로 수퍼 클래스에서 myExampleService.doMunge을 호출 할 때 널 포인터 예외가 발생합니다.

하위 클래스는 상속 된 getter 및 setter를 통해 superclass 속성에 액세스 할 수 있으므로 다시 선언 할 필요가 없습니다.

1

이것은 단지 추측에 불과하지만/grails-app/taglib 또는/src 디렉토리의 어딘가에있는 taglib 클래스 파일입니까? 나는/grails-app 폴더 밖에있는 클래스에 (적어도 자동으로) 서비스를 삽입 할 수 없다는 것을 알았다.

+0

예 - grails-app/taglib에 있습니다. – founddrama

관련 문제