DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Creating Annotations in Java
  • Automate Migration Assessment With XML Linter
  • Smart BDD vs. Cucumber Using Java and JUnit5
  • Java: A Time-Tested Programming Language Still Going Strong

Trending

  • What Is Kubernetes RBAC and Why Do You Need It?
  • Monkey-Patching in Java
  • Securing Your Applications With Spring Security
  • How To Optimize Feature Sets With Genetic Algorithms
  1. DZone
  2. Coding
  3. Frameworks
  4. A PDF Framework That Solves the Pain Points of Enterprise Development

A PDF Framework That Solves the Pain Points of Enterprise Development

In this article, learn about a PDF framework that solves the pain points of enterprise development using Java and JavaScript.

jinqiu hong user avatar by
jinqiu hong
·
Sep. 05, 23 · Tutorial
Like (1)
Save
Tweet
Share
4.96K Views

Join the DZone community and get the full member experience.

Join For Free

What Is Nanhu-Print-Java?

Nanhu-print-java is a PDF generation framework implemented in the Java language. 

Users can prepare the JSON format business data and an XML format configure file, then call the nanhu-print-java framework API to complete the generation of a PDF file.

Nanhu-print-java's GitHub address can be found here. 

Here is a development video.

Background of the Birth of Nanhu-Print-Java

The company I work for wants to implement a custom printing function, which needs to meet the following functions:

  1. Define some templates. For each field of each template, the label can be customized, displayed, and hidden, the width of each column of the table can be customized, and users can select fields for these templates on the browser side.
  2. The header of the template. The header of the table needs to be displayed on every page, and information such as amount summary and signature need to be fixed at the bottom of the page.

The company prepared two technical solutions at the beginning:

  1. The front and back ends are implemented separately.  The front end uses JS to realize the page and control the page fields, and the back end uses Java to call the iText pdf library to generate pdf for printing.
  2. The front end implements almost all the functions. After the front-end, JS implements the page, the generated HTML is sent to the back-end, and the back-end uses Java to call the HTML-to-PDF framework to generate the PDF for printing.

It is worth considering that each field on the page has to do complex display and hide operations, and the development of the interface display directly through Java is very cumbersome. After the development is completed, changes in requirements, the addition of fields, and the subtraction of fields will all involve program modifications. The code would be bad maintenance. Therefore, the first option was rejected.

Therefore, the company chose the second solution, using JS to generate HTML on the front end and sending it to the back end to convert HTML to PDF.

During the implementation process, the following problems were encountered that were difficult to solve:

  1. There are obvious differences in fonts, page styles, etc., between the front-end HTML and the PDF generated by the back-end. For a longer document, with a long table inside the document, it will appear on multiple pages when printed. The front-end JS code generates a div according to the defined height and adds the content of the page one by one. When the content exceeds one page, it regenerates a div and adds content to it. The div array takes shape into multiple pages. After sending these multiple pages to the backend, using HTML to PDF framework, and generating a PDF, it is found that the frontend displays a good HTML page due to the difference of font fendering between the frontend windows and the backend Linux environment and the browser in the front-end windows environment differs from the analysis of the CSS style by the html-to-pdf framework in the back-end environment. The PDF generated by the back-end will have the problem that the page content is too small or too large, leading to the printing effect is not good. For example, an A4 page, an HTML page at the front end, fills the entire div, and the display is very beautiful, but when the pdf is generated, due to the small font size or the framework conversion, the content of the generated pdf page is very small: there is a lot of white space at the bottom of the entire pdf page. However, due to the opacity of converting HTML to PDF, this problem is difficult to solve.
  2. There are complicated JS controls on the page to display and hide, and the page code is difficult to maintain. For example, when a certain column of the table adjusts the column width, the text in this column may wrap. At this time, the part of the content that was originally at the end of the table will be pushed out of the page boundary, and it is necessary to trigger the height control code of the page elements. After a period of failed development and testing, the author developed the Nanhu-print-java framework, which solved the problems encountered by the company relatively smoothly. Nanhu-print-java defines a file in XML format, which defines dynamic tags such as if, forEach, and set and static tags such as table, div, and span. Constrain users to only use these tags. On the front end, through Nanhu-print-js, parse XML to generate HTML, which will be displayed in the browser. On the back end, the PDF is generated by parsing XML so that the font and other styles of PDF are not affected by the front-end environment, which better solves the problem of differences between front-end display and back-end printing. The user's development process is mainly to configure files in XML format, and there is basically no complicated code control, which also achieves the effect of greatly improving development efficiency and reducing maintenance costs.

The Basic Workflow of Nanhu-Print-Java

The Basic Workflow of Nanhu-Print-Java

First of all, Nanhu-print-java is a PDF printing framework that defines its own XML model format file. When users write XML format files, they need to follow the element definition of the XSD file.

As shown in the figure above, when using Nanhu-print-java, the user must prepare the XML model file and the business data to be printed and then call the framework API of Nanhu-print-java to complete the generation of the PDF file.

The sample code is as follows:

sample code

Main Functions of Nanhu-Print-Java

Each Page Has a Fixed Header, and the Last Page Has a Fixed Footer

Bill printing is a common function in enterprise applications. It is usually required to display the title and company name at the top of a page and display the summary of the table amount, date, company signature, and other information at the bottom of the page.

If the table information in the document is relatively long and there are multiple pages, it is usually required to have the table head row information at the top of every page.

Using the Nanhu-print-java framework, users can complete such functions conveniently and quickly through configuration.

The simplified content of the configuration is:

XML
 
	 <body>

        <params>

            <param name="extendToFillBody" value="default"></param>

        </params>

        <table>

            <thead showPosition="firstPage">

                BillTitle,,,,,,

            </thead>

            <thead showPosition="everyPage">

                table head content,,,,,,

            </thead>

            <tbody>

                table body content,,,,,,

            </tbody>

            <tloop>

                last page fill content,,,,,,

            </tloop>

            <tbottom>

                last page bottom content,,,,,,

            </tbottom>

        </table>

    </body>


Display Page Number at Any Position on Every Page

For multi-page documents, it may be necessary to display page numbers in the table header and may also need to display page numbers in the table footer.

Users can use the following configuration methods to realize page number-related information appearing anywhere on the page.

XML
 
   <div>

        <params>

            <param name="customContent" value="com.hongjinqiu.nanhuprint.eval.custom.CustomPageNumber" />

            <param name="customContentFormat" value="{currentPageNumber} of {totalPageNumber}" />

        </params>

    </div>


Print With Template

For documents such as courier orders, when developing a PDF printing template, a picture needs to be used as the background. When users use Nanhu-print-java to develop this type of version, they can set the background image and then adjust the padding value of the text:

XML
 
	 <div backgroundSize="contain" width="100px" height="420px">

        <css>

            <backgroundImage js="url('http://xxxx.png')" />

        </css>

        <div paddingLeft="10px" paddingTop="24px"><span value="InvoiceCode" /></div>

    </div>


Watermark

The Nanhu-print-java framework supports text watermarking or image watermarking through configuration. 

The configuration is as follows:

Image Watermark

XML
 
	 <div fontWeight="bold" paddingTop="10">

        <params>

            <param name="waterMark" value="default" />

            <param name="waterMarkOpacity" value="0.9" />

            <param name="waterMarkOffsetX" value="-150" />

            <param name="waterMarkOffsetY" value="0" />

            <param name="waterMarkImage" value="http://localhost:8891/images/camel.png" />

            <param name="waterMarkImageWidth" value="200" />

            <param name="waterMarkImageHeight" value="78" />

            <param name="waterMarkRotation" value="45" />

            <param name="waterMarkLayer" value="default" />

        </params>

    </div>


Text Watermark

XML
 
	<div>

        <params>

            <param name="waterMark" value="default" />

            <param name="waterMarkText" value="I am waterMarkText" />

            <param name="waterMarkOpacity" value="0.5" />

            <param name="waterMarkTextFontSize" value="24" />

            <param name="waterMarkOffsetX" value="0" />

            <param name="waterMarkOffsetY" value="100" />

            <param name="waterMarkRotation" value="45" />

            <param name="waterMarkLayer" value="under" />

        </params>

    </div>


Different Backgrounds of Table Rows Are Printed Alternately

If you have a long table and need to display different background colors for each row, you can easily implement it through configuration. 

The configuration example is:

XML
 
	<forEach var="item" itemsJs="data.contentList" varStatus="index">

        <set valueJs="'white'" var="loopBgColor" />

        <if testJs="index %2 == 0">

            <set valueJs="'orange'" var="loopBgColor" />

        </if>

        <tr fontFamily="abc" backgroundColor="js:loopBgColor">

            <td width="100%">

                <div paddingTop="20">

                    <span value="js:item"/>

                </div>

            </td>

        </tr>

    </forEach>


Use Dynamic Tags To Implement Complex Display Logic

Nanhu-print-java framework supports dynamic tags: if, forEach, macroRef, set, Macro.

An example configuration is:

XML
 
	<if testJs="index %2 == 0"></if>

    <forEach var="item" itemsJs="data.contentList" varStatus="index"></forEach>


Macros for Repeating Block References

On the page, if there are repeated code display blocks, you can put the repeated code display blocks in the macro tag and then refer to them in other places.

Define macro code block:

XML
 
	<macro name="addressBillingMacro">

        <div cls="f12">

            <span value="wwww"/>

        </div>

    </macro>


Refer macro code block:

XML
 
<macroRef name="addressBillingMacro"/>


Reduce the Font Size in the Cell To Show the Full Content

In the printing of documents, sometimes the cell width is fixed, but the cell content is too long, which can be configured through the scaleToFitContentByPdf parameter to easily achieve content scaling.

Configuration example:

XML
 
	<div width="20px" scaleToFitContentByPdf="true">

        <span value="RMB 999,999,999.99" />

    </div>


Cell Width Can Be Set To Change Dynamically With Cell Content

If you want the text not to shrink or wrap and the cell width to change with the content, you can configure it as follows:

XML
 
	<td textAlign="left">

        <params>

            <param name="calcWidth" value="com.hongjinqiu.nanhuprint.eval.custom.CalcWidth" />

            <param name="calcWidthTagId" value="leftIssueBy" />

        </params>

        <div id="leftIssueBy" cls="f13 bodyLineHeight" whiteSpace="nowrap" paddingRight="5px" >

            <span value="ISSUED BY:" />

        </div>

    </td>


Formatting of Fields Such as Quantity, Unit Price, and Amount

Quantity, unit price, amount, and other fields usually need to be formatted and displayed. 

Users can pass the value to the framework by formatting in the application.

The formatting of these fields can also be implemented through the configuration provided by the framework:

XML
 
	<span value="js:item.item_price" format="num"/>

    <span value="js:item.item_price" format="unitPrice"/>

    <span value="js:item.item_price" format="amt"/>


Java language PDF Framework Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Creating Annotations in Java
  • Automate Migration Assessment With XML Linter
  • Smart BDD vs. Cucumber Using Java and JUnit5
  • Java: A Time-Tested Programming Language Still Going Strong

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: