How to specify path to resources inside a war file? - java

I have build my project with maven and spring framework using text editors.
I am able to run the project the root folder using the command on terminal
mvn spring-boot:run
I have referenced to my source files inside java file using the java statement
Document doc = builder.parse("src/main/resources/data/resorts.xml");
Everything works fine.
When I export the whole project as a war file using the command
mvn package
on terminal
I get a war file inside the target folder of the root directory
I run the war file using the command
java -jar filename.war
There is no compilation error but during runtime it shows the error java.io.FileNotFoundException
I think I have not specified the path of the reference file correctly
Can you mention how the relative path must be mentioned in the the path string to make it able to be run from the war file.
My directory structure is
.
|-- src
| `-- main
| |-- java
| | `-- hello
| | `-- org
| | `-- json
| `-- resources
| |-- data
| `-- templates
`-- target
|-- classes
| |-- data
| |-- hello
| |-- org
| | `-- json
| `-- templates
|-- generated-sources
| `-- annotations
|-- gs-handling-form-submission-0.1.0
| |-- META-INF
| `-- WEB-INF
| |-- classes
| | |-- data
| | |-- hello
| | |-- org
| | | `-- json
| | `-- templates
| `-- lib
|-- maven-archiver
`-- maven-status
`-- maven-compiler-plugin
`-- compile
`-- default-compile
33 directories
The java files are inside the hello directory.

You are probably experiencing problems with the path received from the URI class to a file located inside a jar.
Application.class.getClassLoader().getResource("path-to/filename.txt").getPath()
Outputs: /path-to-your/application.jar!/path-to/filename.txt
If you try to create a File object or a Stream to that path it will fail with FileNotFoundException
If possible you should change the class Document to receive the content of the file or a InputStream.
Then you can use the classloader to fetch the stream for the file instead of the path.
In your case:
InputStream is = Application.class.getClassLoader()
.getResourceAsStream("data/resorts.xml");
And then create the Document with the is object.

Related

How to create per module application.properties in spring boot?

