@Value mit bestimmt Werten, sonst default

S

Schuriko

Bekanntes Mitglied
Ist es möglich für @Value über SpEL einen bestimmt Wert aus einem property file zu ermitteln, und wenn kein erlaubter Wert ist, dann wird der default Wert verwendet.
 
S

Schuriko

Bekanntes Mitglied
Diese Seite habe ich mir auch schon angeschaut, bin allerdings noch nicht weitergekommen, wie man NUR bestimmte Werte zulässt und wenn es KEIN erlaubter Wert ist, dann soll der Default-Wert verwendet werden.
 
T

thecain

Top Contributor
Achso, kein erlaubter... Das wird wohl nicht gehen.

Ich würde entweder im Code den Wert auf default setzen, wenn ungültig, oder direkt mit einer Exception abbrechen.
 
S

Schuriko

Bekanntes Mitglied
Ich habe es jetzt mal wie folgt realisiert:

Code:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;

import com.editor.helpers.generator;

@Configuration
@PropertySource("classpath:app.properties")
public class Config {

    @Value("${generator_name:null}")
    String generator_name;

    Generator generator = null;
   
    @Bean
    @Scope(value="singleton")
    public Generator getGenerator() {
        if ( generator == null ) {
            if ( generator_name == null ) {
                throw new IllegalArgumentException();
            }

            switch ( generator_name.toLowerCase() ) {
                case "a" : generator = new GeneratorA();
                                break;
                             
                case "b" : generator = new GeneratorB();
                               break;
            }
        }
       
        return generator;
    }

}

Oder wie würdet ihr es realisieren? Und wo sollte ich die InvalidArgumentException abfangen bzw. bearbeiten?
Ich sollte noch dazu erwähnen es wird eine Web-Anwendung, die Thymeleaf verwendet, ist.
 
kneitzel

kneitzel

Top Contributor
Ich frage mich gerade nur, wieso Du nicht die GeneratorA und GeneratorB zu Beans machst um dann im Config File halt den Bean entsprechend zu definieren, also sowas wie
XML:
<beans>
    <bean id="generator" class="my.namespace.GeneratorA">
        <!-- maybe more options go in here -->
    </bean>
</beans>
Dann hättest Du ein Config File, in dem Du jederzeit einen anderen Generator angeben kannst. Und Du musst keinen Config Bean anpassen ... da gibt es dann keine Abhängigkeit zu den existierenden Generatoren.

Oder - so Du unbedingt das in der Art haben willst: Da es ja um eine einmalige Sache geht, könntest Du den kompletten Klassennamen hinterlegen und dann eine neue Instanz erzeugen. Das wäre dann evtl. sowas in der Art (Fehlerbehandlung müsste man noch einfügen):

Java:
    @Value("${generator_class:null}")
    String generatorClass;

    Generator generator = null;
  
    @Bean
//    @Scope(value="singleton") ==> Singleton ist Standard in Spring, daher ist diese Annotation unnötig.
    public Generator getGenerator() {
          if (generator == null) {
            Class c = Class.forName(generatorClass);
            generator = (Generator) c.newInstance();
          }
        return generator;
    }

Bei beiden Varianten hast Du keine Abhängigkeit von einer Klasse zu allen bekannten Generator Implementationen.

Und die Exception wirst du bei Dir und bei meiner letzteren Methode dann nur da abfangen können, wo getGenerator aufgerufen wird.

