Spring kann die Bean-XML-Konfigurationsdatei nicht finden, wenn sie vorhanden ist

75

Ich versuche meine erste Bohne im Frühling zu machen, habe aber ein Problem beim Laden eines Kontexts. Ich habe eine XML-Konfigurationsdatei der Bean in src / main / resources.

Ich erhalte die folgende IOException:

Ausnahme im Thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException analysiert XML-Dokument aus Klassenpfadressource [src / main / resources / beans.xml]; verschachtelte Ausnahme ist

java.io.FileNotFoundException: Die Klassenpfadressource [src / main / resources / beans.xml] kann nicht geöffnet werden, da sie nicht vorhanden ist

aber ich verstehe es nicht, da ich den folgenden Codetest mache:

File f = new File("src/main/resources/beans.xml");
System.out.println("Exist test: " + f.exists());

das gibt mir wahr! resourcesist im Klassenpfad. Was ist los?

dawrutowicz
quelle
Wie lade ich den Kontext?
Aleksandr M

Antworten:

164

Danke, aber das war nicht die Lösung. Ich fand heraus, warum es bei mir nicht funktionierte.

Da ich eine Erklärung abgegeben hatte:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Ich dachte, ich würde auf das Stammverzeichnis des Projekts verweisen, wenn die Datei beans.xml vorhanden war. Dann habe ich die Konfigurationsdatei in src / main / resources abgelegt und die Initialisierung geändert in:

ApplicationContext context = new ClassPathXmlApplicationContext("src/main/resources/beans.xml");

Es war immer noch eine IO-Ausnahme.

Dann wurde die Datei in src / main / resources / belassen, aber ich habe die Deklaration geändert in:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

und es hat das Problem gelöst - vielleicht ist es für jemanden hilfreich.

danke und Prost!

Bearbeiten:

Da ich viele Leute für die Lösung begebe und vor einigen Jahren als Student erste Erfahrungen mit Spring gemacht habe, möchte ich kurz erklären, warum es funktioniert.

Wenn das Projekt kompiliert und gepackt wird, werden alle Dateien und Unterverzeichnisse von 'src / main / java' im Projekt in das Stammverzeichnis des gepackten JARs (das Artefakt, das wir erstellen möchten) verschoben. Die gleiche Regel gilt für 'src / main / resources'.

Dies ist eine Konvention, die von vielen Tools wie maven oder sbt beim Erstellen eines Projekts eingehalten wird (Hinweis: als Standardkonfiguration!). Wenn sich Code (aus dem Beitrag) im laufenden Modus befand, konnte er nichts wie "src / main / resources / beans.xml" finden, da sich beans.xml im Stammverzeichnis von jar befand (kopiert nach / bean) .xml im erstellten jar / ear / war).

Bei Verwendung von ClassPathXmlApplicationContext lautete die richtige Speicherortdeklaration für Beans-XML-Definitionen in diesem Fall "/beans.xml", da dies der Pfad ist, zu dem er in jar und später in classpath gehört.

Sie kann überprüft werden, indem Sie ein Glas mit einem Archivierungsprogramm (dh rar) entpacken und dessen Inhalt anhand der Verzeichnisstruktur anzeigen.

Ich würde empfehlen, Artikel über classpath als Ergänzung zu lesen.

dawrutowicz
quelle
Ich sehe den Unterschied zwischen ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");undApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Florian F
1
@FlorianF gibt es keinen Unterschied. Der Unterschied besteht darin, wo die Datei abgelegt wird, was im Beitrag beschrieben wird.
Dawrutowicz
2
Ich sehe, du wechselst beans.xmlzu src/main/resources/beans.xmlund dann zurück zu beans.xml. Vielen Dank.
Florian F
Du sollst src nicht auf dem Klassenpfad haben. Wenn Sie das Projekt erstellen, werden diese Ressourcen an einer anderen Stelle gepackt.
OrangeDog
1
Hallo, wenn wir dieses JAR über die Befehlszeile ausführen, scheint es nicht wie erwartet zu funktionieren (funktioniert gut bei Eclipse).
Dhruv Singhal
58