I have a spring boot project in which there are multiple modules, I want to have each module separate application properties file, but when I added properties file in all modules, it's still picking properties from main application properties file.
Project Structure:
|-- Dockerfile
|-- build.gradle
|-- modules
| |-- application
| | |-- build.gradle
| | `-- src
| | `-- main
| | |-- java
| | | `-- org
| | | `-- example
| | | |-- CoreApplication.java
| | `-- resources
| | |-- application-beta.properties
| | |-- application-dev.properties
| | |-- application-local.properties
| | |-- application-prod.properties
| | |-- application-test.properties
| | `-- application.properties
| |-- config-management
| | |-- build.gradle
| | `-- src
| | `-- main
| | |-- java
| | | `-- org
| | | `-- example
| | | `-- controller
| | | `-- TestController.java
| | `-- resources
| | |-- application-beta.properties
| | |-- application-dev.properties
| | |-- application-local.properties
| | |-- application-prod.properties
| | |-- application-test.properties
| | `-- application.properties
`-- settings.gradle
application.properties in config module
config.hello=hello-from-config
application.properties in application module
config.hello=hello-from-application
TestController.java in config module
#RestController
public class TestController {
#Value("${config.hello}")
private String hello;
#GetMapping("hello")
public String get() {
return hello;
}
}
After calling /hello api, response: hello-from-application
This isn't a complete answer to your question but more a list of advices I think you should follow when designing your multi-module application project.
With spring many things are easier to configure with #Configuration beans. On many occasions, you'll be forced to have such beans to configure specific functionalities. These configuration beans are also a great way of including a configuration of one module in another.
What I do is the following - each module has one main #Configuration bean. This bean #Imports all other #Configuration beans inside your module, as well as, loads the properties file and imports the main #Configuration beans of the modules and maybe external dependencies your module depends on.
You should remember that spring, and java in general uses the classloader to load these .properties files that you have in the resources folders. The way you have organized the .property files currently they override each other; depending on how spring boot works the classloader will either load the first *.properties file it encounters, or maybe, your extra property files won't even make it into the shaded jar file. As a solution, use packages. Each module should have all of its stuff in a specific package, this includes the configuration files.
Do not include environment-related configuration files in your application source code. Move it to your deployment procedures. You can have samples of these environment-related files in your /docs or /distribution folder in your project, but have them here as documentation and not as actual configurations used in these environments. In 99% of the cases, environment-related configurations should be stored separately from your compiled application, the way you have it now they are compiled into the application itself.
Hope this was helpful.
P.S.
Once you organize the config files in the manner I describe, you may still end up fighting a battle against Spring's property file loader(don't remember the exact name), but that's a separate topic, and there are already many questions on that topic here.

calling a jar contains java and python classes, but path problem while python execution

I have a maven java project. It contains python file and calls (using PythonInterpreter) then, return the result back to java class.
I have to deliver my project as a jar file. And they will call methods in my java class, my java class will execute my python code and later jar calling project will get result from java class.
I created a test project calling my jar pretending I have their java project. But it doesn't work. It is searching my python class inside the test project.
I am calling my python class inside main project using this:
interpreter.execfile("./src/main/java/deneme.py");
When I call my method from test project:
int a = JythonExampleStatic.denemeSumMethodStatic(34, 1);
My test project return this error:
Exception in thread "main" IOError: (2, 'File not found -
C:\\Users\\user.name\\eclipse-workspace\\test.project.artifact\\.\\src\\main\\java\\deneme.py (python path I called inside main project)
(The system cannot find the file specified)')
Note that my python class will never be callable from outside of project scope, it is just for execution.
How should I call my python class?
or
Where should I make a change?
|- mainProject
| |-- src
| |-- |-- main
| |-- |-- |-- java
| |-- |-- |-- | -- MyClassCallingPython.java (using PythonInterpreter)
| |-- |-- |-- resources
| |-- |-- |-- | -- MyPython.py
|- testProject
| |-- src
| |-- |-- main
| |-- |-- |-- java
| |-- |-- |-- |-- MethodCallsMyClassCallingPython.java
| |-- |-- |-- ReferencedLibraries
| |-- |-- |-- |-- mainProject.jar

How to reference a config file out of classpath at runtime (in IDE)

I'm taking over a maven/spring application, where the configuration files are not on the classpath. i.e, the config folder is copied by the maven-assembly-plugin next to the jar, to ease the configuration when the application is deployed.
My problem is that I need these config files to run this app from within my IDE (intelliJ), and of course, Spring is complaining
Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist
The assembly takes either "application-prod" or "application-test".properties, depending on the maven profile used at packaging time, and copy it as "application.properties" into the /config folder, so next to the jar.
My question is:
What should I do to have this "application.properties" file available in the classpath (ideally depending on the maven profile), when running the application in Intellij, without messing around with the project structure ?
I guess that giving the properties file as a parameter to the launcher could be a solution, but I don't know how.
So here is the simplified project structure:
|-- src/
| |-- main/
| | |-- assembly/
| | | |-- bin.xml
| |
| | |-- config/
| | | |-- images/
| | | |-- application-prod.properties
| | | |-- application-test.properties
| |
| | |-- java/...
| | | |-- gui/
| | | | |-- Application.java
| |
| | |-- resources/
| | | |-- context/
| | | | |-- context.xml
| |
| | | |-- fxml/
| | | | |-- welcome.fxml
| |
| | | |-- gui.properties
| |
|-- pom.xml
Many thanks.
In this simple situation without multimodule dependencies it can make the trick.
You can right click on any directory in your IntelliJ project, select "Mark Directory As", and choose "Source Root" (or resource root as well). That directory folder will change color from yellow to blue (or resource icon will appear); IntelliJ will ensure that all those directories will be in your CLASSPATH.
Also take a note that you should not try to explicitly add smth to CP var in IDEA. Classpath is configured in the Module Dependencies of your module.

RMI - stub creation with rmic

I am stuck with creating stubs for my simple RMI implementation. With command line, I am at directory, where I have my class files stored.
For me it is: C:\Users\John\Documents\NetBeansProjects\testServer\build\classes\RMI
RMI here is the package I have my files in. Now when I am in this folder, I tri to make stubs with rmic -v1.2 -keep CountingOnServer, but command line writes me, that class CountingOnServer not found. No matter what I am doing, still it is writing such a unbelivable mistake... do you know how to solve that?
Thx
As a guess, issue is that CountingOnServer is inside some package, so you should use full name like RMI.CountingOnServer. Don't forget to run rmic from the the class-path root which in your case seems to be build\classes directory.
If you have your RMI implementation in packages run rmic at the root of your class files,
ex,
|-- build
| |-- classes
| | `-- com
| | |-- client
| | | `-- TestRMI.class
| | |-- rmi
| | | |-- Hello.class
| | | |-- HelloInterface.class
| | | `-- Hello_Stub.class
| | `-- RMTServer
| | `-- RmiServer.class
I have my classes in build/classes/com/rmi directory so, to create stubs I can run rmic at the root as,
../build/classes/rmic com.rmi.Hello

Where do I put the .tld file so that the resulting JAR file built with maven2 is properly packaged?

I currently have the following directory structure for my code:
src
|-- main
| `-- java
| `-- com
| `-- upthescala
| `-- tags
| `-- ViewProtectTag.java
|-- test
|-- pom.xml
|-- .project
|-- .classpath
`-- .hgignore
I want to include a tld file for my JSP tag, and I'm not sure where to package it. My initial thought is to add a src/main/resources directory and put META-INF/viewprotect.tld in there.
My initial thought is to add a src/main/resources directory and put META-INF/viewprotect.tld in there
And that's a good initial thought.

Categories

Resources