Eu tenho a seguinte estrutura de projeto.
ProjectName
|
|---src
|
|---main
|
|---java
| |
| |---ModuleName
| |
| |---module-info.java
| |
| |---PackageName
| |
| |---Main.java
|
|---resources
|
|---ResourceParentFolder
|
|---ResourceSubFolderA
| |
| |---Resource1A.png
| |---Resource2A.png
| |---Resource3A.png
|
|---ResourceSubFolderB
|
|---Resource1B.png
|---Resource2B.png
|---Resource3B.png
Eu tenho um script de shell que compila o código e depois o executa.
javac \
--module-source-path="src/main/java" \
--module=ModuleName \
-d classes
java \
--module-path="classes;src/main/resources" \
--module=ModuleName/PackageName.Main
Também tenho um script de shell que transforma meu código compilado em um jar modular e, em seguida, executa esse jar.
jar \
--verbose \
--create \
--file run/executable/jar/ProjectName.jar \
--main-class PackageName.Main \
-C classes/ModuleName . \
-C src/main/resources .
java \
--module-path="run/executable/jar" \
--module=ModuleName/PackageName.Main
No meu método principal, tenho uma chamada para java.lang.module.ModuleReader
, especificamente para o método list() , que me permite percorrer meu módulo e seu conteúdo.
Consigo ver o conteúdo do meu ResourceParentFolder
se pegar meu arquivo jar e tentar executá-lo, mas a chamada para list()
retorna os .class
arquivos apenas quando estou executando apenas meu código compilado. Isso ocorre porque meu módulo está configurado incorretamente? Ou isso é simplesmente uma funcionalidade não suportada?
Novamente, ModuleReader.list()
retorna uma lista recursiva do conteúdo do meu código-fonte e da minha pasta de recursos quando executado como um jar, mas só retorna o código-fonte quando executado como código compilado. Como faço para que o código compilado também preencha o ModuleReader.list()
? Ou essa funcionalidade simplesmente não é suportada, a menos que esteja em uma jarra ou algo assim?
E para ser claro, estou bem ciente de que existem um milhão e mais uma maneira de obter um recurso. Mas quero saber se é possível fazer do jeito que solicitei acima. E se não, então por quê?
EDIT - detalhando algumas das minhas tentativas fracassadas.
Tentei copiar o src/main/resources
diretório para classes
o local do meu módulo antes que ele se transformasse em um jar. Infelizmente, nada foi captado por ele.
Também tentei fazer --patch-modules
, mas também falhou, mas com erro.
error: no source files
Aqui está o comando que usei.
javac --patch-module ModuleName=src/main/resources
Sua tentativa de adicionar
src/main/resources
ao caminho do módulo não funcionará conforme o esperado. Simplesmente adicionar diretórios ao caminho do módulo não torna o conteúdo deles parte do seu módulo. Você precisa:Tenha as classes e os recursos no mesmo local, seja um diretório ou um arquivo JAR. Isso torna os recursos parte do módulo. E observe que é por isso que seu arquivo JAR funciona conforme o esperado, porque você empacotou as classes e os recursos no mesmo arquivo JAR.
Essa abordagem é essencialmente como "deveria ser feita".
Use
--patch-module
em tempo de execução. Observe que esta abordagem não requer a movimentação dos arquivos de recursos para qualquer lugar.Além disso, você usaria esse argumento em tempo de compilação se estivesse tentando
opens
um pacote somente de recursos; caso contrário, será emitido um aviso informando que o pacote não existe. Embora, se bem me lembro, você receberá um erro em tempo de execução neste cenário (onde umopens
pacote não é inerentemente parte do módulo), mesmo com um--patch-module
argumento.Dito isso, recomendo usar uma ferramenta de construção (por exemplo, Maven, Gradle, etc.) para projetos Java não triviais. Eles normalmente cuidarão de tudo isso para você.
Exemplo
Aqui está um exemplo de ambas as abordagens discutidas acima. Observe que todos os comandos foram executados no diretório do projeto no Windows 10 usando PowerShell Core 7.2.13 e Java 20.0.1.
Embora a saída abaixo liste diretórios de recursos , bem como recursos reais, isso não é garantido. Na verdade, se não me engano, esses mesmos diretórios não serão listados quando o módulo for empacotado em uma imagem de tempo de execução (via /
jlink
)jpackage
.Código fonte
O código-fonte é o mesmo em ambas as abordagens.
informações do módulo
amostra.Principal
Estrutura de diretório
Observe que adicionei um
app
"diretório de módulo"src/main/resources
simplesmente para espelhar o que foi feitosrc/main/java
(o que é necessário se você quiser usar--module-source-path
e--module
comjavac
). Isso não é necessário, embora não fosse necessário alterar ligeiramente os comandos usados abaixo (apenas alterações nos caminhos).Abordagem 1 – Mesclar Classes e Recursos
Comandos
Saída
Como você pode ver, o recurso
foo/res.txt
(e até mesmo o diretóriofoo/
) foi listado.Estrutura de diretório (após executar comandos)
Abordagem 2 - Uso
--patch-module
Comandos
Saída
Novamente, você pode ver que o recurso
foo/res.txt
(e o diretóriofoo/
) foi listado.Estrutura de diretório (após executar comandos)