Spring MVC file not found exception - java

I'm using Spring MVC. In my controller I called a function from MyClass
MyClass{
public static void readFile(){
File file = new FileReader("myPath/myFile.txt");
...
}
public static void main(String[] args) {
readFile();//No problem
}
}
controller:
#Controller
public class MyController{
#RequestMapping(value = "/url", method = RequestMethod.GET)
public String readFile(Locale locale, Model model) {
MyClass.readFile();//File not found exception
....
}
}
The reading works when I test it in the main() of MyClass, but when I run the project on server and visit "/url", I got this:
java.io.FileNotFoundException: myPath/myFile.txt (The system cannot find the path specified)
How do I specify the path in the controller?
Thank you for your time.

What is the working directory on the server? From that directory, does the relative path to the file ("myPath/myFile.txt") exist on the server?
Assuming you only need to read myFile.txt, then typically myFile.txt would be included within the WAR, and read via getResourceAsStream.

I think you are looking for Resource implementations in Spring. Spring will determine which type of Resource to use, for example if your file is in the classpath Spring will create a ClasspathResource or it points to a file it will create a FileResource. If you are using Spring 4. Try something like
#Value("file:///myPath/myFile.txt")
Resource myFile;
Have a look at this Spring Resources docs

because this is not absolutely path. Program will find files under Working Directory
you can add this into first program and the second one
System.out.println("Working Directory = " +
System.getProperty("user.dir"));
You will see the difference.

Related

How can I set my own property file and log file location in spring boot through my own environment variable?

I want to set both property file (myproperty.properties) and log file location (myLogFile.log) through my own environment variable name (MYENV for example).
property file name must be different from spring boot application.properties name and log file has its own name also.
Do not want to use spring.config.name and spring.config.location.
MYENV will be set to "/locationFiles" value for example. myproperty.properties file location is "/locationFiles/config"
and myLogFile.log file location is "/locationFiles/log".
I know that I can use the following code snippet for reading my environment variable.
But How do I use propertiesLocation below to read the properties data in a simple Spring boot way?
I do not know how to define a corresponding java configuration class as It seems that configuration ppties file path cannot be set in a variable.
import org.springframework.core.env.Environment;
public class MyClass {
#Autowired
private Environment env;
String propertiesLocation;
private void propertyLocation() {
this.propertiesLocation = env.getProperty("MYENV")+"/config/";
}
}
The following code snippet does not match with what I want to do as I cannot
write something like that : #PropertySource(env.getProperty("MYENV")+"/config/")
#SpringBootApplication
#PropertySource("classpath:myproperty.properties")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I saw Environment Specific application.properties file in Spring Boot application but I does not match exactly with what I've described above.
As I want to define my own environment variable name and file names.
And I'm also looking for another way than using java -jar -Dspring.config.location=<path-to-file> myBootProject.jar as defined in Spring boot how to read properties file outside jar.
I want to know if there is an alternative way to this method.

How to ensure Spring `Resource::createRelative` returns relative file resource for directory resource without trailing slash?

Hej,
in a Spring Boot application I need to use a base directory on the filesystem and access file resources relative to that.
Spring Boot allows to configure a directory via application.properties and a file:// URL as value.
When the property is missing its trailing slash, Resource::createRelative() fails to actually return a relative resource.
What kind of code or configuration do I need to make the createRelative() call work as intended, e.g. by ensuring that the Resource ends with a trailing slash?
The follwing test should illustrate my use case / problem:
#SpringBootTest
// NOTE: directory is missing trailing slash
#TestPropertySource(properties = "demo.directory=file://C:/Windows")
class RelativeFileUrlResourceTest {
#ConfigurationProperties(prefix = "demo")
static class TestProperties {
Resource directory;
public Resource getDirectory() {
return directory;
}
public void setDirectory(Resource directory) {
this.directory = directory;
}
}
#TestConfiguration
#EnableConfigurationProperties(TestProperties.class)
static class Config {
}
#Autowired
TestProperties testProperties;
#Test
void givenCreateRelative_thenResourceShouldBeRelative() throws IOException {
Resource directoryResource = testProperties.getDirectory();
File directoryFile = directoryResource.getFile();
assertTrue(directoryFile.isDirectory());
Resource relativeResource = directoryResource.createRelative("relative");
File relativeFile = relativeResource.getFile();
assertEquals(directoryFile, relativeFile.getParentFile());
}
}
The test fails with:
org.opentest4j.AssertionFailedError:
Expected :C:\Windows
Actual :C:\
The magic C:/Windows value is just an example of a folder that exists and does not have a trailing slash for test purposes. Once the trailing slash is added, i.e. C:/Windows/, the test passes.
Further note that both the canonical and absolute directory File do not contain a trailing slash either (at least tested on Windows).
The relative (file) resource is needed to pass it up all the way to a Spring MVC controller while using the Spring Resource abstraction to access it as a generic InputStream.
The actual application contains some logic to determine the relative file from the HTTP request instead of a hardcoded "relative" filename.
Is Resource::createRelative() unfit for this kind of use case? What other abstractions / solutions does Spring (Boot) offer?

Adding external static files (css, js, png ...) in spring boot

