How can I read resources file from outside project directory? - java

Below code works fine if file location is resources folder but when file location is outside the project directory like(c:\file.json) it fails.
How can we load file from outside project directory.
#Bean
public UserInfo readFile() {
String fileName="prop.json";
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
try {
UserInfo info= new ObjectMapper(new JsonFactory()).readValue(file, UserInfo.class);
} catch (Exception e) {
}
return info;
}

You should create a Configuration class that implements WebMvcConfigurer and
override the addResourceHadndler Method to add new resource to spring context.
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// register you resource here
}
}

Related

How to read war-file manifest in its jar-dependency?

How do I read the war-file manifest property in its jar-dependency?
UPD: servlets are not used here (it's spring-bean initialization code).
Since a .war file’s purpose is to handle servlets, I assume all of your code is called from servlets, or from a technology built on servlets, like JSP, JSF, or even Spring.
Call the current request’s getServletContext() method, and use the getResource or getResourceAsStream method of ServletContext. Those methods work just like the same methods of java.lang.Class, only they look in the .war file itself before searching the web application’s classpath for a matching path.
For example:
public Optional<Manifest> getWarManifest(ServletRequest request)
throws IOException {
InputStream manifest =
request.getServletContext().getResourceAsStream(
"/META-INF/MANIFEST.MF");
if (manifest == null) {
return Optional.empty();
}
try (InputStream stream = new BufferedInputStream(manifest)) {
return Optional.of(new Manifest(stream));
}
}
Update:
Since you want to read the manifest when preparing a Spring bean, it appears you can autowire a ServletContext object:
#Configuration
public class MyAppConfig {
#Bean
public MyBean createMyBean(#Autowired ServletContext context)
throws IOException {
Optional<Manifest> manifest;
InputStream source =
context.getResourceAsStream("/META-INF/MANIFEST.MF");
if (source == null) {
manifest = Optional.empty();
} else {
try (InputStream stream = new BufferedInputStream(source)) {
manifest = Optional.of(new Manifest(stream));
}
}
return new MyBean(manifest);
}
}

Spring Boot can't autowire #ConfigurationProperties

Here is my FileStorageProperties class:
#Data
#ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
}
This gives me saying : not registered via #enableconfigurationproperties or marked as spring component.
And here is my FileStorageService :
#Service
public class FileStorageService {
private final Path fileStorageLocation;
#Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
public String storeFile(MultipartFile file) {
// Normalize file name
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
// Check if the file's name contains invalid characters
if(fileName.contains("..")) {
throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
}
// Copy file to the target location (Replacing existing file with the same name)
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public Resource loadFileAsResource(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if(resource.exists()) {
return resource;
} else {
throw new MyFileNotFoundException("File not found " + fileName);
}
} catch (MalformedURLException ex) {
throw new MyFileNotFoundException("File not found " + fileName, ex);
}
}
}
This gives me error saying : could not autowire no beans of type found.
And here is my project structure :
And when I try to run it, it gives me :
APPLICATION FAILED TO START
Description:
Parameter 0 of constructor in com.mua.cse616.Service.FileStorageService required a bean of type 'com.mua.cse616.Property.FileStorageProperties' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.mua.cse616.Property.FileStorageProperties' in your configuration.
How can I resolve this?
This is expected as #ConfigurationProperties does not make a class a Spring Component. Mark the class with #Component and it should work. Note that a class can only be injected if it is a Component.
Edit: From Spring 2.2+ (Reference)
#ConfigurationProperties scanning
Classes annotated with #ConfigurationProperties can now be found via classpath scanning as an alternative to using #EnableConfigurationProperties or #Component. Add #ConfigurationPropertiesScan to your application to enable scanning.
Try to annotate with #ConfigurationProperties and #Component
In here , Spring Boot #ConfigurationProperties is annotation for externalized configuration.if you are trying to inject property value from a property file to a class, you can add #ConfigurationProperties at a class level with stereotype annotations such as #Component or add #ConfigurationProperties to a #Bean method.
add bellow annotation in FileStorageProperties class:
#Component

spring boot - serving images from folder outside src

I have a folder named uploads which is at the same level as src folder. I upload images to this folder.
Then I added the following configuration to be able to serve the images in thymeleaf:
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/uploads/**")
.addResourceLocations("/resources/","/../../uploads/")
.setCachePeriod(0);
}
}
I try to serve the images in Thymeleaf like this:
<img class="img-thumbnail img-responsive" src="#" th:src="#{'/uploads/' + ${photo}}" alt="">
where ${photo} is the name file name.
However I get the following error:
The resource path [/../../uploads/rtf_vtvsq1r12q.png] has been normalized to [null] which is not valid.
Apparently the path in my configuration is wrong. Could somebody please tell me what I'm doing wrong?
There is missing file. Add below configuration:
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/images/**")
.addResourceLocations("file:resources/", "file:uploads/")
.setCachePeriod(0);
}
}
here you get details.

add directory to classpath in runtime

In my current spring project, when I run the application, it's created a directory on the user's home directory where I store some configuration files (*.properties file). In my code, I refer to this file in that way:
private String getFilename() {
return System.getProperty("user.home")+File.separator+".webapp"+File.separator+"webapp.preferences";
}
which allows me run the application in any operational system without change the code. I need add this directory to the classpath of the application, to allow me use the annotation PropertySource to access the properties stored in the file using either the method getproperty from Enviroment class or the Value annotation.
I using spring-boot, so the start point for the application it's that:
#Controller
#EnableJpaRepositories
#EnableAutoConfiguration
#ComponentScan(value="com.spring")
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
I also have classes WebAppInitializer, WebAppConfig and DispatcherConfig to store the configurations handled by the XML files web.xml and dispatcher-config.xml from spring.
Anyone can tell if this is possible and hor to accomplish that?
UPDATE
Following the sugestions in the commentaries, I add to my project this bean:
#Bean
static PropertySourcesPlaceholderConfigurer property() throws Exception {
PropertySourcesPlaceholderConfigurer propertyConfigurer = new PropertySourcesPlaceholderConfigurer();
String filename = System.getProperty("user.home")+File.separator+".webapp"+File.separator+"webapp.preferences";
File file = new File( filename );
if(file.exists())
propertyConfigurer.setLocation( new FileSystemResource( filename ) );
else {
if(file.mkdir()) {
FileOutputStream fos = new FileOutputStream( filename );
fos.close();
propertyConfigurer.setLocation( new FileSystemResource( filename ) );
}
}
return propertyConfigurer;
}
and try use this in my pojo class:
#Input(label = "Titulo")
#Property(key = "geral.titulo")
#Value(value = "${geral.titulo}")
private String titulo;
but when I create a new instance of this classe, the fields don't receive the value indicated by the annotation. What I am doing wrong? I verify the file and the properties exists in it.

Mount an external folder as a resource in Wicket

What I am trying to accomplish is for some image references in a css file to be located in a folder seperate to the actual application.
Is it possible to mount an external folder as a resource in Wicket?
In pseudocode this is what I am trying to do:
public class Application extends WicketApplication
{
init()
{
mountResource(new FolderResource("Path/to/some/folder", "someid"));
}
}
So that the .css class would reference the resources like this:
.someclass
{
url("resources/someid/images/image.png")
}
I'm sure I've seen this somewhere but I just can't seem to be able to find it again...
EDIT
Should also note that im currently running on Wicket 1.4
As simple as following.
MyApplication.java:
public class MyApplication extends WebApplication {
...
public void init() {
...
final String resourceId = "images";
getSharedResources().add(resourceId, new FolderResource(new File(getServletContext().getRealPath("img"))));
mountSharedResource("/image", Application.class.getName() + "/" + resourceId);
}
...
}
FolderResource.java:
public class FolderResource extends WebResource {
private File folder;
public FolderResource(File folder) {
this.folder = folder;
}
#Override
public IResourceStream getResourceStream() {
String fileName = getParameters().getString("file");
File file = new File(folder, fileName);
return new FileResourceStream(file);
}
}
And then you can get any image from "img" folder inside your application by simple URL:
/your-application/app/image?file=any-image.png
Here "/your-application" is the application context path, "/app" is the Wicket servlet mapping in web.xml, and "any-image.png" is the name of the image file.

Categories

Resources