Versuche dies:

new ClassPathXmlApplicationContext("file:src/main/resources/beans.xml");

Datei: Präfix zeigt auf Dateisystemressourcen, nicht auf Klassenpfad.

Der Dateipfad kann relativ oder systembezogen sein (/ home / user / Work / src ...)

Mikhail Kolesnikov
quelle
1
Nun, es ist besser, Ressourcen im Klassenpfad zu halten, als sie fest zu codieren, aber danke. Ich hatte damals noch keine Erfahrung mit CP :-)
dawrutowicz
1
Es ist wahrscheinlich besser, FileSystemXmlApplicationContext für Dateien zu verwenden.
Romnempire
Ich habe ein ähnliches Problem und diese Lösung hat bei mir funktioniert.
Avdhut
20

Ich hatte auch ein ähnliches Problem, aber aus einem etwas anderen Grund, also teile es hier, falls es irgendjemandem helfen kann.

Mein Dateispeicherort

beans.xml Datei

Wie ich es benutzt habe

ClassPathXmlApplicationContext("beans.xml");

Es gibt zwei Lösungen

  1. Nehmen Sie die beans.xml aus dem Paket und fügen Sie sie in das Standardpaket ein.
  2. Geben Sie den Paketnamen an, während Sie ihn verwenden.

ClassPathXmlApplicationContext("com/mypackage/beans.xml");

Kalher
quelle
1
Nun, wahr, um gesagt zu werden. Die Referenz "com / mypackage / beans.xml" ist dieselbe wie "/com/mypackage/beans.xml", da "com / mypackage / beans.xml" ein relevanter Pfad ist, der "/" (root) verwendet, um einen absoluten Pfad zu erstellen.
Dawrutowicz
7

src/main/resourcesist ein Quellverzeichnis, Sie sollten es nicht direkt referenzieren. Wenn Sie das Projekt erstellen / verpacken, wird der Inhalt an die richtige Stelle für Ihren Klassenpfad kopiert. Sie sollten es dann so laden

new ClassPathXmlApplicationContext("beans.xml")

Oder so

new GenericXmlApplicationContext("classpath:beans.xml");
OrangeDog
quelle
7

Dies liegt daran, dass applicationContect.xml oder any_filename.XML nicht unter dem richtigen Pfad platziert ist.

Schritte zur Fehlerbehebung

1: Fügen Sie die XML-Datei unter dem Ressourcenordner hinzu.

2: Wenn Sie keinen Ressourcenordner haben. Erstellen Sie eine, indem Sie neu navigieren, indem Sie mit der rechten Maustaste auf das Projekt neu> Quellordner klicken, es als Ressource benennen und Ihre XML-Datei darunter ablegen.

Gani
quelle
4

benutze es ApplicationContext context = new FileSystemXmlApplicationContext("Beans.xml");

Deep Shah
quelle
3

Sie haben sich das src-Verzeichnis angesehen. Die XML-Datei existiert tatsächlich dort. Schauen Sie sich jedoch das Klassen- oder bin / build-Verzeichnis an, in dem alle Ihre Ausgabeklassen festgelegt sind. Ich vermute, Sie benötigen nur den Pfad resources / beans.xml, um ihn zu verwenden.

Michael Z.
quelle
3

Ich vermute, Sie erstellen eine .war / .jar-Datei und folglich handelt es sich nicht mehr um eine Datei, sondern um eine Ressource in diesem Paket. Versuchen Sie stattdessen ClassLoader.getResourceAsStream (String path) .

Brian Agnew
quelle
Hallo ... Entschuldigung, dass Sie etwas spät gefragt haben, aber können Sie bitte erläutern, wie Sie vom Eingabestream in den Anwendungskontext konvertieren können? Ich versuche derzeit, eine ausführbare JAR-Datei auszuführen, aber es heißt, dass die Bean-XML nicht geladen werden kann, da sie nicht vorhanden ist.
Dhruv Singhal
3

Beachten Sie, dass der erste applicationContext als Teil von geladen wird web.xml. was mit dem unten genannten erwähnt wird.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>

