Mit Jenkins gebaut: NPE Spring Context

OnDemand

Top Contributor
Hallo zusammen,

wir haben heute einen neuen Server mit Jenkins aufgesetzt und unser Projekt bauen lassen. Das läuft auch ganz wunderbar durch, aber beim Starten der App bekommen wir eine NPE. Angeblich sei der Spring Context null.

Wir haben folgende Klasse um an die Beans zu kommen:

Java:
@Component
public class SpringContext implements ApplicationContextAware {

    private static ApplicationContext context;

    public static <T extends Object> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        SpringContext.context = context;    //Hier die NPE
    }
}

Hier eine "Anforderung" einer Bean:
Code:
@Service
@DisallowConcurrentExecution
public class XXExport implements Job {
    ProductService productService = SpringContext.getBean(ProductService.class);
}

Klappt lokal wunderbar, da ist nix null beim starten. Auf dem alten Jenkins Server auch nichts null. Nur wenn die App mit dem neuen Server gebaut wird, startet die App nicht.

Hier mal ein paar Unterschiede die mir aufgefallen sind, welche die Server betreffen:

alter Server: java -v 11.0.4
neuer Server: java -v 11.0.15
lokaler Rechner: java -v 11.0.15
Die Java Version kann es schon mal nicht sein, da auf dem lokalen alles paletti ist, wenn ich die .jar lokal baue und auf den Server lege und starte

alter Server: mvn -v 3.6.0
neuer Server: mvn -v 3.6.3
lokaler Rechner: mvn in IDE, kein Plan welche Version
Sollte Maven ein mögliches Problem sein?

Beide Jenkins bauen die App identisch mit clean package -Pproduction (Vaadin)

Die Application.java ist auch nicht irgendwie verändert worden, sodass er die Services nicht findet. Hat also alle nötigen Annotationen:
Code:
@SpringBootApplication
@EnableScheduling
@EnableRetry
@EnableAsync
@EnableEncryptableProperties
public class Application extends SpringBootServletInitializer implements CommandLineRunner {

//....
}


Weiß grad nicht was ich noch schauen könnte und warum die NPE auftritt sobald es mit dem neuen Jenkins gebaut wird. Es könnte doch nur mit Maven zu tun haben, aber warum?
Auf dem Server wo die App starten soll, ist Java 11.0.15 also auch identisch mit dem neuen, womit Jenkins baut. Der alte Server baut mit einer älteren Version. Mein lokaler Rechner hat aber auch 0.15. Das schließe ich dann auch mal aus.

Dann sind noch ein paar Unterschiede in den node-Versionen welche Vaadin braucht, aber das ist eher Frontend Stuff, das sollte mit dem Java NPE nix zu tun haben. In Jenkins selbst bekommen wir keinen Fehler, nur ein paar Warnungen zu npm aber auch die sind auf dem alten Jenkins identisch zum Neuen.

Jenkins löscht auch den Workspace nach dem bauen, also können auch keine alten Dateien irgendwie drin sein. Bin echt ratlos, hat noch jemand ne Idee in welche Richtung ich suchen könnte?
 

sascha-sphw

Top Contributor
Java:
SpringContext.context = context;    //Hier die NPE
Das kann ich mir irgendwie nicht vorstellen. Selbst wenn context null ist, wird SpringContext.context einfach null zugewiesen und gut. Eine NPE würde ich hier nicht erwarten.

Ich würde aber auf static hier komplett verzichten.
Warum geht folgendes nicht?
Java:
@Service
@DisallowConcurrentExecution
public class XXExport implements Job {
    private final ProductService productService;
   
    public XXExport(final ProductService productService) {
        this.productService = productService;
    }
}
 

OnDemand

Top Contributor
Das ginge auch, braucht aber einige Zeilen Code mehr, vor allem wenn ich einige Service injecten will Es funktioniert ja grundsätzlich (seit 1 Jahr) Nur mit dem neuen Jenkins jetzt nicht mehr.

Stimmt, die NPE kommt hier - hab ich falsch kommentiert oben

Java:
public static <T extends Object> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass); //hier NPE
    }
 

OnDemand

Top Contributor
Mmn ist nicht garantiert, dass context initialsiert ist, bevor die Methode zum ersten mal aufgerufen wird.
Das wäre aber viel Glück ;) Echt kurios. Aber das wäre eine Erklärung. Das jetzt alles umbauen wäre mittelfristig möglich und eine Lösung. Aber für jetzt muss ich mal schauen wie ich die Initialisierung priorisieren kann
 

OnDemand

Top Contributor
Hab jetzt einfach mal stumpf den Context in die Startklasse autowired und siehe da, es startet.

Java:
@SpringBootApplication
@EnableScheduling
@EnableRetry
@EnableAsync
@EnableEncryptableProperties
public class Application extends SpringBootServletInitializer implements CommandLineRunner {

    @Autowired
    SpringContext springContext;
    
        public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
 

thecain

Top Contributor
Ja, jetzt initialisiert die Klasse früher und alles ist bereit, aber auch eine "Bastellösung". Ich würde das noch sauber lösen. Zumal es ja kein Spassprojekt ist.

Schlussendlich aber natürlich deine Entscheidung
 

OnDemand

Top Contributor
Jop gefällt mir auch nicht. Werd es mittelfristig umbauen und Stück für Stück, sobald ich solchen Code sehe mit der Konstruktorinjektion ersetzen. Danke für dein heißen Tipp bezgl. der Initialisierung!
 

Ähnliche Java Themen

Neue Themen


Oben