In this page

Logging

The Better PDF Exporter app records its internal activities to a so-called log. The log helps you to understand the activity of the app when diagnosing problems.

Viewing the log

The Better PDF Exporter app writes its own log lines to the Jira log:

  1. Find the logfile named atlassian-jira.log (see the guide by Atlassian).
  2. Search for the text "com.midori" to find the lines written by Better PDF Exporter.
  3. If you can't see any log line written by the app, wait a few seconds then click "Refresh" and see if it solves the problem.

If you can't interpret the log lines you found, report it to our support. We are there to help you!

Configuring logging

When investigating a run-time problem, you may need to increase the logging level for the Better PDF Exporter app. Doing so, it will write more details about what it does to the log, which helps you understand the problem.

How to enable DEBUG-level logging

To turn on DEBUG logging from the web interface without stopping Jira:

  1. Login to Jira as administrator.
  2. Go to Jira AdministrationSystemLogging and Profiling.
  3. Click Configure logging level for another package under Default Loggers.
  4. Enter "com.midori" to Package Name and choose "DEBUG" in Logging Level.
  5. Click Add.
  6. Check if this new package was correctly added to the Default Loggers list.

Now execute the app function that you think fails, then check the log for the details.

How to enable TRACE-level logging

In some rare cases, you may need to turn on TRACE logging, the most detailed logging level. For that, just follow the DEBUG-level logging guide but choose "TRACE" as logging level (instead of "DEBUG").

Warning: TRACE logging can produce a very high number of log lines. Therefore, it should be turned off as soon as possible!

Troubleshooting

This section gives you practical hints to find the root cause when investigating problems in PDF templates and Groovy scripts.

Reduce data

If you see a problem that occurs when exporting a large data set, it is hard to find the precise root cause because of the sheer volume of data. Does it occur for every issue, for Story-type issues only or for the issue FOO-123 only? Similarly, does it occur for every field, for date-type fields only or for the "Due date" field only?

The following techniques help you re-produce a problem with a smaller scope, what is key to find the solution.

Reduce issues

It is helpful when the problem is related to one or more specific issues.

It's a simple idea that you can apply in several ways:

  • If you fail to export a large number of issues, export only the first one! If it fails as well, then you have a single issue to reproduce the problem. To verify if the problem appears for any issue, repeat the test using a few other randomly chosen issues.
  • Or, if you see the problem with a smaller number of issues, start removing issues one by one (or in small batches) and repeat the test after each removal. If the problem disappears, then it is caused by the most recently removed issue (batch).
  • Or, the previous technique in reverse direction: start adding issues one by one (or in small batches) and repeat the test after each addition. If the problem appears, then it is caused by the most recently added issue (batch).
  • Or, find a single or small number of problematic issues in a large dataset with "bisection":
    1. Split up the issues to two similarly-sized partitions (using JQL, for example).
    2. Test with the first partition.
    3. Test with the second partition.
    4. If the problem appears only with one of the partitions, then split that partition again, test those two halves again, and so on.
    5. Repeat this until you have a small scope.

These can be used in combination, be creative!

Reduce fields

It is helpful when the problem is related to a specific field.

The idea is the same as reducing the number of issues, but with fields. Basically, you just systematically add or remove fields and repeat the test until you reach a small scope that reproduces the problem. (You can add or remove fields to the PDF export typically by commenting in and commenting out fields in the template or by adding and removing columns in the Issue Navigator.)

Reduce features

It is helpful when the problem is related to a specific feature (e.g. exporting comments).

Obviously, disable the suspicious feature and test. If the problem disappears, then it is caused by that feature.

Reduce code

It is helpful when the problem is related to a specific code part in the PDF template or in the Groovy script.

Comment out the code part and test. If the problem disappears, then it is caused by that code part.

Other troubleshooting techniques

Advanced techniques in this section can give further help find problems in Groovy code.

Using getter-based expressions instead of property-based ones

Although these are identical when they succeed, the template expression that uses the getter method name may show more details about a problem than its property name based equivalent. Therefore, if you have a problem in the method that calculates the value "baz", replace ${fooBar.baz} with ${fooBar.getBaz()}.

Wrapping problematic code in a try-catch block

When you have a problematic code block, used through a template expression like ${fooBar.getBaz()} or ${fooBar.baz} and it mysteriously breaks the export, wrap it in a try-catch block!

See this example (that deliberately throws an exception to demonstrate "problematic code"):

import org.apache.log4j.Logger

fooBar = new FooBarTool()

public class FooBarTool {
	def log = Logger.getLogger(this.getClass())

	def getBaz() {
		try {
			throw new NullPointerException() // <- this is here just to demonstrate the technique

			// ... problematic code comes here

		} catch (Exception ex) {
			log.error(ex)
			return ex.message
		}
	}
}