<servlet>
    <servlet-name>myOwn-controller</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>META-INF/spring/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Wobei wie unten beschrieben, versucht der Code auch, einen weiteren applicationContext zu erstellen.

private static final ApplicationContext context = 
               new ClassPathXmlApplicationContext("beans.xml");

Sehen Sie den Unterschied zwischen beans.xmlundapplicationContext.xml

Und wenn appliationContext.xmlunter <META-INF/spring/>mit deklariert hat, <import resource="beans.xml"/>dann appliationContext.xmllädt dies das beans.xmlunter dem gleichen Ort META-INF/springvon appliationContext.xml.

Wohingegen; im Code; wenn es wie unten deklariert ist

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Dies ist die Beans.xml auf WEB-INF/classesOR in Eclipse src/main/resources.

[Wenn Sie beans.xmlat hinzugefügt haben, wird src/main/resourceses möglicherweise beim WEB-INF/classesErstellen des WAR platziert.]

Es werden also insgesamt ZWEI Dateien nachgeschlagen.

Ich habe dieses Problem behoben, indem ich beim Importieren applicationContext.xmlwie unten beschrieben eine Klassenpfadsuche hinzugefügt habe

<import resource="classpath*:beans.xml" />

und entfernte die Zeile ClassPathXmlApplicationContext("beans.xml")im Java-Code, so dass nur ein ApplicationContext geladen wird.

Kanagavelu Sugumar
quelle
2

Im Frühjahr befinden sich alle Quelldateien in src / main / java. Ebenso werden die Ressourcen im Allgemeinen in src / main / resources gespeichert. Bewahren Sie Ihre Spring-Konfigurationsdatei also im Ressourcenordner auf.

Stellen Sie sicher, dass Sie den ClassPath-Eintrag für Ihre Dateien auch in src / main / resources haben.

Überprüfen Sie in .classpath die folgenden 2 Zeilen. Wenn sie fehlen, fügen Sie sie hinzu.

<classpathentry path="src/main/java" kind="src"/>
<classpathentry path="src/main/resources" kind="src" />

Wenn Sie also alles installiert haben, sollte der folgende Code funktionieren.

ApplicationContext ctx = neuer ClassPathXmlApplicationContext ("Spring-Module.xml");

Shashesh
quelle
1

Gradle : v4.10.3

IDE : IntelliJ

Ich hatte dieses Problem, als ich gradle zum Ausführen meines Builds und Tests verwendete. Das Kopieren der applicationContext.xml überall hat nicht geholfen. Selbst die Angabe des vollständigen Pfades wie unten hat nicht geholfen!

context = new ClassPathXmlApplicationContext("C:\\...\\applicationContext.xml");

Die Lösung (zumindest für Gradle) liegt in der Art und Weise, wie Gradle Ressourcen verarbeitet. Für mein Gradle-Projekt hatte ich den Arbeitsbereich wie unter https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout definiert angelegt

Wenn Sie einen Test mit dem Standard-Gradle-Aufgabensatz ausführen, enthalten Sie einen Schritt "processTestResources", in dem unter C: \ ..... \ src \ test \ resources nach Testressourcen gesucht wird (Gradle stellt den vollständigen Pfad hilfreich zur Verfügung).

Ihre .properties-Datei und applicationContext.xml müssen sich in diesem Verzeichnis befinden. Wenn das Ressourcenverzeichnis nicht vorhanden ist (wie in meinem Fall), müssen Sie es erstellen und die Datei (en) dort kopieren. Danach funktionierte die einfache Angabe des Dateinamens einwandfrei.

context = new ClassPathXmlApplicationContext("applicationContext.xml");
user1554876
quelle
0

Ich habe das Gegenteil von den meisten getan. Ich verwende Force IDE Luna Java EE und habe meine Beans.xml-Datei in das Paket eingefügt. Ich habe jedoch der Beans.xml-Zeichenfolge - für das ClassPathXMLApplicationContext-Argument - den relativen Pfad vorangestellt. In meiner Hauptanwendung - der, die auf die Beans.xml-Datei zugreift - habe ich also:

    ApplicationContext context = 
         new ClassPathXmlApplicationContext("com/tutorialspoin/Beans.xml");