Bei der ersten Version von mir würde beim Start der Applikation der Bean nicht erzeugt werden können (sowie alle davon abhängigen Beans). Da muss man also beim App Server entsprechend ein Monitoring haben (oder eben bei Updates immer verifizieren
 
S

Schuriko

Bekanntes Mitglied
Ich frage mich gerade nur, wieso Du nicht die GeneratorA und GeneratorB zu Beans machst um dann im Config File halt den Bean entsprechend zu definieren, also sowas wie
XML:
<beans>
    <bean id="generator" class="my.namespace.GeneratorA">
        <!-- maybe more options go in here -->
    </bean>
</beans>
Dann hättest Du ein Config File, in dem Du jederzeit einen anderen Generator angeben kannst. Und Du musst keinen Config Bean anpassen ... da gibt es dann keine Abhängigkeit zu den existierenden Generatoren.

Oder - so Du unbedingt das in der Art haben willst: Da es ja um eine einmalige Sache geht, könntest Du den kompletten Klassennamen hinterlegen und dann eine neue Instanz erzeugen. Das wäre dann evtl. sowas in der Art (Fehlerbehandlung müsste man noch einfügen):

Java:
    @Value("${generator_class:null}")
    String generatorClass;

    Generator generator = null;
 
    @Bean
//    @Scope(value="singleton") ==> Singleton ist Standard in Spring, daher ist diese Annotation unnötig.
    public Generator getGenerator() {
          if (generator == null) {
            Class c = Class.forName(generatorClass);
            generator = (Generator) c.newInstance();
          }
        return generator;
    }

Bei beiden Varianten hast Du keine Abhängigkeit von einer Klasse zu allen bekannten Generator Implementationen.

Und die Exception wirst du bei Dir und bei meiner letzteren Methode dann nur da abfangen können, wo getGenerator aufgerufen wird.

Bei der ersten Version von mir würde beim Start der Applikation der Bean nicht erzeugt werden können (sowie alle davon abhängigen Beans). Da muss man also beim App Server entsprechend ein Monitoring haben (oder eben bei Updates immer verifizieren

Wie sollte man am besten die ClassNotFoundException behandeln für
Code:
Class c = Class.forName(generatorClass);
wenn z.B. eine nicht existende Klasse angibt?

Außerdem wird mir für
Code:
generator = (Generator) c.newInstance();
newInstance als deprecated angegeben.
 
T

thecain

Top Contributor
Würde ich auch nicht so machen.

Ich denke für dich würde es sich anbieten via Spring Profiles die richtigen Beans zu laden. Mit newInstance sind sie mMn auch nicht sauber im Spring Context.
Siehe: https://www.baeldung.com/spring-profiles

/e xml configs würde ich in aktuellem Versionen auch nicht mehr unbedingt verwenden
 
kneitzel

kneitzel

Top Contributor
Die Frage ist doch: kannst du da sinnvoll etwas machen? Wenn du Generator A und B hast und jemand gibt C an?

Ist das eine Art Eingabe die ständig kommt oder ist das einmalige Konfiguration?

Einmalige Konfiguration solltest du beim Start dem Admin um die Ohren hauen ... so wie es bei der Definition als Bean direkt passiert. Das ist halt etwas, das ordentlich und sorgfältig gemacht werden muss ...
 
S

Schuriko

Bekanntes Mitglied
Würde ich auch nicht so machen.

Ich denke für dich würde es sich anbieten via Spring Profiles die richtigen Beans zu laden. Mit newInstance sind sie mMn auch nicht sauber im Spring Context.
Siehe: https://www.baeldung.com/spring-profiles

/e xml configs würde ich in aktuellem Versionen auch nicht mehr unbedingt verwenden
Ich habe mir https://www.baeldung.com/spring-profiles. Diese bezieht sich allerdings darauf wann eine Bean verwendet werden soll. Deshalb verstehe ich gerad nicht so recht, wie du von meinem Problem hierauf kommst????
 
S

Schuriko

Bekanntes Mitglied
Die Frage ist doch: kannst du da sinnvoll etwas machen? Wenn du Generator A und B hast und jemand gibt C an?

Ist das eine Art Eingabe die ständig kommt oder ist das einmalige Konfiguration?

Einmalige Konfiguration solltest du beim Start dem Admin um die Ohren hauen ... so wie es bei der Definition als Bean direkt passiert. Das ist halt etwas, das ordentlich und sorgfältig gemacht werden muss ...
Im Augenblick soll es erstmal eine einmalige Konfiguration sein, aber ich könnte mir später auch Vorstellen, dass die Eingabe gewechselt wird.
 
T

thecain

Top Contributor
So wie ich deinen Code sehe willst du einen bestimmten Generator anhand eines Properties laden.
Property = Profile
Generator = Bean
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Erstmal zu deinem Code:

Oder wie würdet ihr es realisieren?
Lass in jedem Fall den Check auf null weg. Das ist nicht Thread-Sicher, und wird sowieso von Spring behandelt.

Und wo sollte ich die InvalidArgumentException abfangen bzw. bearbeiten?
Gar nicht - wenn der Entwickler die Anwendung nicht korrekt konfiguriert, muss die nicht starten, sondern kann ruhig mit Exception beendet werden.
Die Exception sollte aber sinnvoller gewählt werden, mindestens mit einer vernünftigen Message, tendenziell aber auch mit anderem Typ (da ja an der Stelle kein Argument übergeben wird).



Dann wie man es anders lösen könnte:

Generell Type-safe Configuration Properties dafür nutzen.
Statt magischen Strings einen Enum dafür nutzen.
Der enum kann dann auch einfach eine public Generator getGenerator bekommen, dann ist kein switch oä mehr nötig.
Ein von der Properties-Klasse getrennter Provider, der die Properties-Klasse injiziert bekommt, und über [USER=22881]@Bean[/USER] den jeweiligen Generator verfügbar macht.
Den Provider mit @ConditionalOnMissingBean annotieren, damit man die Bean einfach überschrieben kann.


Grob so: (vermutlich voller Fehler, aber als Idee sollte das reichen)
Java:
@ConfigurationProperties("...")
public class GeneratorProperties {
    Type generator;

    public enum Type {
        A {
            Generator getGenerator() {
                return ...;
            }
        }, B {
            @Override
            Generator getGenerator() {
                return ...
            }
        };

        abstract Generator getGenerator();
    }
}

Java:
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(Generator.class) 
    public Generator generator() {
        return generatorProperties.type.getGenerator();
    }
}
 
T

thecain

Top Contributor
Test, dev, prod sind ja nur Beispiele. das könnte auch hund, katze oder huhn sein...

Aber mit dem Vorschlag von @mrBrown solltest du ja jetzt genug Ideen und Ansätze haben um es so umzusetzen wie du willst.

Sonst musst du den Use-Case noch genauer vorstellen.
 
S

Schuriko

Bekanntes Mitglied
Erstmal zu deinem Code:


Lass in jedem Fall den Check auf null weg. Das ist nicht Thread-Sicher, und wird sowieso von Spring behandelt.


Gar nicht - wenn der Entwickler die Anwendung nicht korrekt konfiguriert, muss die nicht starten, sondern kann ruhig mit Exception beendet werden.
Die Exception sollte aber sinnvoller gewählt werden, mindestens mit einer vernünftigen Message, tendenziell aber auch mit anderem Typ (da ja an der Stelle kein Argument übergeben wird).



Dann wie man es anders lösen könnte:

Generell Type-safe Configuration Properties dafür nutzen.
Statt magischen Strings einen Enum dafür nutzen.
Der enum kann dann auch einfach eine public Generator getGenerator bekommen, dann ist kein switch oä mehr nötig.
Ein von der Properties-Klasse getrennter Provider, der die Properties-Klasse injiziert bekommt, und über [USER=22881]@Bean[/USER] den jeweiligen Generator verfügbar macht.
Den Provider mit @ConditionalOnMissingBean annotieren, damit man die Bean einfach überschrieben kann.


Grob so: (vermutlich voller Fehler, aber als Idee sollte das reichen)
Java:
@ConfigurationProperties("...")
public class GeneratorProperties {
    Type generator;

    public enum Type {
        A {
            Generator getGenerator() {
                return ...;
            }
        }, B {
            @Override
            Generator getGenerator() {
                return ...
            }
        };

        abstract Generator getGenerator();
    }
}

Java:
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(Generator.class)
    public Generator generator() {
        return generatorProperties.type.getGenerator();
    }
}
Ich kann aus deinem Beispiel nicht erkennen, an welcher Stelle aus der Datei "app.properties" der Wert gelesen wird und anhand dessen entschieden wird welcher Generator benutzt werden soll.
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Ich kann aus deinem Beispiel nicht erkennen, an welcher Stelle aus der Datei "app.properties" der Wert gelesen wird und anhand dessen entschieden wird welcher Generator benutzt werden soll.

