Spring Boot Creating endpoint for download logs - java

I created an endpoint in spring boot to download logs of the application:
#Service
public class LogService {
public byte[] obterLog() {
try {
InputStream inputStream = new ClassPathResource("spring.log").getInputStream();
byte[] log = FileCopyUtils.copyToByteArray(inputStream);
return log;
} catch (IOException e) {
throw new FileException(e.getMessage());
}
}
And the controller
#Autowired
private LogService logService;
#GetMapping
public ResponseEntity<byte[]> getLog() {
byte[] log = logService.obterLog();
return ResponseEntity.ok().body(log);
}
But I can only get the log on the second time that I run the application and the log file is on the target/classes folder.
On the first time that I run the application I get a exception:
Class path resource [spring.log] cannot be opened because it does not exist
Why is this happening?

Yes the exception is right. When there are logs, it start printing into .log file and if it is not there, it will create one. In your case you could log something in when the app starts.
You could try something like this and see if the file exist and log something and then try again.
Path path = Paths.get("/path/to/spring.log");
// file exists and it is not a directory
if(Files.exists(path) && !Files.isDirectory(path)) {
log.info("file created");
}

Related

Spring Boot rest controller not working when package in a jar

I am developing a REST API using Spring Boot rest controller. Something strange is happening ; When I test my controller with Eclipse it is working just fine BUT when i deploy the app, packaged in a jar and started with the "java" command line in a docker container then, it doesn't work.
What confuse me is that there is no log. And when I put a sysout at the very beginning of my controller I realized that the controller is not even executed !
Here is the controller with the concerned endpoint, but i am not sure it will help :
#RestController
#RequestMapping("/pdf")
#EnableSwagger2
public class PDFGeneratorResources {
#Autowired
PDFGenerator pdfService;
#Autowired
ResourceLoader resourceLoader;
#PostMapping("/generate-recipies-shoppinglist")
public ResponseEntity<String> generateRecipiesAndShoppingListPDF(#RequestBody List<Day> daysList) {
System.out.println("TRACE");
ResponseEntity<String> responseEntity = null;
String generatedPDFFileURL = "";
try {
generatedPDFFileURL = pdfService.generatePDFFromHTML(PDFTemplates.RecipiesAndShoppingList,
new RecipiesShoppinglistContextBuilder(new ArrayList<Day>(daysList)));
responseEntity = new ResponseEntity<String>(generatedPDFFileURL, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return responseEntity;
}
}
Question : Is there any way of making spring boot log everything that's happening between tomcat and my controller ? King of --verbose option for spring boot ?
PS:
Here is the DockerFile I am using to deploy the app
FROM registry.gitlab.com/softreaver/meals-ready-backend/runners:centos7jdk11
MAINTAINER MILAZZO_christopher
COPY ./target/*.jar /app.jar
RUN echo -e "/usr/bin/java -Xms128m -Xmx128m -jar /app.jar\n" > /start-app.sh
RUN chmod u+x /start-app.sh
EXPOSE 8080
ENTRYPOINT ["/bin/bash", "/start-app.sh"]
I finally found the problem thx to log.level.root=debug ; I am using the Spring resourceloader to load the template for my PDF service but it seems that it is not able to find the resources folder inside a jar file.
It says : cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/templates/......
I found a solution on internet and made it work by using inputStream :
#Service
public class ResourceLoaderService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
ResourceLoader resourceLoader;
public String getResourceAbsolutePathString(String location) throws Exception {
Resource resource = resourceLoader.getResource(location);
String absolutePathString = "/";
try {
if (resource.getURL().getProtocol().equals("jar")) {
logger.debug("Jar file system activated");
File tempFile = Files.createTempFile("Mealsready_backend_", null).toFile();
resource.getInputStream().transferTo(new FileOutputStream(tempFile));
absolutePathString = tempFile.getAbsolutePath();
} else {
absolutePathString = resource.getFile().getAbsolutePath();
}
} catch (IOException e) {
logger.error("Error while trying to retrieve a resource : " + e.getMessage());
// TO DELETE Remplacer par un ServiceException
throw new Exception();
}
return absolutePathString;
}
}

Spring Batch Java configuration - Writing to remote sftp xml file without local file

I have a requirement to write xml file to a sftp server in a Spring Batch application. Currently below code writes xml file to local file system using StaxEventItemWriter. I need to write directly to remote server instead of writing it to local and then moving to the sftp server. Referred this link (Writing to a remote file using Spring Integrations Sftp Streaming java configuration) but not sure how to write using StaxEventItemWriter/setup Resource object with remote file
public void write(List<? extends UserDTO> items) throws Exception {
for(UserDTO item : items) {
StaxEventItemWriter<UserDTO> staxWriter = getStaxEventItemWriter(item);
staxWriter.write(Arrays.asList(item));
}
}
private StaxEventItemWriter<UserDTO> getStaxEventItemWriter(UserDTO user) {
String key = user.getDomain();
StaxEventItemWriter<UserDTO> writer = writers.get(key);
if (writer == null) {enter code here
writer = new StaxEventItemWriter<>();
try {
UrlResource resource = new UrlResource("file:"+outputDir+"/"+key+"_"+fileName+".xml");
writer.setResource(resource);
writer.setRootTagName("customerSet");
Jaxb2Marshaller UserMarshaller = new Jaxb2Marshaller();
UserMarshaller.setClassesToBeBound(UserDTO.class);
writer.setMarshaller(UserMarshaller);
writer.setOverwriteOutput(Boolean.TRUE);
writer.open(executionContext);
} catch (MalformedURLException e) {
e.printStackTrace();
}
writers.put(key, writer);
}
return writer;
}
You can probably try to use SftpResource which is based on Spring Integration (similar to the solution in the link you shared) and use it in your StaxEventItemWriter.

Why I cannot read properties file using getResourceAsStream from WEB-INF/classes in WildFly? [duplicate]

This question already has answers here:
How to read properties file in web application? [duplicate]
(3 answers)
Closed 7 years ago.
My PC's operating system is Windows 7 64-bit.
I created a very simple Dynamic Web Project app in Eclipse:
I have a app.properties file in WEB-INF/classes directory with these properties:
DefaultMaximumBatchSize=1000
DAOFactory=MSSQLSERVER
I have a class AppProperties which reads the above file into a Properties object at startup using getResourceAsStream:
public class AppProperties {
private static final Properties APP_PROPERTIES;
static {
InputStream inputStream = null;
APP_PROPERTIES = new Properties();
try {
inputStream = AppProperties.class.getResourceAsStream("/WEB-INF/classes/app.properties");
System.out.println("AppProperties: inputStream=" + inputStream);
if (inputStream != null) {
APP_PROPERTIES.load(inputStream);
}
} catch (Exception e) {
System.out.println("AppProperties: Exception occured; e=" + e);
}
}
public static String getValue(String propertyName) {
if (propertyName == null || propertyName.equalsIgnoreCase(""))
return null;
else
return APP_PROPERTIES.getProperty(propertyName);
}
}
I have a listener class AppContextListener:
public class AppContextListener implements ServletContextListener {
public AppContextListener() {
}
public void contextInitialized(ServletContextEvent arg0) {
String defaultMaxBatchSize = AppProperties.getValue("DefaultMaximumBatchSize");
System.out.println("AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=" + defaultMaxBatchSize);
}
public void contextDestroyed(ServletContextEvent arg0) {
}
}
I deployed the app to JBoss 4.2.3, run the JBoss 4.2.3 and I get this output in server.log:
AppProperties: inputStream=java.io.FileInputStream#1adde645
AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=1000
Perfect.
I then deployed the same app to WildFly 8.2.1, run the WildFly 8.2.1 and I get this output in server.log:
AppProperties: inputStream=null
AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=null
What happened? What is the correct way to read properties file in WildFly from WEB-INF/classes directory?
Class.getResourceAsStream() looks for a resource in all of the directories and jars that constitute the classpath of the application.
So, if you start a java program with
java -cp foo;bar.jar com.baz.Main
And you use SomeClass.class.getResourceAsStream("/blabla/app.properties"), The classloader will look for the app.properties file under foo/blabla, and in the blabla directory of bar.jar.
Now, in a webapp, what constitutes the classpath of the webapp is
the directory WEB-INF/classes
all the jar files under WEB-INF/lib
So, if you call
AppProperties.class.getResourceAsStream("/WEB-INF/classes/app.properties")
the classloader will look for app.properties in
/WEB-INF/classes/WEB-INF/classes
<all the jar files of WEB-INF/lib>/WEB-INF/classes
The conclusion is that, to load an app.properties file located in WEB-INF/classes, what you need is
AppProperties.class.getResourceAsStream("app.properties")
JBoss shouldn't have worked.
Class.getResourceAsStream retrieves the resource from the classpath and the webapp root folder is not in the classpath.
The WEB-INF/classes folder is. Use getResourceAsStream("/app.properties"), and remember to close the stream:
private static final Properties APP_PROPERTIES = new Properties();
static {
try (InputStream inputStream = AppProperties.class.getResourceAsStream("/app.properties")) {
System.out.println("AppProperties: inputStream=" + inputStream);
if (inputStream != null)
APP_PROPERTIES.load(inputStream);
} catch (Exception e) {
System.out.println("AppProperties: Exception occured; e=" + e);
}
}
Now, if app.properties is always next to AppProperties.class, instead of at the root, make the name unqualified (remove the /). This will work even when your class is in a package (and it is in a package, right?).
Try
InputStream inputStream =
this.getClass().getClassLoader().getResourceAsStream("/my.properties");`

java.io.FileNotFoundException: resourceedge-config.xml (The system cannot find the file specified)

I was using jboss server to deploy my applications and it works fine. My jboss server is corrupted, and I'm changing to tomcat 7.0.55 and its giving me error on my console
"java.io.FileNotFoundException: resourceedge-config.xml (The system cannot find the file specified)"
The resourceedge-config.xml is readingfrom this method:
public static Properties loadSystemConfiguration() throws FileNotFoundException, IOException{
return loadSystemConfiguration(ConfigReader.getFile_Prefix() + "-config.xml");
}
And it's also calling from my application filter class too which is:
//get the application context
ServletContext context = filterConfig.getServletContext();
String configFilePrefix = context.getInitParameter(ApplicationFilter.APPLICATION_CONFIG_FILE_PREFIX);
if(configFilePrefix != null){
ConfigReader.setFile_Prefix(configFilePrefix);
}
try{
configuration = ConfigReader.loadSystemConfiguration();
}catch(Exception e){
e.printStackTrace();
configuration = null;
}
The resourceedge-config.xml is place inside C:\apache-tomcat-7.0.55\bin
Please I need help on this to enable to read the file resourceedge-config.xml.
Thanks

open a file in a tomcat webapplication

i want to open a file and return its content. Although it is in the same directory like the class that wants to open the file, the file can't be found. Would be cool if you could help me solving the problem.
Here is the code:
#GET #Produces("text/html") #Path("/{partNO}/") #Consumes("text/html")
public String getPartNoResponseHTML(#PathParam("partNO") String parID) throws WebApplicationException {
PartNoTemplate partNo = getPartNoResponse(parID);
String result = "";
try {
result = readFile(PART_NO_TEMPLATE_FILE);
} catch (FileNotFoundException e) {
e.printStackTrace(System.out);
return e.getMessage() + e.toString();
// throw new WebApplicationException(Response.Status.NOT_FOUND);
} finally {
result = result.replace("{partNO}", parID);
result = result.replace("{inputFormat}", partNo.getFormat().toString());
}
return result;
}
I guess it can't find the file, because its running on tomcat. I'm also using Jersey and JAX-RS. Thank you for your help,
Maxi
If the file is inside the application WAR (or in a jar) you can try by using
InputStream input = servletContext.getClass().getClassLoader().getResourceAsStream("my_filename.txt");
Your problem is similar (I think) with How can I read file from classes directory in my WAR?
Try to get the path of the file from ServletContext.
ServletContext context = //Get the servlet context
In JAX-RS to get servlet context use this:
#javax.ws.rs.core.Context
ServletContext context;
Then get the file from your web application:
File file = new File(context.getRealPath("/someFolder/myFile.txt"));
You don't post the code that actually tries to read the file, but assuming the file is in the classpath (as you mention it's in the same directory as the class) then you can do:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
See here

Categories