Skip to main content
 

Nuovo canale di esportazione per stampa diretta

Gli utenti possono esportare i reports Jasper in diversi formati, come PDF e CSV. Se avete bisogno di un altro formato di file, è possibile creare un canale di esportazione personalizzato. È necessario implementare una classe Java personalizzata che genera il formato di file richiesto quindi integrare la nuova classe nel server. Questa personalizzazione deve essere fatta nel codice sorgente di JasperReports Server. Per creare questo nuovo canale di esportazione ho seguito le istruzioni trovate su Adding custom export channels", nel portale Jasper della community. E necessario lavorare con JasperResports Server Source Code e, inseconda battuta, un deploy del codice sul server Jasper di produzione. Così per prima cosa è necessario usare le istruzioni del link sopra e crearsi in locale l'ambiente di sviluppo.

Verrà creato un nuovo canale di esportazione in TXT piatto. Il file risultante verrà inviato direttamente in stampa, e il nome della stampante sarà tra i parametri dell' URl di lancio del report. La stampante deve essere installata sul server Jasper, non stiamo parlando di stampanti installate sui client che lanciaranno il report. Le stampanti che andremo ad usare sono quelle che possono essere usate dal report server Jasper.

Questo nuovo canale sarà aggiunto agli altri nel Jasper Report Viewer, ma può essere aggiunto anche allo scheduler e ai web service Jasper.

Parametri export - printer name

I parametri di esportazione definiscono il modo in cui JasperReports Server genera il formato di output. Ad esempio, il parametro "layout" per definire l' aspetto della pagina, con valori possibili come LANDSCAPE o PORTRAIT.

I parametri di esportazione hanno valori predefiniti che possono essere impostati a report o livello di applicazione. Molti parametri sono opzionali; altri sono validi solo per alcuni canali di esportazione. Quando si crea un canale di esportazione, è possibile definire nuovi parametri per controllare come verranno esportati i report nel nuovo formato.

Nel nostro caso, un parametro viene utilizzato per definire il nome della stampante.

Aggiungere un nuovo canale di esportazione al "Report viewer" Jasper

Si tratta della lista dorp-down a disposizione in face di preview del report.

Questi sono gli step richiesti:

  1. Creare una nuova classe exporter che stenda AbstractReportExporter
  2. Creare un nuovo bean per i parametri che estenda AbstractExportParameters
  3. Creare un nuovo bean di configurazione che estenda ExporterConfigurationBean
  4. Aggiungere un "resource bundle" per la label del menù

1 - AbstractReportExporter class

La classe Java per AbstractReportExporter class (.java) si trova nel package com.jaspersoft.jasperserver.war.action. Considerando {jasper_src_home} la directory nella quale avete esploso il JasperReports Server source bundle, AbstractReportExporter.java si trova nella directory {jasper_src_home}/jasperserver/jasperserver-war-jar/src/main/java/com/jaspersoft/jasperserver/war/action. In questa directory inseriremo il nuovo file .java per l' Exporter. Il file e la classe Java si chiamano ReportPrintertxtExporter.java:

/*
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.war.action;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.engine.jasperreports.common.ExportParameters;
import com.jaspersoft.jasperserver.api.JSException;
import com.jaspersoft.jasperserver.api.engine.jasperreports.common.PrintertxtExportParametersBean;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.export.JRTextExporterParameter;
import net.sf.jasperreports.engine.export.JRTextExporter;
import org.springframework.webflow.core.collection.ParameterMap;
import org.springframework.webflow.execution.RequestContext;
import it.acme.jasperserver.TxtDirectPrint;
public class ReportPrintertxtExporter extends AbstractReportExporter{
	private static final String DIALOG_NAME = "printertxtExportParams";
	private PrintertxtExportParametersBean exportParameters;
	/**
	 * @return Returns the exportParameters.
	 */
	public PrintertxtExportParametersBean getExportParameters() {
		return exportParameters;
	}
	/**
	 * @return Returns the exportParameters.
	 */
	public ExportParameters getExportParameters(RequestContext context) {
		return context.getFlowScope().get(ReportPrintertxtExporter.DIALOG_NAME)== null? exportParameters : (ExportParameters)context.getFlowScope().get(ReportPrintertxtExporter.DIALOG_NAME);
	}
	/**
	 * @param exportParameters The exportParameters to set.
	 */
	public void setExportParameters(PrintertxtExportParametersBean exportParameters) {
		this.exportParameters = exportParameters;
	}
	public void export(RequestContext context, ExecutionContext executionContext, String reportUnitURI, Map baseParameters) throws JRException,JSException {
		JRTextExporter exporter = new JRTextExporter(getJasperReportsContext());
		exporter.setParameters(baseParameters);
		PrintertxtExportParametersBean exportParams = (PrintertxtExportParametersBean)getExportParameters(context);
		if (exportParams.isOverrideReportHints()) {
			exporter.setParameter(JRExporterParameter.PARAMETERS_OVERRIDE_REPORT_HINTS, Boolean.TRUE);
		}
		if (exportParams.getCharacterHeight() != null)
			exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, exportParams.getCharacterHeight());
		if (exportParams.getCharacterWidth() != null)
			exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, exportParams.getCharacterWidth());
		if (exportParams.getPageHeight() != null)
			exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, exportParams.getPageHeight());
		if (exportParams.getPageWidth() != null)
			exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, exportParams.getPageWidth());
		/*
		 * report is executed here, and result extracted in a plain TXT format
		 */
		exporter.exportReport();
		ParameterMap params = context.getRequestParameters();
		TxtDirectPrint dp = new TxtDirectPrint(params.asMap(),
				                               getFilename(context),
				                               getJasperReportsContext(),
				                               exporter.getCurrentJasperPrint());
		dp.print(); //the txt result is sent to printer
	}
	/*
	 * The txt results will be sent to browser too, when report is launched from report viewer
	 */
	protected String getContentType(RequestContext context) {
		return "application/txt";
	}
	protected void setAdditionalResponseHeaders(RequestContext context, HttpServletResponse response) {
		super.setAdditionalResponseHeaders(context, response);
		response.setHeader("Content-Disposition", "inline; filename=\"" + getFilename(context) + "\"");
	}
	protected String getDownloadFileExtension() {
		return "txt";
	}
}

Quetsa classe si riferisce ad un altra, it.acme.jasperserver.TxtDirectPrint. Questa nuova classe si trova in {jasper_src_home}/jasperserver/jasperserver-war-jar/src/main/java/it/acme/jasperserver ed è usata per lanciare la stampa.

/*
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package it.acme.jasperserver;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.export.JRTextExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleWriterExporterOutput;
import java.util.Map;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class TxtDirectPrint {
    private String printername;
    private String username;
    private String fileName;
    private JasperPrint jasperPrint;
    private JasperReportsContext jasperReportsContext;
    private Calendar calendar;
    private SimpleDateFormat sdf;
    /**
     * @param params        report parameters
     * @param filename      report file name
     * @param jasperReportsContext
     * @param jasperPrint   An instance of this class represents a page-oriented document that can be viewed, printed or exported to other formats.
     */
    public TxtDirectPrint(Map params,
                          String fileName,
                          JasperReportsContext jasperReportsContext,
                          JasperPrint jasperPrint) {
        this.setFileName(fileName);
        try {
            this.setUsername(params.get("username").toString());
        } catch (NullPointerException e) {
            this.setUsername("none");
        }
        try {
            this.setPrintername(params.get("printername").toString());
        } catch (NullPointerException e) {
            this.setPrintername(null);
        }
        this.setJasperReportsContext(jasperReportsContext);
        this.setJasperPrint(jasperPrint);
        this.calendar = Calendar.getInstance();
        this.sdf      = new SimpleDateFormat("yyyyMMddHHmmss");
    }
    /**
     * Dump TXT report to file system
     */
    private File dumpFile() {
        String timestamp = this.sdf.format(this.calendar.getTime());
        String fileName = System.getProperty("java.io.tmpdir") +
                          File.separator +
                          "Jasperserver";
        if (!(new File(fileName)).mkdirs()) {
           fileName = "";
        } else {
           fileName = fileName + File.separator;
        }
        File destFile = new File(fileName +
                                 "RPT_" + timestamp + "_" +
                                 this.getUsername() + "_" +
                                 this.getPrintername() + "_" +
                                 this.getFileName());
        JRTextExporter exporterTxt = new JRTextExporter(this.jasperReportsContext);
        exporterTxt.setExporterInput(new SimpleExporterInput(this.jasperPrint));
        exporterTxt.setExporterOutput(new SimpleWriterExporterOutput(destFile));
        try {
            exporterTxt.exportReport();
        } catch (JRException e) {
            e.printStackTrace();
        }
        return destFile;
    }
    private static boolean isWindows() {
        return (System.getProperty("os.name").indexOf("win") >= 0);
    }
    public void print() {
        File destFile = this.dumpFile();
        try {
            /*
             * Launch to printer
             */
            if (this.isWindows()) {
                Process p = Runtime.getRuntime().exec("lpt -d" + printername + " " + destFile.getAbsolutePath());
            } else {
/*
* iOS require a blank between "lp -d" and printer name
*/ Process p = Runtime.getRuntime().exec("lp -d" + printername + " " + destFile.getAbsolutePath()); } } catch (java.io.IOException e) { e.printStackTrace(); } } public String getPrintername() { return printername; } public void setPrintername(String printername) { if (printername == null) printername = ""; this.printername = printername; } public String getUsername() { return username; } public void setUsername(String username) { if (username == null) username = ""; this.username = username; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public JasperPrint getJasperPrint() { return jasperPrint; } public void setJasperPrint(JasperPrint jasperPrint) { this.jasperPrint = jasperPrint; } public JasperReportsContext getJasperReportsContext() { return jasperReportsContext; } public void setJasperReportsContext(JasperReportsContext jasperReportsContext) { this.jasperReportsContext = jasperReportsContext; } }

Prestate attenzione ai parametri printername e nome utente. L' Exporter si aspetta che gli venga passato, in URL o in forma di parametro (parametro del report). Il primo è il nome della stampante alla quale verrà inviato il report. Il secondo si riferisce a al nome utente che ha lanciato il report, e viene utilizzato per comporre il nome del file TXT - insieme con un timestamp, il nome della stampante e riportare nome - durante la fase di creazione del file su file-system. Questo file verrà creato nella directory temp di default Java (System.getProperty ( "java.io.tmpdir"), nei miei ambienti che corrisponda a {jasper_deploy_dir}/apache-tomcat/bin o {jasper_deploy_dir}/apache-tomcat/logs.

2 - Creare un nuovo Java bean per i parametri

Create un nuovo Java Bean, che estenda com.jaspersoft.jasperserver.api.engine.jasperreports.common.AbstractExportParameters class. Questa è la mia classe, chiamata PrintertxtExportParametersBean, nel package package com.jaspersoft.jasperserver.api.engine.jasperreports.common ({jasper_src_home}/jasperserver/jasperserver-api-impl/engine/src/main/java/com/jaspersoft/jasperserver/api/engine/jasperreports/common).

/*
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.api.engine.jasperreports.common;
import java.lang.String;
public class PrintertxtExportParametersBean extends AbstractExportParameters {
	public static final String PROPERTY_TEXT_PAGINATED = "com.jaspersoft.jrs.export.text.paginated";
	private Float   characterWidth;
	private Float   characterHeight;
	private Integer pageWidth;
	private Integer pageHeight;
	private String  printername;
	private String  username;
	public Object getObject(){
		return this;
	}
	public void setPropertyValues(Object object){
		if(object instanceof PrintertxtExportParametersBean){
			PrintertxtExportParametersBean bean =(PrintertxtExportParametersBean)object;
			this.setCharacterHeight(bean.getCharacterHeight());
			this.setCharacterWidth(bean.getCharacterWidth());
			this.setPageHeight(bean.getPageHeight());
			this.setPageWidth(bean.getPageWidth());
			this.setPrintername(bean.getPrintername());
			this.setUsername(bean.getUsername());
		}
	}
	/**
	 * @return Returns the characterWidth.
	 */
	public Float getCharacterWidth() {
		return characterWidth;
	}
	/**
	 * @param characterWidth The characterWidth to set.
	 */
	public void setCharacterWidth(Float characterWidth) {
		this.characterWidth = characterWidth;
	}
	/**
	 * @return Returns the characterHeight.
	 */
	public Float getCharacterHeight() {
		return characterHeight;
	}
	/**
	 * @param characterHeight The characterHeight to set.
	 */
	public void setCharacterHeight(Float characterHeight) {
		this.characterHeight = characterHeight;
	}
	/**
	 * @return Returns the pageWidth.
	 */
	public Integer getPageWidth() {
		return pageWidth;
	}
	/**
	 * @param pageWidth The pageWidth to set.
	 */
	public void setPageWidth(Integer pageWidth) {
		this.pageWidth = pageWidth;
	}
	/**
	 * @return Returns the pageHeight.
	 */
	public Integer getPageHeight() {
		return pageHeight;
	}
	/**
	 * @param pageHeight The pageHeight to set.
	 */
	public void setPageHeight(Integer pageHeight) {
		this.pageHeight = pageHeight;
	}
	/**
	 * @return Returns the printername.
	 */
	public String getPrintername() { return printername; }
	/**
	 * @param printername The printername to set.
	 */
	public void setPrintername(String printername) {
		this.printername = printername;
	}
	/**
	 * @return Returns the username.
	 */
	public String getUsername() { return username; }
	/**
	 * @param username The username to set.
	 */
	public void setUsername(String username) {
		this.username = username;
	}
}

3 - Aggiungere il nuovo canale all' elenco di quelli disponibili

Modifichiamo questo file: {jasper_src_home}/jasperserver/jasperserver-war/src/main/webapp/WEB-INF/flows/viewReportBeans.xml. La lista degli exporter è definita da exporterConfigMap alla fine del file. Aggiungete una nuova entry:


<util:map id="exporterConfigMap">
   ....
   <!-- Print direct -->
   <entry key="printertxt" value-ref="printertxtExporterConfiguration"/>

I valori sono oggetti com.jaspersoft.jasperserver.war.action.ExporterConfigurationBean, che definiscono le informazioni telati ogni singolo e xporter. Create un bean chiamato  printertxtExporterConfiguration con le seguenti proprietà. NB: Cercate txtExporterConfiguration e mettete i nuovi tag vicino.


<!-- Direct print -->
<bean id="printertxtExporterConfiguration" class="com.jaspersoft.jasperserver.war.action.ExporterConfigurationBean">
<property name="descriptionKey" value="jasper.report.view.hint.export.printertxt"/>
<property name="iconSrc" value="/images/text.png"/>
<property name="parameterDialogName" value="printertxtExportParams"/>
<property name="exportParameters" ref="printertxtExportParameters"/>
<property name="currentExporter" ref="reportPrintertxtExporter"/>
</bean>

Alla fine, aggiungete anche questa configurazione. Di nuovo, usate come guida il bean reportTextExporter che è molto simile:


<!-- Direct print -->
<bean id="reportPrintertxtExporter" 
class="com.jaspersoft.jasperserver.war.action.ReportPrintertxtExporter"
parent="baseReportExporter"> <property name="setResponseContentLength" value="true"/> </bean>

4 - Message bundles

Apri il file {jasper_src_home}/jasperserver/jasperserver-war/src/main/webapp/WEB-INF/bundles/jasperserver_messages.properties e aggiungi una nuova chiave (exporter name etooltip):

jasper.report.view.hint.export.printertxt=As TXT Direct print

5- Add additional export parameters

Apri il file {jasper_src_home}/jasperserver/common/shared-config/applicationContext.xml, e crea un beam di nome printertxtExportParameters come this:


<!-- Direct print -->
<bean id="printertxtExportParameters" 
class="com.jaspersoft.jasperserver.api.engine.jasperreports.common.PrintertxtExportParametersBean"> <property name="characterWidth" value="10"/> <property name="characterHeight" value="10"/> <property name="pageHeight" value="100"/> <property name="pageWidth" value="80"/> <property name="printername" value=""/> <property name="username" value=""/> </bean>

Riferitevi sempre al bean ExportParameters. Aprite applicationContext-report-scheduling.xml nella stessa cartella e aggiungete:


<bean id="jobPrintertxtExportParameters" parent="printertxtExportParameters">
<property name="printername" value=""/>
<property name="username" value=""/>
</bean>

6- Rebuild and deploy

Compilate il codice di jasper e mettete in produzione la web app, come descritto qui Working With Custom Java Classes. Il vostro exporter nuovo comparirà nella lista di quelli a vostra disposizione nel report viewer.

7 - Running example

Usate il cancale dal viewer o lanciate un URL simile http://jasperserver:8081/jasperserver/flow.html?_flowId=viewReportFlow&ParentFolderUri=...&reportUnit=...&output=printertxt&username=...&printername=...&j_username=jasperausername&j_password=jasperuserpassword

In entrambi i casi il report verrà esportato in TXT, scaricato e inviato alla stampante.

 

Jasper 5.6