Guck die mal den Link an, der dabei steht :)

Aus @ConfigurationProperties und dem Attribut-Namen wird der Key in der properties Datei gebildet, Der Wert des Attributes ist dann der dort eingetragene Wert.
(Wenn man das "..." dort ersetzt "xyz" führt ein "xyz.generator=A" dazu, dass da Generator-Feld zur Laufzeit Type.A enthält).

In GeneratorProvider wird das dann benutzt, in generator() wird einfach nur die getGenerator-Methode des Enums aufgerufen, der gibt dann den Generator zurück. (alle "..." müssen dafür natürlich noch sinnvoll gefühlt werden)
 
S

Schuriko

Bekanntes Mitglied
Test, dev, prod sind ja nur Beispiele. das könnte auch hund, katze oder huhn sein...

Aber mit dem Vorschlag von @mrBrown solltest du ja jetzt genug Ideen und Ansätze haben um es so umzusetzen wie du willst.

Sonst musst du den Use-Case noch genauer vorstellen.
Ok, also ich arbeite an einem Editor, dieser verwendet verschiedene Generatoren, abhängig von der Konfiguration. Aus den jeweiligen Generatoren erhalte ich bestimmte feste Werte und Funktionen. Diese Funktionen verwendet gleiche Funktionen, die allerdings unterschiedliches zurückliefern.

Diese Generatoren werden dann von Funktionen einer Service-Klasse verwendet.

Am Anfang ist es erst einmal angedacht, dass diese beim starten der Web-Anwendung durchgeführt am Anfang zur Verfügung gestellt wird. Es ist allerdings später auch denkbar, dass während der Laufzeit die Generatoren gewechselt werden können.

Ich hoffe ich konnte mich einigermassen verständlich ausdrücken ;)
 
kneitzel

kneitzel

Top Contributor
Also erst einmal zu dem newInstance - das ist tatsächlich ab Java9 deprecated (zeigt, wie lange ich das nicht genutzt habe.... man nutzt in der Regel andere Lösungen) - aber das ist doch trivial zu lösen und Google liefert da schnell den neuen weg:
Und mittels getConstructor().newInstance() fuktioniert es dann ab Java 9.

Ich habe nicht genau verstanden, was der Generator im Editor erzeugen soll, aber wenn Du da einen Editor hast und es diverse Generatoren gibt:
a) Einmalige Konfiguration scheint mir da ungünstig. Angenommen, das generiert Textbausteine. Dann will ich vielleicht Java Bausteine und jemand anderes C# Bausteine. Ich würde sogar so weit gehen, dass ich das nicht einmal für mich festgelegt haben möchte: Ich brauche in einem Tab Java Bausteine und in einem anderen XML Bausteine....
b) Wenn Du so ein tolles Interface hast, dann klingt das gerade zu nach einer tollen Möglichkeit, dies erweitern zu können. Nehmen wir das Beispiel oben: Du hast Generatoren für Java und XML. C# und so interessieren Dich nicht. Dann wäre es doch super, wenn Andere auch Generatoren entwickeln und hinzufügen könnten ohne Deinen Code ändern zu müssen!

(Die Idee von @mrBrown ist die Lösung / Idee, die sehr schön ist, wenn man eine klare, feste Menge an Elementen hat. Aber es muss halt diese feste Menge an Elementen geben. Aber die Frage ist immer, was die genauen Anforderungen sind um daraus abzuleiten, was man machen möchte der muss. Wenn das neue Generatoren hinzufügen für Dich erst einmal egal ist, dann brauchst Du diese Ideen nicht. Aber wie gesagt: Die Festlegung auf einen Generator scheint mit auf Applikationsebene nicht logisch - oder ich habe nicht verstanden, was Du da genau editieren / generieren willst....)

Aber generell hast Du jetzt ganz viele Optionen und Möglichkeiten aus denen Du auswählen kannst. Welche Variante zu Deinen Anforderungen am Besten passt musst Du entscheiden / wissen.
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Also erst einmal zu dem newInstance - das ist tatsächlich ab Java9 deprecated (zeigt, wie lange ich das nicht genutzt habe.... man nutzt in der Regel andere Lösungen) - aber das ist doch trivial zu lösen und Google liefert da schnell den neuen weg:
Und mittels getConstructor().newInstance() fuktioniert es dann ab Java 9.
Würde ich im Spring (oder EE) Kontext aber beides nicht benutzen, dabei sollte man die immer vom jeweiligen Framework erzeugen lassen, damit man zB andere Beans injiziert bekommt.

Die Idee von @mrBrown ist die Lösung / Idee, die sehr schön ist, wenn man eine klare, feste Menge an Elementen hat. Aber es muss halt diese feste Menge an Elementen geben.

