can not find files in jar build b Spring Boot - java

these logs and the Controller Class are self-explanatory:
logs:
java.io.FileNotFoundException: class path resource [/static/index.html] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/mehrdad/ocr/main/ocr-web/target/ocr-web-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/static/index.html
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:217)
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:180)
at com.pouya.ocr.web.web.RouteController.defaultPath(RouteController.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Class:
#Controller
public class RouteController {
#RequestMapping(value = "/app/**", method = RequestMethod.GET)
public ResponseEntity<String> defaultPath() {
System.out.println("Unmapped request handling!");
try {
File index = ResourceUtils.getFile("classpath:/static/index.html");
FileInputStream inputStream = new FileInputStream(index);
String body = StreamUtils.copyToString(inputStream, Charset.defaultCharset());
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(body);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error in redirecting to index");
}
}
}
the second ! seems to cause the problem:
../ocr-web-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/static/index.html
How to solve this?
I tried to use classpath:static/index.html instead of classpath:/static/index.html, nothing changed.

I solved the problem.
do not use ResourceUtils(sometimes Spring does not make Java simpler!)use old java way for loading resource from classPath:
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("/static/index.html");

Related

Spring Boot Creating endpoint for download logs

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");
}

Not able to read resource files from src/test/resources in STS

I created folder src/test/resources/ in root project directory, and inside this I added a file in folder jsons as jsons/server_request.json.
Now I am trying to read this file by calling a the static function in CommonTestUtilityclass given as:
public class CommonTestUtility {
public static String getFileAsString(String fileName) throws IOException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
}
Now while calling this function as
class ServerTest {
#Test
void test_loadResource() {
String content = CommonTestUtility.getFileAsString("jsons/server_request.json");
}
}
, It's giving me the error as:
CommonTestUtility - Cannot invoke "java.net.URL.getFile()" because the return value of "java.lang.ClassLoader.getResource(String)" is null.
I tried to include the src/test/resources/ in the run configuration
of Junit ServerTest.java, but still it's not able to find out the
resource
How to resolve this issue?
https://mkyong.com/java/java-read-a-file-from-resources-folder/
This above link might be helpful.
The getResource() method return an URI you need to change
.getFile() function to. toURI().
Simple code
private File getFileFromResource(String fileName) throws URISyntaxException{
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(fileName);
if (resource == null) {
throw new IllegalArgumentException("file not found! " + fileName);
} else {
// failed if files have whitespaces or special characters
//return new File(resource.getFile());
return new File(resource.toURI());
}
}
I recreated the same scenario you describe and your code works for me.
Could you double-check that your project looks like mine below? If so, I suspect it might be something with your environment.

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;
}
}

Not able to save the image to disk in linux using springboot

I am trying to save images to disk using spring boot and angular, however there are no
exceptions thrown in the below code nor any errors, but i cannot see image in the required folder
#RestController
#CrossOrigin(origins = "http://localhost:4200")
public class ImageController {
#RequestMapping(value = "/postImages", method = RequestMethod.POST, consumes =
MediaType.MULTIPART_FORM_DATA_VALUE )
public ResponseEntity<Void> uploadPolicyDocument(#RequestParam("image")
List<MultipartFile> multipartFile)
{
String OUT_PATH = "home\\krishnachaitanya\\Pictures\\testing\\";
try {
for(MultipartFile mf: multipartFile)
{
byte[] bytes = mf.getBytes();
Path path = Paths.get(OUT_PATH+ mf.getOriginalFilename());
Files.write(path, bytes);
}
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return ResponseEntity.ok().build();
}
Actually I think the file is successfully written, but not in the place you would expect. '\' is not a path separator on Linux and the path you specify is relative, so the file is written in the applications working directory. The file is named: home\krishnachaitanya\Pictures\testing\oryginalFileName.
Change the OUT_PATH to "/home/krishnachaitanya/Pictures/testing/"
The OUT_PATH looks very wrong for a linux system. have you tried to use "/" instead of "\\"

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