Pregunta

Tengo un proyecto Maven de múltiples módulos. Dentro del módulo Persist tengo varios archivos de datos de archivos XML que hacen referencia a un DTD:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "myapp-data.dtd" >

<dataset>
      .....omitted for brevity....
</dataset>

El DTD se almacena en el mismo directorio con los archivos XML e incluso Eclipse informa que estos archivos XML son válidos.

Sin embargo, cuando ejecuto la aplicación, el DBUnit FlatXMlDataSet lanza una excepción de FileNotfound porque no puede localizar el DTD. Aparentemente está buscando el DTD en el directorio del proyecto raíz (por ejemplo, myProject/). Hubiera esperado que buscara el DTD en el mismo directorio que el archivo XML en sí (por ejemplo, myproject/persist/target/test-data).

Mirando el código fuente DBUNIT, tiene esto por decir al respecto, "URI relativo de doctype se resuelve del dicrector de trabajo actual".

¿Cuál es una buena manera de arreglar esto?

¿Fue útil?

Solución

Ok, creo que descubrí este. Gracias a Dios por el código abierto.

Hay un método en FlatXMlDataSetBuilder que toma una transmisión al DTD. Es una locura que este sea un método público en mi opinión, pero de nuevo, es una locura que DBunit no se vea en el mismo directorio que el XML para el archivo DTD. Asi que aqui esta:

String dtdResourceName = "classpath:test-data/myapp-data.dtd";      
Resource res = applicationContext.getResource(dtdResourceName);
builder.setMetaDataSetFromDtd(res.getInputStream());

Ahora dejo la Declaración de Doctype con el DTD en el mismo directorio que el XML y uso este truco para engañar a Dbunit para hacer lo correcto.

Otros consejos

Siempre use las variables correctas para acceder a directorios especiales, porque las compilaciones de múltiples modelos tienen un directorio de trabajo diferente a las compilaciones locales:

Asi que

  • en vez de mydir usar ${project.basedir}/mydir
  • en vez de target/mydir usar ${project.build.directory}/mydir
  • en vez de target/classes/mydir usar ${project.build.outputDirectory}/mydir

Estas variables siempre se evalúan en el proyecto actual, sin importar de dónde se llame. Aquí hay un Descripción general de las variables de POM (No está completo pero las cosas más importantes están ahí)

Además, si alguna vez quieres hacer una depuración interactiva de estilo de consultas, la AYUDA: Evalúa Mojo Viene muy bien:

solo llama

mvn help:evaluate

y se le solicitará una expresión. Si ingresa a una expresión, por ejemplo ${project.build.plugins[0]} , el DOM fusionado para el elemento especificado se enumerará


EDITAR:

Ok, ahora creo que veo el problema. Entonces, ¿por qué no solo hacer referencia al directorio en el XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "target/test-classes/myapp-data.dtd" >

Sé que no es bonito, pero debería funcionar, múltiples módulos o no. El directorio actual para las pruebas unitarias es siempre el $ {Project.Basedir} actual, no el principal proyecto del proyecto.

Puede publicar el DTD en un servidor web y luego poner su URL HTTP en el Doctype, por ejemplo:

<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd">

Try using "File" instead of "FileInputStream" when opening an XML file.

For example:

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName)));

This way, relative path to DTD should start with directory of the XML file.

And if you use

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName)));

path should be relative to current working directory.

It involves some ugly duplication, but you could paste the contents of the DTD into the XML file(s) in question and then use them as internal DTDs.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top