Jein, nur die feste Menge an Elementen kann man über die Konfiguration angeben. Wenn man eine andere Generator-Klasse nutzen will, klappt das einfach über eine eigene [USER=22881]@Bean[/USER] Generator generator() { return new MeinNeuerGenerator();} und das bestehende wird überschrieben.
 
kneitzel

kneitzel

Top Contributor
Würde ich im Spring (oder EE) Kontext aber beides nicht benutzen, dabei sollte man die immer vom jeweiligen Framework erzeugen lassen, damit man zB andere Beans injiziert bekommt.

Da bin ich auf jeden Fall ganz Deiner Meinung. Ich finde die Lösung, das über eine Spring Konfiguration zu lösen, auch deutlich besser. Aber nach dem Hinweis bzgl. des Deprecated wollte ich den Weg zumindest kurz ohne deprecated Methoden skizzieren.

Jein, nur die feste Menge an Elementen kann man über die Konfiguration angeben. Wenn man eine andere Generator-Klasse nutzen will, klappt das einfach über eine eigene [USER=22881]@Bean[/USER] Generator generator() { return new MeinNeuerGenerator();} und das bestehende wird überschrieben.
Ja stimmt, daran habe ich nicht gedacht. Aber klar: Wenn einem die Möglichkeiten der "mitgelieferten" Generatoren nicht zusagt, dann könnte man natürlich diesen ganzen Bean austauschen um dann den eigenen Generator so einzubringen.
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Da bin ich auf jeden Fall ganz Deiner Meinung. Ich finde die Lösung, das über eine Spring Konfiguration zu lösen, auch deutlich besser. Aber nach dem Hinweis bzgl. des Deprecated wollte ich den Weg zumindest kurz ohne deprecated Methoden skizzieren.
Das newInstance könnte man mit BeanFactory#getBean ersetzen, dann hätte man weiterhin die Flexibilität mit dem Klassennamen, aber es wird trotzdem über Spring initialisiert :)
 
kneitzel

kneitzel

Top Contributor
Das newInstance könnte man mit BeanFactory#getBean ersetzen, dann hätte man weiterhin die Flexibilität mit dem Klassennamen, aber es wird trotzdem über Spring initialisiert :)
Die Frage ist, ob man dies als Bean haben möchte. Diese Alternative habe ich ja eigentlich nur gebracht, falls er da aus irgendwelchen Gründen da eben diese Klassen nicht als Beans handhaben möchte (Und da braucht es keinen Bean, der mir dann einen Bean aus einer Konfigurationsdatei gibt.... Das hat man doch alles so man es haben möchte...).

Aber das ganze Szenario erscheint mir immer noch etwas dubios und den Sinn verstehe ich noch nicht wirklich. Aber er hat auf jeden Fall 3 interessante Lösungen bekommen, von denen er sich eine aussuchen kann: Beans direkt im XML File konfigurieren, die Profile (mit denen habe ich selbst auch noch nicht wirklich gearbeitet - also auch für mich ein sehr interessanter Hinweis!) und Dein Vorschlag mit der Enumeration.
 
S

Schuriko

Bekanntes Mitglied
Erstmal zu deinem Code:


Lass in jedem Fall den Check auf null weg. Das ist nicht Thread-Sicher, und wird sowieso von Spring behandelt.


Gar nicht - wenn der Entwickler die Anwendung nicht korrekt konfiguriert, muss die nicht starten, sondern kann ruhig mit Exception beendet werden.
Die Exception sollte aber sinnvoller gewählt werden, mindestens mit einer vernünftigen Message, tendenziell aber auch mit anderem Typ (da ja an der Stelle kein Argument übergeben wird).



Dann wie man es anders lösen könnte:

Generell Type-safe Configuration Properties dafür nutzen.
Statt magischen Strings einen Enum dafür nutzen.
Der enum kann dann auch einfach eine public Generator getGenerator bekommen, dann ist kein switch oä mehr nötig.
Ein von der Properties-Klasse getrennter Provider, der die Properties-Klasse injiziert bekommt, und über [USER=22881]@Bean[/USER] den jeweiligen Generator verfügbar macht.
Den Provider mit @ConditionalOnMissingBean annotieren, damit man die Bean einfach überschrieben kann.


Grob so: (vermutlich voller Fehler, aber als Idee sollte das reichen)
Java:
@ConfigurationProperties("...")
public class GeneratorProperties {
    Type generator;

    public enum Type {
        A {
            Generator getGenerator() {
                return ...;
            }
        }, B {
            @Override
            Generator getGenerator() {
                return ...
            }
        };

        abstract Generator getGenerator();
    }
}

Java:
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(Generator.class)
    public Generator generator() {
        return generatorProperties.type.getGenerator();
    }
}
Gehe ich recht in der Annahme, dass Type von
Code:
import java.lang.reflect.Type;
ist?
 
S

Schuriko

Bekanntes Mitglied
Ich habe mir mal die Seite https://www.baeldung.com/spring-getbean durchgelesen.

Das Beispiel:
Code:
@Configuration
class AnnotationConfig {
 
    @Bean(name = {"tiger", "kitty"})
    @Scope(value = "prototype")
    Tiger getTiger(String name) {
        return new Tiger(name);
    }
 
    @Bean(name = "lion")
    Lion getLion() {
        return new Lion("Hardcoded lion name");
    }
 
    interface Animal {}
}

scheint das Abzubilden, was ich versuche zu realisieren, allerdings wie bekomme ich aus meiner app.properties die Werte, in diesem Falle "tiger", "lion" und Co. übermittelt. Dazu fehlt mir noch etwas das Grundverständnis.
 
