Caminho para o DTD XML para o dbunit em multi-módulo Java/projeto Maven?
Pergunta
Eu tenho um multi-módulo de projeto maven.Dentro do persistem módulo de eu ter um número de arquivos XML, arquivos de dados que fazem referência a um DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "myapp-data.dtd" >
<dataset>
.....omitted for brevity....
</dataset>
O DTD é armazenado no mesmo diretório com os arquivos XML e até mesmo Eclipse relatórios desses arquivos XML como válido.
No entanto, quando eu executar o aplicativo, o o dbunit FlatXMLDataSet lança um FileNotFound exceção porque não localizado o DTD.Ele é, aparentemente, olhando para o DTD no directório raiz do projecto (e.g.myproject/).Eu teria esperado para olhar para o DTD no mesmo diretório que o arquivo XML em si (por exemplo,myproject/persistem/target/test-data).
Olhando para o dbunit o código-fonte, ele tem a dizer sobre isso "em relação DOCTYPE uri são resolvidos a partir do trabalho atual dicrectory."
O que é uma boa maneira de corrigir isso?
Solução
Ok, acho que descobri este. Graças a Deus pelo código aberto.
Existe um método no FlatxmldataSetBuilder que leva um fluxo para o DTD. É uma loucura que este seja um método público IMO, mas, novamente, é uma loucura que o dbunit não pareça no mesmo diretório que o XML para o arquivo DTD. Então aqui está:
String dtdResourceName = "classpath:test-data/myapp-data.dtd";
Resource res = applicationContext.getResource(dtdResourceName);
builder.setMetaDataSetFromDtd(res.getInputStream());
Agora deixo a Declaração Doctype com o DTD no mesmo diretório que o XML e uso esse hack para enganar a dbunit para fazer a coisa certa.
Outras dicas
Use sempre o correto variáveis especiais de acesso a diretórios, porque multi-módulo constrói ter um trabalho diferente do diretório de local baseia-se:
Então,
- em vez de
mydir
utilização${project.basedir}/mydir
- em vez de
target/mydir
utilização${project.build.directory}/mydir
- em vez de
target/classes/mydir
utilização${project.build.outputDirectory}/mydir
Estas variáveis de avaliar sempre para o projeto atual, não importa onde ele é chamado.Aqui está um Visão geral do POM variáveis (não estão completos, mas o mais importante está lá)
Também, se você quiser fazer alguma interativo de consulta estilo de depuração, o ajuda:avaliar mojo vem a calhar:
basta chamar
mvn help:evaluate
e você será solicitado para uma expressão.Se você digitar uma expressão e.g. ${project.build.plugins[0]}
a nova dom para o elemento especificado serão listados
EDITAR:
ok, agora eu acho que eu vejo o problema.então por que não apenas referenciar o diretório no xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "target/test-classes/myapp-data.dtd" >
Eu sei que não é bonito, mas deve funcionar, multi-módulo, ou não.o diretório atual para testes de unidade é sempre o atual, ${projecto.basedir}, não o principal projeto dir.
Você pode publicar o DTD em um servidor da Web e depois colocar seu URL HTTP no doctype, por exemplo:
<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd">
Tente usar "arquivo" em vez de "FileInputStream" ao abrir um arquivo XML.
Por exemplo:
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName)));
Dessa forma, o caminho relativo para o DTD deve começar com o diretório do arquivo XML.
E se você usar
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName)));
O caminho deve ser relativo ao diretório de trabalho atual.
Envolve alguma duplicação feia, mas você pode colar o conteúdo do DTD no (s) arquivo (s) XML em questão e depois usá -los como DTDs internos.