2013-02-12 5 views
7

Ich dachte, die Spring-Annotationen sollten in einer Grails-Umgebung funktionieren, aber ich kann es nicht funktionieren lassen. Ich habe auch die Methode afterProperties ausprobiert, die auch nicht funktioniert hat.@PostConstruct schlägt lautlos auf einem Grails-Dienst fehl

Kann jemand einen Fehler finden? Gibt es eine Konfiguration, die ich tun muss?

package dashboard 

import javax.annotation.PostConstruct 

class EmailJobSchedulerService 
{ 
    def grailsApplication 

    @PostConstruct 
    def init() { 
     def cronExpression = grailsApplication.config.emailAt8AmTrigger 
     println(cronExpression) 
     EmailSubscribersJob.schedule(cronExpression, new HashMap()) 
    } 
} 
+0

Diese Anmerkung an Ort und Stelle eine Menge von Einschränkungen setzen (siehe http://docs.oracle.com/javase/7/docs/api/javax/annotation/PostConstruct.html). Bewerben sich alle? – lucke84

+0

@ lucke84 Nachdem ich es nach Ians Vorschlag in void geändert habe, sollte ich alle Einschränkungen erfüllen. – willcodejavaforfood

+4

Wann soll die cronExpression gedruckt werden? Beim Serverstart? Ich glaube, das wird aufgerufen, wenn der erste Aufruf einer der Methoden des Dienstes erfolgt und nicht beim Serverstart. Ich schlage vor, eine Dummy-Methode im Bootstrap aufzurufen, nur um zu bestätigen. – uchamp

Antwort

14

Versuchen Sie es

@PostConstruct 
void init() { 

(d.h. void anstelle von def) zu verändern. Ich bin nicht sicher, ob Spring dies ausdrücklich erzwingt, aber die specification of @PostConstruct besagt, dass unter anderem "Der Rückgabetyp der Methode muss ungültig sein".

Edit: uchamps Kommentar ist korrekt, ich habe gerade den gleichen Test versucht und in der Tat die annotierte Methode wird nur beim ersten Mal die Service-Bean verwendet wird und nicht unbedingt sofort beim Start aufgerufen. Sie können die Service-Klasse

static lazyInit = false 

der Serviceklasse hinzufügen, damit sie beim Start eifrig initialisiert wird. Dies scheint nicht in der Bedienungsanleitung dokumentiert zu sein, ich habe es von reading the code abgeleitet.

Beachten Sie, dass "verwendet" im vorherigen Absatz nicht unbedingt bedeutet, dass Sie eine Methode aufrufen müssen. Die Service-Bean wird initialisiert, wenn sie zum ersten Mal aus dem Anwendungskontext abgerufen wird, entweder direkt oder weil sie in eine andere Bean initialisiert wurde, die gerade initialisiert wird. Um zum Beispiel des Dienstes in BootStrap Injektion

def emailJobSchedulerService 

mit ausreichen würde, um die @PostConstruct Methode zu schießen, müssen Sie nicht tatsächlich die einen des Service rufen Methoden aus der BootStrap.init Schließung. Wenn Ihr Dienst in einen beliebigen Controller eingespeist wurde, würde der init ebenfalls ausgelöst, wenn einer dieser Controller das erste Mal eine Anfrage bearbeitet (jede Anfrage, es muss keine Aktion sein, die den Service aufruft).

+0

Immer noch nichts. Schätzen Sie die Mühe aber :) – willcodejavaforfood

+1

@willcodejavaforfood unter der Annahme, dass die '.groovy' Datei in Frage ist in' grails-app/services' und nicht 'src/groovy' dann es _should_ einfach funktionieren. Ich habe den gleichen Trick oft benutzt. Eine Sache zu beachten ist jedoch, dass GORM wahrscheinlich nicht zur '@ PostConstruct' Zeit verfügbar ist. Wenn Sie mit GORM-Methoden etwas anfangen müssen, müssen Sie wahrscheinlich eine normale Methode ohne Annotationen definieren und sie von BootStrap aufrufen. –

+0

Das ist seltsam.Habe sogar ein brandneues Projekt nur über die Kommandozeile erstellt und @PostConstruct wurde dort auch nicht aufgerufen. Ich brauche nicht GORM dafür zu verwenden, einfach meinen Job planen, der nicht beibehalten wird. – willcodejavaforfood

1

Hinzufügen einfach auf die Antwort von @Ian - Aus irgendeinem Grund hatte ich:

@PostConstruct 
private void init() { 

Dies scheiterte auch leise und gab seltsame Verhalten. Lösung war „privat“ zu entfernen:

@PostConstruct 
void init() {