S

Schuriko

Bekanntes Mitglied
Ich habe mir mal die Seite https://www.baeldung.com/spring-getbean durchgelesen.

Das Beispiel:
Code:
@Configuration
class AnnotationConfig {

    @Bean(name = {"tiger", "kitty"})
    @Scope(value = "prototype")
    Tiger getTiger(String name) {
        return new Tiger(name);
    }

    @Bean(name = "lion")
    Lion getLion() {
        return new Lion("Hardcoded lion name");
    }

    interface Animal {}
}

scheint das Abzubilden, was ich versuche zu realisieren, allerdings wie bekomme ich aus meiner app.properties die Werte, in diesem Falle "tiger", "lion" und Co. übermittelt. Dazu fehlt mir noch etwas das Grundverständnis.
Ups, übersehen, dass die Funktion ja gleich heissen muss
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Ups, übersehen, dass die Funktion ja gleich heissen muss
Ne, muss sie nicht - ist allerdings was völlig anderes, als die anderen Varianten:

Ich habe mir mal die Seite https://www.baeldung.com/spring-getbean durchgelesen.

Das Beispiel [...] scheint das Abzubilden, was ich versuche zu realisieren, allerdings wie bekomme ich aus meiner app.properties die Werte, in diesem Falle "tiger", "lion" und Co. übermittelt. Dazu fehlt mir noch etwas das Grundverständnis.

Damit hast du 3 Beans vom Typ Animal verfügbar: zwei Objekte vom Typ Tiger, jeweils mit dem Bean-Namen "tiger" und "kitty" und ein Objekt vom Typ Lion, mit dem Bean-Namen "lion".

In den bisherigen Varianten hier hast du dann genau eine Bean vom Typ Generator, die entweder ein Objekt von GeneratorA oder GeneratorB ist.
 
S

Schuriko

Bekanntes Mitglied
Ich habe es jetzt das Beispiel von mrBrown auf meine Anforderungen umgesetzt:

Code:
@ConfigurationProperties("...")
public class GeneratorProperties {
    Type generator;

    public enum Type {
        A {
            Generator getGenerator() {
                return ...;
            }
        }, B {
            @Override
            Generator getGenerator() {
                return ...
            }
        };

        abstract Generator getGenerator();
    }
}
Code:
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(Generator.class)
    public Generator generator() {
        return generatorProperties.type.getGenerator();
    }
}
Wie greife ich den jetzt von außen, konkret meine Service - Klasse, darauf zu?
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Einfach nen Generator injizieren lassen, zB @Autowired Generator generator
 
S

Schuriko

Bekanntes Mitglied
Ich habe dieses mal umgesetzt
Code:
package com.editor.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

@Configuration
@PropertySource("classpath:app.properties")
public class GeneratorProperties {
    Type generator;

    public enum Type {
        GeneratorA {
            Generator getGenerator() {
                return new GeneratorA();
            }
        };

        abstract Generator getGenerator();
    }
}

Code:
package com.editor.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(GeneratorA.class)
    public Generator generator() {
        return generatorProperties.generator.getGenerator();
    }
}

Code:
package com.editor.helpers.generator;

public abstract class Generator {

    public static String getString( String base_directory ) {
        return null;
    }
   
    public static State getIState() {
        return null;
    }
}

und in com.editor.helpers.generator
Code:
package com.editor.helpers.generator;

public abstract class Generator {

    public static String getName() {
        return null;
    }  
}

und
Code:
package com.editor.helpers.generator;

public class GeneratorA extends Generator {
    public static String getName() {
        return "GeneratorA";
    }
}

mit der app.properties im src/main/resource
Code:
generator = generatora

start über
Code:
package com.editor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties
public class EditorApplication {

    public static void main(String[] args) {
        SpringApplication.run(EditorApplication.class, args);
    }

}

wird beim Ausführen in der Console folgendes ausgegeben
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.2.RELEASE)

