2010-06-10 8 views
8

Ho un progetto Maven multi-modulo. All'interno del modulo di persistere Ho un certo numero di file di dati file XML che fanno riferimento a un DTD:Percorso a DTD XML per DBUnit in un progetto Java/Maven multi-modulo?

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

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

Il DTD è memorizzato nella stessa directory con i file XML e anche Eclipse segnala questi file XML come valido.

Tuttavia, quando eseguo l'applicazione, DBUnit FlatXMLDataSet genera un'eccezione FileNotFound perché non è in grado di individuare la DTD. Apparentemente sta cercando il DTD nella directory del progetto root (ad esempio, myproject /). Mi sarei aspettato che cercasse il DTD nella stessa directory del file XML stesso (ad es. Myproject/persist/target/test-data).

Guardando il codice sorgente di DBUnit, ha da dire a riguardo "I dati relativi a DOCTYPE uri sono risolti dall'attuale dicrectory di lavoro".

Qual è un buon modo per risolvere il problema?

risposta

8

OK, penso di aver capito questo. Grazie a Dio per l'open source.

C'è un metodo su FlatXmlDataSetBuilder che porta un flusso al DTD. È assurdo che si tratti di un metodo pubblico IMO, ma poi di nuovo, è assurdo che DBUnit non si trovi nella stessa directory dell'XML per il file dtd.Così qui è:

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

ora lascio la dichiarazione DOCTYPE con DTD nella stessa directory del XML e utilizzare questo hack per ingannare DBUnit a fare la cosa giusta.

+0

quale versione stai usando? Non riesco a trovare questo codice qui: http://dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/FlatXmlDataSetBuilder.html –

+0

È nel link che hai fornito ... verifica riga 195 - difficile da trovare in realtà. http://dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/FlatXmlDataSetBuilder.html#195 – HDave

3

Usare sempre le variabili corrette per accedere alle directory speciali, perché multi-modulo costruisce una directory di lavoro diversa da quella build locale:

Così

  • invece di mydir uso ${project.basedir}/mydir
  • invece di target/mydir utilizzare ${project.build.directory}/mydir
  • anziché target/classes/mydir utilizzare ${project.build.outputDirectory}/mydir

Queste variabili valutano sempre il progetto corrente, indipendentemente da dove viene chiamato. Ecco un Overview of POM variables (non completa, ma la roba più importante è in là)

Inoltre, se vi capitasse di voler fare un po 'debug interattivo di query in stile, il help:evaluate mojo viene in aiuto:

basta chiamare

mvn help:evaluate 

e ti verrà richiesta un'espressione. Se inserisci un'espressione, ad es. ${project.build.plugins[0]}, il dom fusione per l'elemento specificato saranno elencati


EDIT:

ok, ora mi sembra di vedere il problema. allora perché non basta fare riferimento alla directory in xml:

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

So che non è abbastanza, ma dovrebbe funzionare, multi-modulo oppure no. la directory corrente per i test unitari è sempre l'attuale $ {project.basedir}, non la dir principale del progetto.

+1

Non penso che il problema sia con Maven, è con DBUnit. Sta cercando nel posto sbagliato per il DTD. C'è un altro modo migliore per specificarlo all'interno del file XML? C'è un impostazione DBUnit che mi manca? – HDave

+0

Il nuovo approccio risolve il problema di runtime, ma ora Eclipse si lamenta che non è in grado di individuare la DTD per la convalida. Voglio avere la mia torta e mangiarla anche io !! – HDave

+0

La directory "target" esiste solo dopo una generazione di maven. Se eseguo mvn clean non è lì e quindi Eclipse torna a lamentarsi! Ho esaminato il codice sorgente di DBUnit e fanno davvero del loro meglio per NON trovare il dtd .... – HDave

0

Provare a utilizzare "File" anziché "FileInputStream" quando si apre un file XML.

Ad esempio:

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

In questo modo, percorso relativo alla DTD dovrebbe iniziare con la directory del file XML.

E se si utilizza

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

percorso deve essere relativo alla directory di lavoro corrente.

1

Potreste pubblicare la DTD ad un server web e poi mettere l'URL HTTP in DOCTYPE, ad esempio:

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

Si tratta di un po 'di brutto la duplicazione, ma si potrebbe incollare il contenuto del DTD in XML file (s) in questione e quindi li usano come internal DTDs.

Problemi correlati