Background
I have a spring boot application which has the logo.png file added to the static folder of the resource file, which is eventually built into the jar file which is used in the execution.
This jar application need to be run in multiple instances for different clients. So what I did is create an external application.properties file which distinguish the settings for each users.
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Problem
But the problem is, i need to change the logo of each instance of my application. I cannot embed the customer logos into my application jar. Rather I need to keep it external like my application.properties.
For the moment, what I have done is check for the file logo.png in the same folder of jar of execution, and if excist, read the file, get base64 data and show it in the img tag.
But I want this to be done in a proper way as static content. I need the static content to be externalized. so I can let each customer have a specific instance of the jar running with different static resource content
For example. I need to keep the external static files as below and access from the urls in my view href or src attributes of the html tags.
Summary
Required folder structure
+ runtime
- myapp-0.1.0.jar
- application.properties
+ static
- logo.png
Should be able to access
<img th:src="#{/logo.png}" />
You can use resource handlers to serve external files - e.g.
#Component
class WebConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/ext/**").addResourceLocations("file:///yourPath/static/");
}
}
The WebMvcConfigurerAdapter is deprecated. As from Spring Boot 2.x you could use WebMvcConfigurer instead.
#Configuration
public class MediaPathConfig {
// I assign filePath and pathPatterns using #Value annotation
private String filePath = "/ext/**";
private String pathPatterns = "/your/static/path/";
#Bean
public WebMvcConfigurer webMvcConfigurerAdapter() {
return new WebMvcConfigurer() {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern(pathPatterns)) {
registry.addResourceHandler(pathPatterns)
.addResourceLocations("file:" + filePath);
}
}
};
}
}

Spring: How to access contents of webapp/resources in service layer

How do I access the contents of my webapp/resources folder from the service layer? I need to access a JSON file to be used for Elasticsearch mappings...
This is how my project structure looks like:
https://www.dropbox.com/s/crdzae1ko0x9p89/Screenshot%202015-05-25%2010.24.12.png?dl=0
I tried this:
http://www.mkyong.com/java/java-read-a-file-from-resources-folder/
String mapping = String.format("es_mappings/%s.json", type);
ClassLoader classLoader = getClass().getClassLoader();
String result = IOUtils.toString(classLoader.getResourceAsStream(mapping));
But I got a null pointer exception for the third line in the code snippet above.
Also tried this:
File file = ResourceUtils.getFile("classpath:es_mappings/bom_exports.json")
String txt= FileUtils.readFileToString(file);
But I got this error: java.io.FileNotFoundException: class path resource [es_mappings/bom_exports.json] cannot be resolved to absolute file path because it does not reside in the file system.
I have this in my -servlet.xml file:
<mvc:resources location="/resources/" mapping="/resources/**"/>
Thanks.
I using this code. It's simple and works.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
// ...
#Value("/resources/json/your_file.json")
private Resource jsonResource;
// ...
InputStream jsonStream = jsonResource.getInputStream();
Now you can use stream to read json.
Using relative paths depends on the classloader, so you need to either work out where your classloader is looking or else just use an absolute path -
when using getResourceAsStream you need to start with a leading / so try this:
String mapping = String.format("/es_mappings/%s.json", type);
ClassLoader classLoader = getClass().getClassLoader();
String result = IOUtils.toString(classLoader.getResourceAsStream(mapping));
Also I'm not sure the webapp/resources folder will be added to the classpath by default in maven. Usually resources like files you need to access at runtime would be in the src/main/resources directory. (but I could be wrong, the easy way to tell is check the packaged war file, if the files are in /WEB-INF/classes then they are on the classpath)
ResourceUtils.getFile("classpath:es_mappings/bom_exports.json")
This method get resources file from the webapp/WEB-INF/classes when you pass classpath:*.
If you want get the json file from webapp/resources/es_mappings/your_file.json, the service class can implement the interface ServletContextAware and get servletContext. Because the webapp directory is determined by the web container such as tomcat or jetty, it only get the relative path from servletContext.getResource(). That method can get resources under webapp.
Code example maybe like:
class your_service implements ServletContextAware {
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void getJsonResource() {
...//other code
String josnFilepath = servletContext.getResource(
"/resources/es_mappings/your_file.json");
}
}
Also you can get the webapp directory by finding "WEB-INF/classes" substring in classpath.
String path = this.getClass().getResource("").getPath();
String fullPath = URLDecoder.decode(path, "utf-8");
String pathArr[] = fullPath.split("/WEB-INF/classes/");
if (2 == pathArr.length) { //pathArr[0] is webapp directory path
String jsonFilepath = pathArr[0] + "/resources/es_mappings/your_file.json";
}

Get fully qualified resource name in web application in Java

I would like to get access to files in resources folder my web app (independently from this is exploaded WAR or not). I have already used servletContext via Spring to getResource also FileSystem context.
In the end, I choose Spring ResourceLoader because seems that it's the most suitable approach in my case.
I don't like use #PropertySources annotation and get access to particular properties of *.properties files.
UPDATED
I deployed my app using Webspehere Liberty Profile.
#Component
public class FileCreator {
#Autowired
private ResourceLoader resourceLoader;
public String getRealPath(String location) {
String realPath = null;
try {
Resource resource = resourceLoader.getResource(location);
String resourceDesc = resource.getDescription();
realPath = resource.getURI().getPath();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
return realPath;
}
}
I have common maven layout for my Gradle app. It means that myApp.properties file located in /WEB-INF/classes folder
String scheduledServicesRealPath1 = fileCreator.getRealPath("classpath:myApp.properties");
I want to get the absolute path for this file but I 'm getting just null.
Does it exist any approach which can access resources independently from Application server, way of presentation of app on server (exploaded or not) and independent from file system?

Categories

Resources