2020-01-15 05:05:02.319 INFO 9956 --- [ restartedMain] com.editor.BuilderApplication : Starting BuilderApplication on Tommys-Rechner with PID 9956 (C:\Projekte\java\git\Builder\Builder\target\classes started by tomth in C:\Projekte\java\git\Builder\Builder)
2020-01-15 05:05:02.321 INFO 9956 --- [ restartedMain] com.editor.BuilderApplication : No active profile set, falling back to default profiles: default
2020-01-15 05:05:02.356 INFO 9956 --- [ restartedMain] o.s.b.devtools.restart.ChangeableUrls : The Class-Path manifest attribute in C:\Users\tomth\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.2\jaxb-runtime-2.3.2.jar referenced one or more files that do not exist: file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/jakarta.xml.bind-api-2.3.2.jar,file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/txw2-2.3.2.jar,file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/istack-commons-runtime-3.0.8.jar,file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/stax-ex-1.8.1.jar,file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/FastInfoset-1.2.16.jar,file:/C:/Users/tomth/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/jakarta.activation-api-1.2.1.jar
2020-01-15 05:05:02.357 INFO 9956 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-01-15 05:05:02.357 INFO 9956 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-01-15 05:05:02.781 INFO 9956 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-01-15 05:05:02.828 INFO 9956 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 41ms. Found 2 JPA repository interfaces.
2020-01-15 05:05:03.041 INFO 9956 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-01-15 05:05:03.257 INFO 9956 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-01-15 05:05:03.263 INFO 9956 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-01-15 05:05:03.263 INFO 9956 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-01-15 05:05:03.376 INFO 9956 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-01-15 05:05:03.376 INFO 9956 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1019 ms
2020-01-15 05:05:03.486 INFO 9956 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-01-15 05:05:03.546 INFO 9956 --- [ restartedMain] org.hibernate.Version : HHH000412: Hibernate Core {5.4.9.Final}
2020-01-15 05:05:03.638 INFO 9956 --- [ restartedMain] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-01-15 05:05:03.710 INFO 9956 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-01-15 05:05:03.809 INFO 9956 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-01-15 05:05:03.817 INFO 9956 --- [ restartedMain] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: drop table if exists languages
Hibernate: drop table if exists user
Hibernate: create table languages (id bigint not null auto_increment, created_at datetime, iso varchar(255) not null, name varchar(255) not null, updated_at datetime, created_by bigint, updated_by bigint, primary key (id)) engine=MyISAM
Hibernate: create table user (id bigint not null auto_increment, created_at datetime, email varchar(255), firstname varchar(255), lastname varchar(255), password varchar(255), updated_at datetime, created_by bigint, updated_by bigint, primary key (id)) engine=MyISAM
Hibernate: alter table languages add constraint FK6pb75mfcy4xyf5olu4j0abcoi foreign key (created_by) references user (id)
Hibernate: alter table languages add constraint FKn3mumfixnk1277loo0yy5lc4l foreign key (updated_by) references user (id)
Hibernate: alter table user add constraint FKdltbr5t0nljpuuo4isxgslt82 foreign key (created_by) references user (id)
Hibernate: alter table user add constraint FK2a54xhceitopkkw1hlo3tkv3i foreign key (updated_by) references user (id)
2020-01-15 05:05:04.389 INFO 9956 --- [ restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-01-15 05:05:04.394 INFO 9956 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-01-15 05:05:04.417 INFO 9956 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2020-01-15 05:05:04.471 WARN 9956 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'localizationService': Unsatisfied dependency expressed through field 'generator'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.editor.helpers.generator.Generator' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2020-01-15 05:05:04.471 INFO 9956 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-01-15 05:05:04.474 INFO 9956 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-01-15 05:05:04.542 INFO 9956 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2020-01-15 05:05:04.544 INFO 9956 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2020-01-15 05:05:04.551 INFO 9956 --- [ restartedMain] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-01-15 05:05:04.635 ERROR 9956 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :

***************************
APPLICATION FAILED TO START
***************************

Description:

Field generator in com.editor.service.LocalizationService required a bean of type 'com.editor.helpers.generator.Generator' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.editor.helpers.generator.Generator' in your configuration.

Verstehe gerad nicht was hier schieflläuft
 
Zuletzt bearbeitet:
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
  • GeneratorProperties sollte nicht mit Configuration und PropertySource annotiert sein, sondern mit ConfigurationProperties. Musst dann nur einen Präfix angeben, und gibst das dann in den ganz normalem Properties mit präfix.generator = xyz an. Das ganze muss dann noch explizit aktiviert werden mit EnableConfigurationProperties an deiner Haupt-Klasse
  • xyz muss nicht irgendein beliebiger String sein, sondern dem Enum entsprechen. Wenn du den Enum 'A' nennst, sollte es auch A sein, nicht "generatora"
  • ConditionalOnMissingBean muss das Interface/die Abstrakte Klasse angeben, nicht eine konkrete Implementierung
  • (abstrakte Klassen brauchst du nahezu nie, nimm stattdessen einfach ein Interface dafür)
  • src/main/resource ist vermutlich nur ein Tippfehler?
  • GeneratorProvider sollte noch mit Configuration annotiert werden (fehlte in meinem Beispiel auch)


Ist dir generell bewusst, was für eine Auswirkung die statischen Methoden in Generator und den Subklassen haben?
 
S

Schuriko

Bekanntes Mitglied
Bei mir sieht es jetzt wie folgt aus:
Code:
package com.editor.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

@ConfigurationProperties(prefix = "generator")
@PropertySource("classpath:app.properties")
public class GeneratorProperties {
    Type type;

    public enum Type {
        GeneratorA {
            Generator getGenerator() {
                return new GeneratorA();
            }
        };

        abstract Generator getGenerator();
    }
}

Code:
package com.editor.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

@Configuration
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(GeneratorA.class)
    public Generator generator() {
        return generatorProperties.generator.getGenerator();
    }
}

Code:
package com.editor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties
public class EditorApplication {

    public static void main(String[] args) {
        SpringApplication.run(EditorApplication.class, args);
    }

}

Code:
framework.type = GENERATORA

Code:
package com.editor.helpers.generator;

public interface Generator {
       String getName( );
 }

Code:
package com.editor.helpers.generator;

public class GeneratorA implements Generator {
    public String getName() {
        return "GeneratorA";
    }
}

  • xyz muss nicht irgendein beliebiger String sein, sondern dem Enum entsprechen. Wenn du den Enum 'A' nennst, sollte es auch A sein, nicht "generatora"
Ist hierbei die Groß-/Kleinschreibung zu beachten? Wenn ja, wie könnte ich es erreichen, dass die Groß-/Kleinschreibung egal wäre?

Ist dir generell bewusst, was für eine Auswirkung die statischen Methoden in Generator und den Subklassen haben?
Stimmt. Darüber hatte ich noch gar nicht nachgedacht. Verwende keine statischen Funktionen mehr in den Klassen.

Beim Compilieren erhalte ich immer noch die Ausgabe
***************************
APPLICATION FAILED TO START
***************************

Description:

Field generator in com.editor.service.LocalizationService required a bean of type 'com.editor.helpers.generator.Generator' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.editor.helpers.generator.Generator' in your configuration.
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Du solltest auch alle Anmerkungen umsetzen, wenn du die Hälfte ignorierst und dafür andere Dinge machst, klappt das natürlich nicht ;)

  • PropertySource kann erstmal weg, nimm einfach die normalem application.properties dafür
  • Den angegeben Präfix solltest du auch nutzen. Du gibst "generator" an, nutzt es dann aber als "framework.type"
  • Als "MissingBean" solltest du nicht GeneratorA angeben, sondern "Generator"
  • GeneratorProperties musst du explizit aktivieren oder an deiner Haupt-Klasse zusätzlich @ConfigurationPropertiesScan angeben


  • Ist hierbei die Groß-/Kleinschreibung zu beachten? Wenn ja, wie könnte ich es erreichen, dass die Groß-/Kleinschreibung egal wäre?
  • Groß-/Kleinschreibung ist egal, du solltest aber nicht den Enum "A" und die property "generatora" nennen

Beim Compilieren erhalte ich immer noch die Ausgabe
Nicht beim Kompilieren, beim Ausführen.
 
S

Schuriko

Bekanntes Mitglied
Jetzt verstehe ich gar nichts mehr. Sehe vor lauter Bäumen den Wald wohl nicht mehr:

src/main/resources/application.properties
Code:
generator.type = GENERATORA

Main
Code:
package com.editor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties
@ConfigurationPropertiesScan
public class EditorApplication {

    public static void main(String[] args) {
        SpringApplication.run(EditorApplication.class, args);
    }

}

Generator Interface
Code:
package com.editor.helpers.generator;

public interface Generator {
    String getName( );
}

GeneratorA
Code:
package com.editor.helpers.generator;

public class GeneratorA implements Generator {
    public String getName() {
        return "GeneratorA";
    }
}

GeneratorProperties
Code:
package com.editor.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

@ConfigurationProperties(prefix = "generator")
public class GeneratorProperties {
    Type type;

    public enum Type {
        GeneratorA {
            Generator getGenerator() {
                return new GeneratorA();
            }
        };

        abstract Generator getGenerator();
    }
}

GeneratorProvider
Code:
package com.editor.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.editor.helpers.generator.Generator;
import com.editor.helpers.generator.GeneratorA;

@Configuration
public class GeneratorProvider {
    @Autowired
    GeneratorProperties generatorProperties;

    @Bean
    @ConditionalOnMissingBean(GeneratorA.class)
    public Generator generator() {
        return generatorProperties.type.getGenerator();
    }
}

Compilierung:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.2.RELEASE)

2020-01-15 19:33:44.846 INFO 25756 --- [ restartedMain] com.editor.EditorApplication : Starting EditorApplication on Tommys-Rechner with PID 25756 (C:\Projekte\java\Editor\target\classes started by tomth in C:\Projekte\java\Editor)
2020-01-15 19:33:44.847 INFO 25756 --- [ restartedMain] com.editor.EditorApplication : No active profile set, falling back to default profiles: default
2020-01-15 19:33:44.875 INFO 25756 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-01-15 19:33:45.136 WARN 25756 --- [ restartedMain] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'generator' defined in class path resource [com/editor/config/GeneratorProvider.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.editor.helpers.generator.Generator]: Factory method 'generator' threw exception; nested exception is java.lang.NullPointerException
2020-01-15 19:33:45.141 INFO 25756 --- [ restartedMain] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-01-15 19:33:45.149 ERROR 25756 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'generator' defined in class path resource [com/editor/config/GeneratorProvider.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.editor.helpers.generator.Generator]: Factory method 'generator' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at com.editor.EditorApplication.main(EditorApplication.java:14) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.editor.helpers.generator.Generator]: Factory method 'generator' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 23 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.editor.config.GeneratorProvider.generator(GeneratorProvider.java:19) ~[classes/:na]
at com.editor.config.GeneratorProvider$$EnhancerBySpringCGLIB$$ae9b9c5f.CGLIB$generator$0(<generated>) ~[classes/:na]
at com.editor.config.GeneratorProvider$$EnhancerBySpringCGLIB$$ae9b9c5f$$FastClassBySpringCGLIB$$4391d635.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at com.editor.config.GeneratorProvider$$EnhancerBySpringCGLIB$$ae9b9c5f.generator(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 24 common frames omitted
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Mach das Feld Type type mal private und ergänz Getter und Setter (hätte ich explizit sagen sollen...)
 
Zuletzt bearbeitet:
S

Schuriko

Bekanntes Mitglied
Hierfür habe ich eine Service Klasse erstellt
Code:
package com.editor.services;

import org.springframework.beans.factory.annotation.Autowired;

import com.editor.helpers.generator.Generator;

public class GeneratorService {
    
    @Autowired
    Generator generator;
    
    public String getName() {
        return generator.getName();
    }
}
Compelierung und Ausführung funktioniert.

Jetzt wollte ich eine Test Funktion ausführen
Code:
package com.editor.services;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class GeneratorServiceTest {

    @Autowired
    GeneratorService generatorService;
    
    @Test
    void testGetName() {
        String generator = "GeneratorA";

        assertTrue(generatorService.getName().equals( generator ));
    }
}
Beim Ausführen des Test wird mir gesagt:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.editor.services.GeneratorServiceTest': Unsatisfied dependency expressed through field 'generatorService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.editor.services.GeneratorService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:98)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$5(ClassBasedTestDescriptor.java:337)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:342)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:337)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:336)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:259)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:252)
at java.base/java.util.Optional.orElseGet(Optional.java:369)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:251)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:29)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:107)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:107)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:75)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.editor.services.GeneratorService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1695)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1253)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
... 69 more