Why does it help in troubleshooting?

  1. The exception will be caught, but the export will not stop!
  2. The exception will be written to the log.
  3. The exception message will be returned to the template. It will appear exactly where the actual value should, giving you a "very visual" way of locating the problem.

Typical problems and their solutions

I cannot export more than 1000 issues in one turn.

To prevent overloading the server, Jira exposes a limit on the number of issues that can be exported in one go. The Better PDF Exporter fully obeys this limit.

The limit is set to 1000 by default, but can be overridden by configuring the following settings in jira-config.properties:

  • jira.search.views.default.max This is the default soft limit. Soft means that this value will be automatically added as a URL parameter called tempMax to each export request. You can manually increase the default value by changing the URL in your browser's address bar, or even remove the tempMax request parameter from the URL. You cannot exceed the value defined by the next configuration setting this way.
  • jira.search.views.max.limit This is the absolute hard limit. You cannot set tempMax to values greater than this, as you will get a 403 HTTP error. However, you can grant some users the permission to even break this limit - see next setting!
  • jira.search.views.max.unlimited.group If you select a group here, any of its members can export an unlimited number of issues. Note that you still need to override the tempMax URL parameter by hand. Also be careful, as these users will be potentially generate huge load on the server.

For more detailed explanation of these settings, please see the official Atlassian documentation.

Please note that in modern Jira versions these settings are configurable also through the UI!

I see the "Failed to load PDF views: check the browser's Javascript console!" error in the "Export" menu.

This typically happens in the backlog screen and in the Tempo Timesheets screens when you have a lot of issues (500 or more) to export. That makes the generated export URL very long, which then exceeds the max URL length accepted by the server.

To fix the problem, increase the max URL length limit in Jira:

  1. Go to the conf folder in your Jira installation directory, and edit the server.xml file.
  2. Go through all the lines that start with <Connector. (Search for term "Connector" in the file, or look at the example below.) You're interested only in those connectors whose protocol is HTTP or HTTPS (not AJP).
  3. Add maxHttpHeaderSize="20000" to the connector properties. For example:
    <Connector port="8080" protocol="HTTP/1.1"
    	connectionTimeout="20000"
    	redirectPort="8443" maxHttpHeaderSize="20000" />
    
  4. Restart Jira.
  5. If the problem is still present, increase maxHttpHeaderSize even further and try again. Beware: tuning this setting can increase the memory usage of Jira, as well.

Alternatively, you can export the issues in your backlog from the Issue Navigator screen! This screen works differently and completely avoids the problem with the URL length.

Steps:

  1. Open the backlog, click the Board dropdown in the top right, then Configure.
  2. Click the Edit Filter Query button.
  3. It will show you the JQL used for this board. Note that it will return also the issues that are not open or are not in the backlog (but a sprint)! The JQL will be something like this:
    project = FOO ORDER BY Rank ASC
  4. Go to the Issue Navigator. Take the previous JQL, and add these additional filters in front of the ORDER BY clause:
    AND issuetype NOT IN subtaskIssueTypes() AND issuetype != Epic AND resolution = Unresolved AND (Sprint = EMPTY OR Sprint NOT IN (openSprints(), futureSprints())) AND status != Resolved
    The resulting JQL will look something like this:
    project = FOO AND issuetype NOT IN subtaskIssueTypes() AND issuetype != Epic AND resolution = Unresolved AND (Sprint = EMPTY OR Sprint NOT IN (openSprints(), futureSprints())) AND status != Resolved ORDER BY Rank ASC
  5. Execute the JQL query, and you should get the issues in the backlog. (If there are differences, you may need to polish the JQL a bit.)
  6. Export the issues.

Font-related problems

I see '#' characters instead of Cyrillic / Chinese / Japanese / etc. characters in the PDF files.

The most typical problem with fonts is that your document contains a character, but its glyph (symbol) is not available in the supplied font. For example, your issue description contains a Chinese character, but the supplied font does not contain any Asian glyph.

When the glyph for a character is not found, the renderer will replace it with the hash character '#' in the final PDF document. It means that seeing unexpected hash characters in the document is the typical indicator of the problem. Please note that even with this, the PDF document will be successfully rendered and will be a valid file.

Depending on the number and importance of the missing glyphs:

  1. The document may be usable if only a single unimportant glyph was missing (like an emoji).
  2. The document may be unusable if a high number of important glyphs were missing (like all Kanji and Kana in a Japanese document).

If it is the latter, use automatic (easier) or custom fonts (more control).

I see "Times" or "Times New Roman" being used in my PDF instead of the custom font I set in the template.

When you are trying to use a font family in the FO template, but the corresponding font file is not found by the renderer, it will use "Times" instead. Unexpectedly seeing "Times" indicates that the custom font is not properly configured.

