The question pretty much says it all. I get following exception:
ExceptionConverter: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
Caused By: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
The physical location of the font file is
As far as I can see, it should be not found in resources by iText's
Answer by BalusC
Based on the source code of iText's
FontFactory#register() method can only take a path representing a valid (relative) disk file system path, or a resource URL (e.g. HTTP URL or classpath URL), not a web resource path. You actually supplied a web resource path which you can usually pass to
There are several ways to get it to work:
1. Convert the web resource path to an absolute disk file system path with help of
String path = getServletContext().getRealPath("/WEB-INF/resources/fonts/foobar.ttf"); PdfFontFactory.register(path); caveat is that this method is highly unportable and environment-dependent. Among others, this will fail when the server is configured to expand the WAR straight into memory instead of on local disk file system, or uses a virtual file system. E.g., by default, it may work on Tomcat, but it may not work on WebLogic. Your stack trace confirms that you're using WebLogic. The chance is big that the `getRealPath()` will by default always return `null`.
2. Move the font file outside
/WEB-INF folder so that it's publicly accessible by a HTTP URL. Provided that you can move whole
/resources folder one level up, outside
/WEB-INF, and that the font is accessible by
http://localhost:8080/context/resources/fonts/foobar.ttf (first test in a normal web browser to be sure), then just supply exactly that path.
String path = "http://localhost:8080/context/resources/fonts/foobar.ttf"; PdfFontFactory.register(path);
You can if necessary dynamically construct
http://localhost:8080/context (the base URL) as below:
String url = request.getRequestURL().toString(); String baseURL = url.substring(0, url.length() - request.getRequestURI().length()) + request.getContextPath(); String path = baseURL + "/resources/fonts/foobar.ttf"; PdfFontFactory.register(path);
3. Move the font file to the classpath. I.e. make sure it ultimately ends up in
/WEB-INF/classes among all those Java class files and resource files. Let's assume that the package name is just
fonts. In case you're using Maven, just put it in
/main/resources/fonts/foobar.ttf. In case you're using a "plain vanilla" web project with only a
src folder where you put all your Java packages and class source files, then create a package
fonts the usual way and put the
foobar.ttf file right there. Then you can supply a path of
String path = "/fonts/foobar.ttf"; PdfFontFactory.register(path);
4. In case none of above options apply, your last resort is creating a temporary file with help of
File#createTempFile() in container managed temporary folder, grabbing the web resource contents by
ServletContext#getResourceAsStream(), writing it to the temp file and finally provide the absolute temp file path.
String tempDir = (String) getServletContext().getAttribute(ServletContext.TEMPDIR); File tempFile = File.createTempFile("foobar-", ".ttf", new File(tempDir)); InputStream input = getServletContext().getResourceAsStream("/WEB-INF/resources/fonts/foobar.ttf"); Files.copy(input, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); String path = tempFile.getAbsolutePath(); PdfFontFactory.register(path);
Note: the above answer assumes that the code is placed in a "plain" Java EE servlet class. In case you're using JSF — as confirmed by the stack trace — you can obtain the
ServletContext attributes by
ExternalContext#getApplicationMap(), the real path by
ExternalContext#getRealPath(), and the resource stream by