Console:
...
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.editor.services.GeneratorServiceTest': Unsatisfied dependency expressed through field 'generatorService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.editor.services.GeneratorService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119) ~[spring-test-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43) ~[spring-boot-test-autoconfigure-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244) ~[spring-test-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:98) ~[spring-test-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$5(ClassBasedTestDescriptor.java:337) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:342) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:337) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) ~[na:na]
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) ~[na:na]
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) ~[na:na]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:336) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:259) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:252) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na]
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:251) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:29) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69) ~[junit-jupiter-engine-5.5.2.jar:5.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:107) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:107) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:75) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) ~[junit-platform-engine-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) ~[.cp/:na]
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197) ~[.cp/:na]
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) ~[.cp/:na]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) ~[.cp/:na]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137) ~[.cp/:na]
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209) ~[.cp/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.editor.services.GeneratorService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1695) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1253) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 69 common frames omitted
Weis jemand was hier gerade schief läuft?
 

Anhänge

  • Editor.zip
    70 KB · Aufrufe: 0
S

Schuriko

Bekanntes Mitglied
Hast natürlich vollkommen recht. Ist wohl schon zu spät. Muss wohl langsam ins Bett :D:D:D
Es funktioniert jetzt vollständig.

Danke @All
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Value Wert aus HTML-Button mittels thymeleaf spring an java übergeben Allgemeine Java-Themen 0
Meeresgott Effizientester Weg um nach der Value einer verschachtelten Map aufzulösen Allgemeine Java-Themen 5
Thallius Key/Value Table in Klasse einlesen Allgemeine Java-Themen 14
H Klassen LibGDX - Verschiedene Klassen als Value in einer Map Allgemeine Java-Themen 8
B HashMap aus Value Key bekommen Allgemeine Java-Themen 2
F Unterschied zwischen NormalizedValue und Value Allgemeine Java-Themen 5
Q For-Schleife in String-Value Allgemeine Java-Themen 3
L Variablen HashMap nimmt value nicht an Allgemeine Java-Themen 3
M Java - Call by value <-> Call by reference Allgemeine Java-Themen 16
B Load of Known null Value Allgemeine Java-Themen 9
T Hashmap mit geordneter/ungeordneter liste als Value Allgemeine Java-Themen 5
algorismi int-variable Value Change event Allgemeine Java-Themen 3
G HTTP key-value-paar Allgemeine Java-Themen 8
J Map nach value sortieren Allgemeine Java-Themen 14
G Verschachtelte Treemaps, nach Value sortieren Allgemeine Java-Themen 11
faetzminator Regex zur Suche von "value-losen" Attributen in HTML Tags Allgemeine Java-Themen 7
B Set.contains() auch false wenn value == null? Allgemeine Java-Themen 4
G Generics in Map. Type of value abhängig vom key Allgemeine Java-Themen 3
S Map die die auch ein getKey(value) erlaubt? Allgemeine Java-Themen 2
MQue call by value Allgemeine Java-Themen 5
F Javadoc: @value tag nicht für private fields? Allgemeine Java-Themen 11
P call by value/referenz Allgemeine Java-Themen 4
N Sieht aus wie ein "Call by Referece/Call by Value" Allgemeine Java-Themen 7
S Call by Value Allgemeine Java-Themen 9
T [TreeMap] Corresponding value to a key Allgemeine Java-Themen 10
V Objekt aus Session als copy by value bekommen Allgemeine Java-Themen 4
R Wert in Hashtable ändern (Key ändern, Value bleibt) Allgemeine Java-Themen 3
H Aus der FAQ: Call by Value <-> Call by Reference Allgemeine Java-Themen 8
C Map(Key/Value) mit mehreren Values Allgemeine Java-Themen 16
M Value als String in beliebige Klasse konvertieren Allgemeine Java-Themen 18
Fredy Return by value mit String?? Allgemeine Java-Themen 6
S Test mit Werten aus der .properties Allgemeine Java-Themen 4
Zrebna Random Number - Generische Formel zwischen zwei INKLUSIVEN Werten Allgemeine Java-Themen 16
O Variablen Addition von Double-Werten ergibt seltsame 0.9999999 Zahlen Allgemeine Java-Themen 2
Z Array mit unterschiedlichen Werten Allgemeine Java-Themen 1
B Verteilungs-/Vergabe-Algorithmus mit abhängigen Score-Werten Allgemeine Java-Themen 3
L einfache Verzinsung mit for-Schleife & Ausschluss von Werten beim Einlesen Allgemeine Java-Themen 5
T Sechsecke, erkennen von bestimmten Werten Allgemeine Java-Themen 9
I Datentypen Mögliche Auswahl an Werten Allgemeine Java-Themen 4
I 2D-Grafik Polygon mit Double Werten zeichnen Allgemeine Java-Themen 4
S Baum mit vordefinierten Werten befüllen Allgemeine Java-Themen 2
M Problem mit return-werten Allgemeine Java-Themen 35
O Problem bei der Umwandlung von Hex-Werten Allgemeine Java-Themen 5
T Wurfweitenberechnung: X-Werte bei extremen Werten falsch. Allgemeine Java-Themen 15
A Problem bei Übergabe von Werten in ein double Array. Allgemeine Java-Themen 21
N Array mit null Werten filtern Allgemeine Java-Themen 5
W sin und cos bei hohen Werten extrem langsam Allgemeine Java-Themen 12
MQue zwischen Class zum speichern von Werten Allgemeine Java-Themen 4
S Problem beim Einlesen von byte-werten aus datei Allgemeine Java-Themen 2
G JComboBox mit Werten aus einer Access Datenbank füllen Allgemeine Java-Themen 18
G Einfügen von Werten aus TXT-Datei in ein Array !?! Allgemeine Java-Themen 9

Ähnliche Java Themen

Anzeige

Neue Themen


Oben