Ich bemerkte auch, dass sich, sobald ich die Beans.xml-Datei aus dem src-Ordner in das Paket verschoben hatte, unten links im XML-Dateisymbol ein Bean-Bild befand, das nicht vorhanden war, als sich diese XML-Datei außerhalb des Pakets befand. Dies ist ein guter Indikator, um mich wissen zu lassen, dass ClassPathXMLAppllicationsContext jetzt auf die Beans-XML-Datei zugreifen kann.

user1548875
quelle
0

Das hat bei mir funktioniert:

  new ClassPathXmlApplicationContext("classpath:beans.xml");
Sushrut Rathi
quelle
Hallo, das hat auch bei mir funktioniert, aber das Problem ist, dass beim Erstellen der JAR-Datei das JAR nicht für mich ausgeführt wird. Ich meine, ich erhalte den NoClassDefFoundError, während ich versuche, die JAR-Datei auszuführen, wenn ich die Anwendung in Eclipse ausführe Als Java läuft es ohne Fehler, nicht sicher, wie man das
löst
0

Wenn dieses Problem Sie immer noch beschäftigt und Sie mit Eclipse entwickeln, sehen Sie sich diesen Eclipse-Fehler an: Ressourcendateien aus "src / main / resources" sind nicht korrekt im Klassenpfad enthalten

Die Lösung scheint darin zu bestehen, die Eigenschaften des Projekts, den Java-Erstellungspfad und die Quellordner zu untersuchen. Löschen Sie das /src/main/resourcesVerzeichnis und fügen Sie es erneut hinzu. Dadurch wird Eclipse daran erinnert, dass diese Dateien in den Klassenpfad kopiert werden müssen.

Dieser Fehler hat mich bei der Verwendung der "Neon" -Version von Eclipse betroffen. (Und war sehr frustrierend, bis ich die soeben beschriebene einfache Lösung erkannte)

Geeb
quelle
0

Ich hatte dieses Problem und es machte mich verrückt; Ich fand letztendlich Folgendes in meiner POM.xml, was die Ursache des Problems war:

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
            <include>**/*.properties</include>
        </includes>
    </resource>
</resources>
JL_SO
quelle
0

Ich war mir nicht sicher, ob ich es schreiben sollte, aber vielleicht spart jemand ein paar Stunden:

mvn clean

kann den Job machen, wenn Ihre gesamte Konfiguration bereits perfekt ist!

Ismail Yavuz
quelle
0

Ich habe mich eine Weile mit diesem Problem befasst und bin zu der folgenden Lösung gekommen

  1. Erstellen Sie eine ApplicationContextAware- Klasse (eine Klasse, die ApplicationContextAware implementiert ).
  2. In ApplicationContextAware müssen wir nur die eine Methode implementieren

    public void setApplicationContext (ApplicationContext-Kontext) löst eine BeansException aus

  3. Erzählen Sie dem Frühlingskontext von dieser neuen Bohne (ich nenne sie SpringContext).

    bean id = "springContext" class = "packe.of.SpringContext" />
    

Hier ist das Code-Snippet

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpringContext implements ApplicationContextAware {
  private static ApplicationContext context;

  @Override
  public void setApplicationContext(ApplicationContext context) throws BeansException {
    this.context = context;
  }
  public static ApplicationContext getApplicationContext() {
    return context;
  }
}
  1. Dann können Sie beispielsweise eine beliebige Methode des Anwendungskontexts außerhalb des Frühlingskontexts aufrufen

    SomeServiceClassOrComponent UtilityService SpringContext.getApplicationContext (). GetBean (SomeServiceClassOrComponent .class);
    

Ich hoffe, dass dies das Problem für viele Benutzer lösen wird

Muhannad A.Alhariri
quelle
0

Beans.xml oder file.XML werden nicht unter den richtigen Pfad gestellt. Sie sollten die XML-Datei unter dem Ressourcenordner hinzufügen, wenn Sie ein Maven-Projekt haben. src -> main -> java -> resources

Mihai Vlasceanu
quelle