From c92393b168634c1c5641ab35dfb84f5de0429190 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 24 Oct 2017 13:14:53 +0200 Subject: [PATCH] Compatibility with OpenPDF as alternative to iText 2.1.7 Issue: SPR-16107 (cherry picked from commit 9efdadc) --- .../view/document/AbstractPdfStamperView.java | 7 +- .../view/document/AbstractPdfView.java | 18 ++- src/asciidoc/web-view.adoc | 153 +++++++++++++----- 3 files changed, 127 insertions(+), 51 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfStamperView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfStamperView.java index d7e8705545..559745383f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfStamperView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfStamperView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,11 @@ import org.springframework.web.servlet.view.AbstractUrlBasedView; * document with an AcroForm. Application-specific view classes * will extend this class to merge the PDF form with model data. * + *

This view implementation uses Bruno Lowagie's + * iText package. + * Known to work with iText 2.1.7 as well as its fork + * OpenPDF. + * *

Thanks to Bryant Larsen for the suggestion and the original prototype! * * @author Juergen Hoeller diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfView.java index 516425c399..f3baaae4ed 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/document/AbstractPdfView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,13 +30,17 @@ import com.lowagie.text.pdf.PdfWriter; import org.springframework.web.servlet.view.AbstractView; /** - * Abstract superclass for PDF views, using Bruno Lowagie's - * iText package. - * Application-specific view classes will extend this class. - * The view will be held in the subclass itself, not in a template. + * Abstract superclass for PDF views. Application-specific view classes + * will extend this class. The view will be held in the subclass itself, + * not in a template. * - *

Note: Internet Explorer requires a ".pdf" extension, as - * it doesn't always respect the declared content type. + *

This view implementation uses Bruno Lowagie's + * iText package. + * Known to work with iText 2.1.7 as well as its fork + * OpenPDF. + * + *

Note: Internet Explorer requires a ".pdf" extension, as it doesn't + * always respect the declared content type. * * @author Rod Johnson * @author Juergen Hoeller diff --git a/src/asciidoc/web-view.adoc b/src/asciidoc/web-view.adoc index 7e01497584..7458ab2937 100644 --- a/src/asciidoc/web-view.adoc +++ b/src/asciidoc/web-view.adoc @@ -1,9 +1,12 @@ [[view]] -= View technologies += View Technologies + + [[view-introduction]] == Introduction + One of the areas in which Spring excels is in the separation of view technologies from the rest of the MVC framework. For example, deciding to use Groovy Markup Templates or Thymeleaf in place of an existing JSP is primarily a matter of configuration. @@ -13,6 +16,8 @@ briefly on how to add new ones. This chapter assumes you are already familiar wi to the MVC framework. + + [[view-thymeleaf]] == Thymeleaf @@ -26,6 +31,8 @@ Please refer to the http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring documentation section for more details. + + [[view-groovymarkup]] == Groovy Markup Templates @@ -36,6 +43,8 @@ text based content. This requires Groovy 2.3.1+ on the classpath. + + [[view-groovymarkup-configuration]] === Configuration @@ -76,6 +85,8 @@ The XML counterpart using the MVC namespace is: ---- + + [[view-groovymarkup-example]] === Example @@ -98,8 +109,11 @@ Here is a sample template for an HTML page: ---- + + [[view-velocity]] == Velocity & FreeMarker + http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two templating languages that can be used as view technologies within Spring MVC applications. The languages are quite similar and serve similar needs and so are @@ -117,6 +131,7 @@ FreeMarker support instead, or Thymeleaf which comes with Spring support itself. [[view-velocity-dependencies]] === Dependencies + Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar` in order to work with Velocity or FreeMarker respectively and `commons-collections.jar` is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where @@ -130,6 +145,7 @@ your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribu [[view-velocity-contextconfig]] === Context configuration + A suitable configuration is initialized by adding the relevant configurer bean definition to your `'{asterisk}-servlet.xml'` as shown below: @@ -185,6 +201,7 @@ For non web-apps add a `VelocityConfigurationFactoryBean` or a [[view-velocity-createtemplates]] === Creating templates + Your templates need to be stored in the directory specified by the `{asterisk}Configurer` bean shown above. This document does not cover details of creating templates for the two languages - please see their relevant websites for information. If you use the view @@ -198,6 +215,7 @@ template as appropriate. [[view-velocity-advancedconfig]] === Advanced configuration + The basic configurations highlighted above will be suitable for most application requirements, however additional configuration options are available for when unusual or advanced requirements dictate. @@ -205,6 +223,7 @@ advanced requirements dictate. [[view-velocity-example-velocityproperties]] ==== velocity.properties + This file is completely optional, but if specified, contains the values that are passed to the Velocity runtime in order to configure velocity itself. Only required for advanced configurations, if you need this file, specify its location on the @@ -247,6 +266,7 @@ examples and definitions of the `'velocity.properties'` file itself. [[views-freemarker]] ==== FreeMarker + FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker `Configuration` object managed by Spring by setting the appropriate bean properties on the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a @@ -275,6 +295,7 @@ the `Configuration` object. [[view-velocity-forms]] === Bind support and form handling + Spring provides a tag library for use in JSP's that contains (amongst other things) a `` tag. This tag primarily enables forms to display values from form backing objects and to show the results of failed validations from a `Validator` in the @@ -285,6 +306,7 @@ generating form input elements themselves. [[view-bind-macros]] ==== The bind macros + A standard set of macros are maintained within the `spring-webmvc.jar` file for both languages, so they are always available to a suitably configured application. @@ -299,6 +321,7 @@ directly, the files are called spring.vm / spring.ftl and are in the packages [[view-simple-binding]] ==== Simple binding + In your HTML forms (vm / ftl templates) which act as a form view for a Spring MVC controller, you can use code similar to the following to bind to field values and display error messages for each input field in similar fashion to the JSP equivalent. @@ -364,6 +387,7 @@ wherever possible. They are explained in the next section. [[views-form-macros]] ==== Form input generation macros + Additional convenience macros for both languages simplify both binding and form generation (including validation error display). It is never necessary to use these macros to generate form input fields, and they can be mixed and matched with simple HTML @@ -467,6 +491,7 @@ differences exist between the two languages, they are explained in the notes. [[views-form-macros-input]] ===== Input Fields + [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -519,6 +544,7 @@ information or rows and cols attributes for the textarea. [[views-form-macros-select]] ===== Selection Fields + Four selection field macros can be used to generate common UI value selection inputs in your HTML forms. @@ -566,15 +592,15 @@ codes would be created with suitable keys like the example below. [source,java,indent=0] [subs="verbatim,quotes"] ---- - protected Map referenceData(HttpServletRequest request) throws Exception { - Map cityMap = new LinkedHashMap(); + protected Map referenceData(HttpServletRequest request) throws Exception { + Map cityMap = new LinkedHashMap<>(); cityMap.put("LDN", "London"); cityMap.put("PRS", "Paris"); cityMap.put("NYC", "New York"); - Map m = new HashMap(); - m.put("cityMap", cityMap); - return m; + Map model = new HashMap<>(); + model.put("cityMap", cityMap); + return model; } ---- @@ -593,6 +619,7 @@ user still sees the more user friendly city names. [[views-form-macros-html-escaping]] ==== HTML escaping and XHTML compliance + Default usage of the form macros above will result in HTML tags that are HTML 4.01 compliant and that use the default value for HTML escaping defined in your web.xml as used by Spring's bind support. In order to make the tags XHTML compliant or to override @@ -637,6 +664,7 @@ In similar fashion, HTML escaping can be specified per field: [[view-jsp]] == JSP & JSTL + Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP or JSTL is done using a normal view resolver defined in the `WebApplicationContext`. Furthermore, of course you need to write some JSPs that will actually render the view. @@ -657,6 +685,7 @@ somewhat. [[view-jsp-resolver]] === View resolvers + Just as with any other view technology you're integrating with Spring, for JSPs you'll need a view resolver that will resolve your views. The most commonly used view resolvers when developing with JSPs are the `InternalResourceViewResolver` and the @@ -700,6 +729,7 @@ under the `'WEB-INF'` directory, so there can be no direct access by clients. [[view-jsp-jstl]] === 'Plain-old' JSPs versus JSTL + When using the Java Standard Tag Library you must use a special view class, the `JstlView`, as JSTL needs some preparation before things such as the I18N features will work. @@ -707,7 +737,8 @@ work. [[view-jsp-tags]] -=== Additional tags facilitating development +=== Spring's JSP tag library + Spring provides data binding of request parameters to command objects as described in earlier chapters. To facilitate the development of JSP pages in combination with those data binding features, Spring provides a few tags that make things even easier. All @@ -720,7 +751,8 @@ information about the individual tags can be found in the appendix entitled [[view-jsp-formtaglib]] -=== Using Spring's form tag library +=== Spring's form tag library + As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags @@ -737,6 +769,7 @@ included generated HTML snippets where certain tags require further commentary. [[view-jsp-formtaglib-configuration]] ==== Configuration + The form tag library comes bundled in `spring-webmvc.jar`. The library descriptor is called `spring-form.tld`. @@ -1400,7 +1433,8 @@ The HTML would look like: [[rest-method-conversion]] -==== HTTP Method Conversion +==== HTTP method conversion + A key principle of REST is the use of the Uniform Interface. This means that all resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST, and DELETE. For each method, the HTTP specification defines the exact semantics. For @@ -1460,7 +1494,8 @@ The corresponding `@Controller` method is shown below: [[view-jsp-formtaglib-html5]] -==== HTML5 Tags +==== HTML5 tags + Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, which means you can enter any HTML5 specific attributes. @@ -1471,8 +1506,9 @@ is the default type. + [[view-script]] -== Script templates +== Script views It is possible to integrate any templating library running on top of a JSR-223 script engine in web applications using Spring. The following describes in a @@ -1488,8 +1524,10 @@ It has been tested with: * http://www.stuartellis.eu/articles/erb/[ERB] running on http://jruby.org[JRuby] * https://docs.python.org/2/library/string.html#template-strings[String templates] running on http://www.jython.org/[Jython] + + [[view-script-dependencies]] -=== Dependencies +=== Requirements To be able to use script templates integration, you need to have available in your classpath the script engine: @@ -1508,8 +1546,9 @@ for Javascript you can use http://www.webjars.org/[WebJars] to add Maven/Gradle in order to make your javascript libraries available in the classpath. + [[view-script-integrate]] -=== How to integrate script based templating +=== Script templates To be able to use script templates, you have to configure it in order to specify various parameters like the script engine to use, the script files to load and what function should be called to @@ -1669,7 +1708,8 @@ for more configuration examples. [[view-xml-marshalling]] -== XML Marshalling View +== XML Marshalling + The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` package to render the response content as XML. The object to be marshalled can be set explicitly using ``MarhsallingView``'s `modelKey` bean property. Alternatively, the view @@ -1681,13 +1721,12 @@ Mappers>>. - [[view-tiles]] == Tiles + It is possible to integrate Tiles - just as any other view technology - in web applications using Spring. The following describes in a broad way how to do this. - [NOTE] ==== This section focuses on Spring's support for Tiles v3 in the @@ -1695,15 +1734,19 @@ This section focuses on Spring's support for Tiles v3 in the ==== + [[view-tiles-dependencies]] === Dependencies + To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher and http://tiles.apache.org/framework/dependency-management.html[its transitive dependencies] to your project. + [[view-tiles-integrate]] -=== How to integrate Tiles +=== Configuration + To be able to use Tiles, you have to configure it using files containing definitions (for basic information on definitions and other Tiles concepts, please have a look at http://tiles.apache.org[]). In Spring this is done using the `TilesConfigurer`. Have a @@ -1778,7 +1821,7 @@ resolve. ==== ResourceBundleViewResolver The `ResourceBundleViewResolver` has to be provided with a property file containing -viewnames and viewclasses the resolver can use: +view names and view classes the resolver can use: [source,xml,indent=0] [subs="verbatim,quotes"] @@ -1854,18 +1897,16 @@ per preparer name (as used in your Tiles definitions). + [[view-xslt]] == XSLT + XSLT is a transformation language for XML and is popular as a view technology within web applications. XSLT can be a good choice as a view technology if your application naturally deals with XML, or if your model can easily be converted to XML. The following section shows how to produce an XML document as model data and have it transformed with XSLT in a Spring Web MVC application. - - -[[view-xslt-firstwords]] -=== My First Words This example is a trivial Spring application that creates a list of words in the `Controller` and adds them to the model map. The map is returned along with the view name of our XSLT view. See <> for details of Spring Web MVC's @@ -1873,8 +1914,10 @@ name of our XSLT view. See <> for details of Spring Web MVC's document ready for transformation. + [[view-xslt-beandefs]] -==== Bean definitions +=== Beans + Configuration is standard for a simple Spring application. The MVC configuration has to define a `XsltViewResolver` bean and regular MVC annotation configuration. @@ -1901,8 +1944,9 @@ public class WebConfig extends WebMvcConfigurerAdapter { And we need a Controller that encapsulates our word generation logic. + [[view-xslt-controllercode]] -==== Standard MVC controller code +=== Controller The controller logic is encapsulated in a `@Controller` class, with the handler method being defined like so... @@ -1947,15 +1991,15 @@ Next, `XsltViewResolver` will resolve the "home" XSLT template file and merge th DOM document into it to generate our view. + [[view-xslt-transforming]] -==== Document transformation +=== Transformation Finally, the `XsltViewResolver` will resolve the "home" XSLT template file and merge the DOM document into it to generate our view. As shown in the `XsltViewResolver` configuration, XSLT templates live in the war file in the `'WEB-INF/xsl'` directory and end with a `"xslt"` file extension. - [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2004,34 +2048,41 @@ This is rendered as: ---- + + + [[view-document]] -== Document views (PDF/Excel) +== Document views: PDF, Excel [[view-document-intro]] === Introduction + Returning an HTML page isn't always the best way for the user to view the model output, and Spring makes it simple to generate a PDF document or an Excel spreadsheet dynamically from the model data. The document is the view and will be streamed from the server with the correct content type to (hopefully) enable the client PC to run their spreadsheet or PDF viewer application in response. -In order to use Excel views, you need to add the 'poi' library to your classpath, and -for PDF generation, the iText library. +In order to use Excel views, you need to add the Apache POI library to your classpath, +and for PDF generation, the common iText 2.1.7 or its fork OpenPDF (e.g. OpenPDF 1.0.4). [[view-document-config]] -=== Configuration and setup +=== Configuration + Document based views are handled in an almost identical fashion to XSLT views, and the following sections build upon the previous one by demonstrating how the same controller used in the XSLT example is invoked to render the same model as both a PDF document and an Excel spreadsheet (which can also be viewed or manipulated in Open Office). + [[view-document-configviews]] -==== Document view definitions +=== View definition + First, let's amend the views.properties file (or xml equivalent) and add a simple view definition for both document types. The entire file now looks like this with the XSLT view shown from earlier: @@ -2052,16 +2103,20 @@ __If you want to start with a template spreadsheet or a fillable PDF form to add model data to, specify the location as the 'url' property in the view definition__ + [[view-document-configcontroller]] -==== Controller code +=== Controller + The controller code we'll use remains exactly the same from the XSLT example earlier other than to change the name of the view to use. Of course, you could be clever and have this selected based on a URL parameter or some other logic - proof that Spring really is very good at decoupling the views from the controllers! + [[view-document-configsubclasses]] -==== Subclassing for Excel views +=== Excel views + Exactly as we did for the XSLT example, we'll subclass suitable abstract classes in order to implement custom behavior in generating our output documents. For Excel, this involves writing a subclass of @@ -2144,8 +2199,10 @@ that the Excel spreadsheet is created and downloaded automatically when you requ same page as before. + [[view-document-configsubclasspdf]] -==== Subclassing for PDF views +=== PDF views + The PDF version of the word list is even simpler. This time, the class extends `org.springframework.web.servlet.view.document.AbstractPdfView` and implements the `buildPdfDocument()` method as follows: @@ -2179,6 +2236,7 @@ document should appear listing each of the words in the model map. [[view-jasper-reports]] == JasperReports + JasperReports ( http://jasperreports.sourceforge.net[]) is a powerful open-source reporting engine that supports the creation of report designs using an easily understood XML file format. JasperReports is capable of rendering reports in four different @@ -2188,8 +2246,9 @@ formats: CSV, Excel, HTML and PDF. [[view-jasper-reports-dependencies]] === Dependencies -Your application will need to include the latest release of JasperReports, which at the -time of writing was 0.6.1. JasperReports itself depends on the following projects: + +Your application will need to include a recent release of JasperReports, e.g. 6.2. +JasperReports itself depends on the following projects: * BeanShell * Commons BeanUtils @@ -2199,12 +2258,13 @@ time of writing was 0.6.1. JasperReports itself depends on the following project * iText * POI -JasperReports also requires a JAXP compliant XML parser. +JasperReports also requires a JAXP-compliant XML parser. [[view-jasper-reports-configuration]] === Configuration + To configure JasperReports views in your Spring container configuration you need to define a `ViewResolver` to map view names to the appropriate view class depending on which format you want your report rendered in. @@ -2277,6 +2337,7 @@ file. [[view-jasper-reports-configuration-report-files]] ==== About Report Files + JasperReports has two distinct types of report file: the design file, which has a `.jrxml` extension, and the compiled report file, which has a `.jasper` extension. Typically, you use the JasperReports Ant task to compile your `.jrxml` design file into @@ -2413,7 +2474,8 @@ approach. [[view-jasper-reports-subreports]] -=== Working with Sub-Reports +=== Working with sub-reports + JasperReports provides support for embedded sub-reports within your master report files. There are a wide variety of mechanisms for including sub-reports in your report files. The easiest way is to hard code the report path and the SQL query for the sub report @@ -2424,7 +2486,8 @@ and you can include additional data for these sub-reports directly from your con [[view-jasper-reports-subreports-config-reports]] -==== Configuring Sub-Report Files +==== Configuring sub-report files + To control which sub-report files are included in a master report using Spring, your report file must be configured to accept sub-reports from an external source. To do this you declare a parameter in your report file like so: @@ -2475,7 +2538,8 @@ the given key. [[view-jasper-reports-subreports-config-datasources]] -==== Configuring Sub-Report Data Sources +==== Configuring sub-report data sources + This step is entirely optional when using Spring to configure your sub-reports. If you wish, you can still configure the data source for your sub-reports using static queries. However, if you want Spring to convert data returned in your `ModelAndView` into @@ -2495,7 +2559,8 @@ and the key used in your report design file. [[view-jasper-reports-exporter-parameters]] -=== Configuring Exporter Parameters +=== Configuring exporter parameters + If you have special requirements for exporter configuration -- perhaps you want a specific page size for your PDF report -- you can configure these exporter parameters declaratively in your Spring configuration file using the `exporterParameters` property @@ -2530,7 +2595,8 @@ which will output a footer in the resulting HTML. [[view-feeds]] -== Feed Views +== Feed views: RSS, Atom + Both `AbstractAtomFeedView` and `AbstractRssFeedView` inherit from the base class `AbstractFeedView` and are used to provide Atom and RSS Feed views respectfully. They are based on java.net's https://rome.dev.java.net[ROME] project and are located in the @@ -2595,6 +2661,7 @@ https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-sp [[view-json-mapping]] == JSON Mapping View + The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response content as JSON. By default, the entire contents of the model map (with the exception of framework-specific classes) will be encoded as JSON. For cases where the contents of the @@ -2617,6 +2684,7 @@ name(s) could be customized through the `jsonpParameterNames` property. [[view-xml-mapping]] == XML Mapping View + The `MappingJackson2XmlView` uses the https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML extension]'s `XmlMapper` to render the response content as XML. If the model contains multiples entries, the @@ -2627,4 +2695,3 @@ XML mapping can be customized as needed through the use of JAXB or Jackson's pro annotations. When further control is needed, a custom `XmlMapper` can be injected through the `ObjectMapper` property for cases where custom XML serializers/deserializers need to be provided for specific types. -