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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top