The code below permits reading a /demo directory when deployed to localhost w/o a context-path, with the /demo directly off the project root.
Path demoDirPath = Paths.get(context.getContextPath(), demoDir);
Iterator<Path> contents=demoDirPath.iterator();
HashSet<Path> jsonFiles = new HashSet<>();
try (Stream<Path> stream = Files.list(demoDirPath)) {
jsonFiles = (HashSet<Path>) stream
.filter(file -> !Files.isDirectory(file) && file.getFileName().toString().endsWith(".json")
&& file.getFileName().toString().contains(transType)
)
.collect(Collectors.toSet());
} catch (IOException e) {
}
However for war deployment the /demo is not accessible and does not fail just jsonFiles.size()==0. Then /demo is placed in /resources/demo and with a context-path. I tried the second code snippet below and the resource is null. How can I read the /demo in actual context-path based deployment, please?
String folder ="classpath:/resources/demo";
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(folder);
try {
List<File> collect = Files.walk(Paths.get(resource.toURI()))
.filter(Files::isRegularFile)
.map(x -> x.toFile())
.collect(Collectors.toList());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
Related
I just want to execute a local "cmd" file right after finished and success to build .war file.
on spring boot Web Application i have tested successfully on this code.
//MainApplication.java
#EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("cmd.exe", "/c", "ls D:\\workspace\\web\\target\\");
processBuilder.command("D:\\workspace\\web\\target\\example.cmd");
try {
Process process = processBuilder.start();
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But how to get mvc build state, in order to execute a .cmd file right after build has finished and created .war file on /target directory successfully.
this code doesn't run on mvc build.
Thank you!
I would like to generate a blog posts overview. For that I want to read the html files from a folder inside the templates folder in the resources folder where Spring Boot stores its templates.
I tried that but it doesnt return an error but also list no files.
What is the way to go here?
Thanks
#Controller
public class Route {
#Autowired
private ResourceLoader resourceLoader;
#RequestMapping("/")
public String home() throws IOException {
final String path = "templates/blog";
final Resource res = resourceLoader.getResource("templates/blog");
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(res.getInputStream()))) {
reader.lines().forEachOrdered(System.out::println);
}
return "blog/a";
}
}
#Controller
public class Route {
#Value("classpath:templates/blog/*")
private Resource[] resources;
#RequestMapping("/")
public String home() throws IOException {
for (final Resource res : resources) {
System.out.println(res.getFilename());
}
return "blog/a";
}
}
did the trick to me.
You should be able to achieve this using NIO2.
In order for NIO2 to work, it requires the concept of FileSystem, and one can be created from the jar URI. Then this file system can be used with Files/Paths.
The code below contains two branches - the first handles loading the files from inside Jar, the second branch - when the code runs from IDE or via "mvn spring-boot:run".
All streams are being used via try-with-resources so they will be auto-closed.
The find function starts from the top of the file system and recursively searches for html files.
public static void readFile(String location) throws URISyntaxException {
URI uri = Objects.requireNonNull(ReadFromJar.class.getClassLoader().getResource(location)).toURI();
if (uri.getScheme().equals("jar")) { //inside jar
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) { //build a new FS that represents the jar's contents
Files.find(fs.getPath("/"), 10, (path, fileAttr) -> // control the search depth (e.g. 10)
fileAttr.isRegularFile() //match only files
&& path.toString().contains("blog") //match only files in paths containing "blog"
&& path.getFileName().toString().matches(".*\\.html")) // match only html files
.forEach(ReadFromJar::printFileContent);
} catch (IOException ex) {
ex.printStackTrace();
}
}
else { //from IDE or spring-boot:run
final Path path = Paths.get(uri);
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(path)) {
dirStream.forEach(ReadFromJar::printFileContent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void printFileContent(final Path file) {
try {
System.out.println("Full path: " + file.toAbsolutePath().toString());
Files.lines(file).forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
I'm trying to read a property file using below code, basically I'm having a Spring Boot app and I'm trying to read the below non spring bean class.The property file is in src/main/resource directory.
public class VisaProperties {
static Properties properties;
static {
try {
properties = new Properties();
String propertiesFile = System.getProperty("ftproperties");
if (propertiesFile == null) {
properties.load(VisaProperties.class.getResourceAsStream("motoconfig.cybersource.properties"));
} else {
properties.load(new FileReader(propertiesFile));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String getProperty(Property property) {
return (String) properties.get(property.getValue());
}
}
and trying call the end point property using below code getting null. How can I call the property?
VisaProperties.getProperty(Property.END_POINT)
You can simplify the code as:
final Properties properties = new Properties();
try (final InputStream stream =
this.getClass().getResourceAsStream("config.properties")) {
properties.load(stream);
}
Note: Use "try with resources" so that stream will be automatically
closed when the try {} block exits.
Done, using the code below:
Properties properties = new Properties();
InputStream inputStream = VisaProperties.class
.getClassLoader()
.getResourceAsStream("config.properties");
properties.load(inputStream);
inputStream.close();
We are developing generic automated application which will download *.pgp file from SFTP server.
The application working fine with *.txt files. But when we are trying to pull *.pgp files we are getting the below exception.
2016-03-18 17:45:45 INFO jsch:52 - SSH_MSG_SERVICE_REQUEST sent
2016-03-18 17:45:46 INFO jsch:52 - SSH_MSG_SERVICE_ACCEPT received
2016-03-18 17:45:46 INFO jsch:52 - Next authentication method: publickey
2016-03-18 17:45:48 INFO jsch:52 - Authentication succeeded (publickey).
sftpSession org.springframework.integration.sftp.session.SftpSession#37831f
files size158
java.io.IOException: inputstream is closed
at com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2884)
at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2908)
at com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36)
at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1390)
at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1340)
at org.springframework.util.StreamUtils.copy(StreamUtils.java:126)
at org.springframework.util.FileCopyUtils.copy(FileCopyUtils.java:109)
at org.springframework.integration.sftp.session.SftpSession.read(SftpSession.java:129)
at com.sftp.test.SFTPTest.main(SFTPTest.java:49)
java code :
public class SFTPTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
DefaultSftpSessionFactory defaultSftpSessionFactory = applicationContext.getBean("defaultSftpSessionFactory", DefaultSftpSessionFactory.class);
System.out.println(defaultSftpSessionFactory);
SftpSession sftpSession = defaultSftpSessionFactory.getSession();
System.out.println("sftpSessikon "+sftpSession);
String remoteDirectory = "/";
String localDirectory = "C:/312421/temp/";
OutputStream outputStream = null;
List<String> fileAtSFTPList = new ArrayList<String>();
try {
String[] fileNames = sftpSession.listNames(remoteDirectory);
for (String fileName : fileNames) {
boolean isMatch = fileCheckingAtSFTPWithPattern(fileName);
if(isMatch){
fileAtSFTPList.add(fileName);
}
}
System.out.println("files size" + fileAtSFTPList.size());
for (String fileName : fileAtSFTPList) {
File file = new File(localDirectory + fileName);
/*InputStream ipstream= sftpSession.readRaw(fileName);
FileUtils.writeByteArrayToFile(file, IOUtils.toByteArray(ipstream));
ipstream.close();*/
outputStream = new FileOutputStream(file);
sftpSession.read(remoteDirectory + fileName, outputStream);
outputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static boolean fileCheckingAtSFTPWithPattern(String fileName){
Pattern pattern = Pattern.compile(".*\\.pgp$");
Matcher matcher = pattern.matcher(fileName);
if(matcher.find()){
return true;
}
return false;
}
}
Please suggest how to sort out this issue.
Thanks
The file type is irrelevant to Spring Integration - it looks like the server is closing the connection while reading the preamble - before the data is being fetched...
at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2908)
at com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36)
at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1390)
at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1340)
The data itself is not read until later (line 1442 in ChannelSftp).
So it looks like a server-side problem.
Is there a way using ResourceLoader to get a list of "sub resources" in a directory in the jar?
For example, given sources
src/main/resources/mydir/myfile1.txt
src/main/resources/mydir/myfile2.txt
and using
#Autowired
private ResourceLoader resourceLoader;
I can get to the directory
Resource dir = resourceLoader.getResource("classpath:mydir")
dir.exists() // true
but not the files within the dir. If I could get the file, I could call dir.getFile().listFiles(), but
dir.getFile() // explodes with FileNotFoundException
But I can't find a way to get the "child" resources.
You can use a ResourcePatternResolver to get all the resources that match a particular pattern. For example:
Resource[] resources = resourcePatternResolver.getResources("/mydir/*.txt")
You can have a ResourcePatternResolver injected in the same way as ResourceLoader.
Based on Bohemian's comment and another answer, I used the following to get an input streams of all YAMLs under a directory and sub-directories in resources (Note that the path passed doesn't begin with /):
private static Stream<InputStream> getInputStreamsFromClasspath(
String path,
PathMatchingResourcePatternResolver resolver
) {
try {
return Arrays.stream(resolver.getResources("/" + path + "/**/*.yaml"))
.filter(Resource::exists)
.map(resource -> {
try {
return resource.getInputStream();
} catch (IOException e) {
return null;
}
})
.filter(Objects::nonNull);
} catch (IOException e) {
logger.error("Failed to get definitions from directory {}", path, e);
return Stream.of();
}
}