Review your custom font configuration and check the following typical problems:

  1. Whether the font directory is existing in the filesystem.
  2. Whether the font directory name is correctly set to the <directory> element in fop-config.xml.
  3. Whether the font file is existing in that directory.
  4. Whether the font family name is correctly set to the font-family="myfont" attribute.
I see "java.io.FileNotFoundException: .fop (Permission denied)" exceptions.

The PDF renderer may try to use a cache file to speed up its font-related operations. This exception is thrown if the cache file cannot be created in the filesystem due to permission problems, i.e. if the operating system user who started the Jira process cannot write to the filesystem in a certain location.

As caching does not affect the performance of the export, unless you make heavy use of a large number of fonts, we suggest disabling caching. For that, add this setting to the fop-config.xml file (which you can edit similarly to a PDF templates):

<!-- ... -->

<!-- default page dimensions in case value is specified as "auto" -->
<default-page-settings height="11in" width="8.26in"/>

<!-- disable caching (to avoid the potential ".fop (Permission denied)" problem) -->
<use-cache>false</use-cache><!-- this is the line to add! -->

<!-- DO NOT DELETE: substitutions for the "auto" pseudo font family -->
<fonts>

<!-- ... -->

Note that caching is disabled by default since app version 7.3.0. Therefore, the problem will not occur in those versions.

I see "Only 0 of the 4 expected font substitutions updated to font family Arial Unicode MS" warnings.

This occurs when you are using automatic fonts, but the configuration file fop-config.xml is broken. You have possibly removed some sections, which are required by automatic fonts, from that.

Solution: save a backup of your current fop-config.xml, restore the file to its factory default state, then re-apply your customization if there were.

I see "java.lang.UnsupportedOperationException: ... not yet supported" exceptions when using a custom font.

Certain fonts may use special features known as "complex scripts" which are not yet supported by the PDF renderer. For example, the Roboto font is known to cause this issue.

If you are working with European languages only, you can safely disable the "complex scripts" feature:

  1. Login to Jira as administrator.
  2. Go to AdministrationAdd-onsPDF Templates.
  3. Open the fop-config.xml file.
  4. Apply the change explained at point 3 in the Disabling complex scripts section.
  5. Save your changes.

Dashboard-related problems

I get errors when exporting a dashboard that contains Sprint Burndown or Wallboard gadgets.

For the investigation of these kind of problems, we need to know more details about the board, the sprint, the issues and the changes during the sprint. Follow these steps:

  1. Open the problematic dashboard in your browser.
  2. Take a screenshot about the problematic gadget.
  3. Hit F12 to open the Developer Tools view (built to your browser).
  4. Click the Network tab and clear the logs if any is visible.
  5. Refresh the dashboard in the browser, and wait till it is completely finished loading.
  6. Search for scopechangeburndownchart.json (in case of Sprint Burndown Gadget problem) or allData.json (in case of Wallboard Gadget problem) in the list of URLs.
  7. Click it to show the request's details in the right, then click the Response tab.
  8. Copy the whole JSON string shown, and paste that into a new text file.
  9. Attach both the image file and the JSON file to the support ticket. This helps us to see the expected output (image) and the input (JSON).

The instructions above are made for Google Chrome, but very similar steps should be taken in other types of browsers. It should be trivial, but feel free ask our help any time.

Other problems

Table borders and underlines are blurred and are drawn with varying line thickness.

When viewing a PDF file in Adobe Reader, especially those with tables and lines, some lines may look thicker than other lines and even different sections of the same line may look somewhat blurry. It is caused by the "Enhance thin lines" feature of Adobe Reader, designed for lower resolution CRT monitors.

To enhance the look, turn off the feature in your Adobe Reader: navigate to EditPreferencesPage Display and uncheck the Enhance thin lines option. There is an additional option called Smooth line art that can make your lines laser-sharp, but can also cause other visual artifacts at line junctions (e.g. borders at the table corners). Find the combination that works best for you.

Unfortunately, these display settings are local (specific to your computer), not attributes of the PDF file itself.

Unwanted empty space is added between an image and the next block.

You may encounter this most typically when you forget to update the default issue-fo.vm template after upgrading the app to 11.0.0 or later.

Theoretically, it may also occur with any template that contains an <fo:external-graphic> element to render an image. The symptom is that there is a large block of unwanted empty space between the image (the attachment image) and the next block (the block containing the image's file name and size).

To fix it, just find this expression:

<fo:external-graphic width="100%" height="100%" content-width="scale-to-fit" content-height="100%" src="url('$url')"/>

...and remove the height attribute:

<fo:external-graphic width="100%" content-width="scale-to-fit" content-height="100%" src="url('$url')"/>

Save your changes and try again.

Questions?

Ask us any time.