Spring Boot 应用程序中的 BIRT

2024-02-03

我需要在现有的 Spring Boot Web 应用程序中创建报告功能(函数)。建议使用 BIRT,我可以将其与 Spring Boot Web 应用程序集成。

我找到了下面的文章,并且能够在 Spring Boot 启动项目中运行报告(使用http://start.spring.io/ http://start.spring.io/)。这篇文章相当老了,确实帮助我找到了一个可行的示例。https://spring.io/blog/2012/01/30/spring-framework-birt https://spring.io/blog/2012/01/30/spring-framework-birt。这篇文章基本上正是我想要的,但是在 Spring Boot Web 应用程序中。

我面临的挑战是使用 BIRT 查看器运行报告,它具有很好的附加功能。 (打印、Expoet 数据、PDF、分页等)

我找不到任何按照本文描述的方式使用 BIRT 的 Spring Boot 示例。

我的问题是:

  1. 是否有其他方法或其他方法可以在 Spring Boot Web 应用程序中执行报告? (显然不想通过从头开始创建类似 BIRT 的功能来重新发明轮子,或者如果可能的话,将报表引擎与 Web 应用程序分开运行)

  2. 今天是否有人在 Spring Boot Web 应用程序中使用 BIRT(与查看器)一起工作,并愿意分享或指导我实现此目的的最佳方法? (我试图让JSP页面与spring boot一起工作,但无法如此成功......更多的是缺乏经验)

有人能帮助我吗。

亲切的问候, 亨克


依赖关系,一个实例IReportEngine,目录是在 Spring Boot Web 应用程序中设置 BIRT 中最具挑战性的部分。 这个例子有一些错误处理并且依赖于环境变量用于指定重要目录的路径。

此设置的一个好处是它是一个用于构建和生成报告的独立 ReST API。它的一个附带好处是它根本不依赖于 JSP。

我在 Docker 容器中运行它。

最初计划使用某些界面来尝试其他报告框架,例如 Jasper 报告或其他框架。

这并不完全是您所要求的,但我认为在某些情况下它更好。您可以非常灵活地使用、配置和部署 BIRT 报表运行程序作为这样的应用程序。这不使用 Actian 提供的预打包 BIRT Viewer。

我会为报告制作一个数据容器,称为birt 报告运行程序数据然后将用于日志记录和报告的所有目录放在该容器上,然后您可以将其挂载到 BIRT 容器上。

主要成分

主文件(BirtReportRunnerApplication.java)

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BirtReportRunnerApplication {

    public static void main(String[] args) {
        SpringApplication.run(BirtReportRunnerApplication.class, args);
    }
}

接收报告请求的控制器(ReportController.java)

package com.example.core.web.controller;

import com.example.core.model.BIRTReport;
import com.example.core.service.ReportRunner;
import com.example.core.web.dto.ReportRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController("ReportController")
@RequestMapping("/reports")
public class ReportController {

    private Logger logger = LoggerFactory.getLogger(ReportController.class);

    @Autowired
    @Qualifier("birt")
    ReportRunner reportRunner;

    @RequestMapping(value = "/birt", method = RequestMethod.POST)
    public ResponseEntity<byte[]> getBIRTReport(@RequestBody ReportRequest reportRequest) {
        byte[] reportBytes;
        ResponseEntity<byte[]> responseEntity;
        try {
            logger.info("REPORT REQUEST NAME:   " + reportRequest.getReportName());
            reportBytes =
                new BIRTReport(
                    reportRequest.getReportName(),
                    reportRequest.getReportParameters(),
                    reportRunner)
                    .runReport().getReportContent().toByteArray();

            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.parseMediaType("application/pdf"));
            String fileName = reportRequest.getReportName() + ".pdf";
            httpHeaders.setContentDispositionFormData(fileName, fileName);
            httpHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
            responseEntity = new ResponseEntity<byte[]>(reportBytes, httpHeaders, HttpStatus.OK);
        } catch (Exception e) {
            responseEntity = new ResponseEntity<byte[]>(HttpStatus.NOT_IMPLEMENTED);
            return responseEntity;
        }
        return responseEntity;
    }
}

用于指定要运行的报告的报告请求 DTO (ReportRequest.java)

package com.example.core.web.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

public class ReportRequest {
    private String reportName;
    private String reportParameters;

    public ReportRequest(@JsonProperty("reportName") String reportName,
                         @JsonProperty("reportParameters") String reportParameters) {
        this.reportName = reportName;
        this.reportParameters = reportParameters;
    }

    public String getReportName() {
        return reportName;
    }

    public String getReportParameters() {
        return reportParameters;
    }

    public void setReportParameters(String reportParameters) {
        this.reportParameters = reportParameters;
    }
}

报表运行器的接口 (ReportRunner.java)

package com.example.core.service;

import com.example.core.model.Report;

import java.io.ByteArrayOutputStream;

public interface ReportRunner {

    ByteArrayOutputStream runReport(Report report);
}

完成大部分工作的最大类 (BIRTReportRunner.java)

package com.example.core.service;

import com.example.core.model.Report;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.*;
import org.eclipse.core.internal.registry.RegistryProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

@Service
@Qualifier("birt")
public class BIRTReportRunner implements ReportRunner {
    private static final String DEFAULT_LOGGING_DIRECTORY = "defaultBirtLoggingDirectory/";
    private Logger logger = LoggerFactory.getLogger(BIRTReportRunner.class);

    private static String reportOutputDirectory;

    private IReportEngine birtReportEngine = null;

    @Autowired
    private Environment env;

    /**
     * Starts up and configures the BIRT Report Engine
     */
    @PostConstruct
    public void startUp() {
        if(env.getProperty("birt_report_input_dir") == null)
            throw new RuntimeException("Cannot start application since birt report input directory was not specified.");
        try {
            String birtLoggingDirectory = env.getProperty("birt_logging_directory") == null ? DEFAULT_LOGGING_DIRECTORY : env.getProperty("birt_logging_directory");
            Level birtLoggingLevel = env.getProperty("birt_logging_level") == null ? Level.SEVERE : Level.parse(env.getProperty("birt_logging_level"));
            EngineConfig engineConfig = new EngineConfig();
            logger.info("BIRT LOG DIRECTORY SET TO : {}", birtLoggingDirectory);
            logger.info("BIRT LOGGING LEVEL SET TO {}", birtLoggingLevel);
            engineConfig.setLogConfig(birtLoggingDirectory, birtLoggingLevel);

            // Required due to a bug in BIRT that occurs in calling Startup after the Platform has already been started up
            RegistryProviderFactory.releaseDefault();
            Platform.startup(engineConfig);
            IReportEngineFactory reportEngineFactory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
            birtReportEngine = reportEngineFactory.createReportEngine(engineConfig);
        } catch (BirtException e) {
            // TODO add logging aspect and find out how to log a platform startup problem from this catch block, if possible, using the aspect.
            // Possibly rethrow the exception here and catch it in the aspect.
            logger.error("Birt Startup Error: {}", e.getMessage());
        }

        reportOutputDirectory = env.getProperty("birt_temp_file_output_dir");
    }

    /**
     * Shuts down the BIRT Report Engine
     */
    @PreDestroy
    public void shutdown() {
        birtReportEngine.destroy();
        RegistryProviderFactory.releaseDefault();
        Platform.shutdown();
    }

    public File getReportFromFilesystem(String reportName) throws RuntimeException {
        String reportDirectory = env.getProperty("birt_report_input_dir");
        Path birtReport = Paths.get(reportDirectory + File.separator + reportName + ".rptdesign");
        if(!Files.isReadable(birtReport))
            throw new RuntimeException("Report " + reportName + " either did not exist or was not writable.");

        return birtReport.toFile();
    }

    /**
     * This method creates and executes the report task, the main responsibility
     * of the entire Report Service.
     * This method is key to enabling pagination for the BIRT report. The IRunTask run task
     * is created and then used to generate an ".rptdocument" binary file.
     * This binary file is then read by the separately created IRenderTask render
     * task. The render task renders the binary document as a binary PDF output
     * stream which is then returned from the method.
     * <p>
     *
     * @param birtReport the report object created at the controller to hold the data of the report request.
     * @return Returns a ByteArrayOutputStream of the PDF bytes generated by the
     */
    @Override
    public ByteArrayOutputStream runReport(Report birtReport) {

        ByteArrayOutputStream byteArrayOutputStream;
        File rptDesignFile;

        // get the path to the report design file
        try {
            rptDesignFile = getReportFromFilesystem(birtReport.getName());
        } catch (Exception e) {
            logger.error("Error while loading rptdesign: {}.", e.getMessage());
            throw new RuntimeException("Could not find report");
        }

        // process any additional parameters
        Map<String, String> parsedParameters = parseParametersAsMap(birtReport.getParameters());

        byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            IReportRunnable reportDesign = birtReportEngine.openReportDesign(rptDesignFile.getPath());
            IRunTask runTask = birtReportEngine.createRunTask(reportDesign);

            if (parsedParameters.size() > 0) {
                for (Map.Entry<String, String> entry : parsedParameters.entrySet()) {
                    runTask.setParameterValue(entry.getKey(), entry.getValue());
                }
            }
            runTask.validateParameters();

            String rptdocument = reportOutputDirectory + File.separator
                    + "generated" + File.separator
                    + birtReport.getName() + ".rptdocument";
            runTask.run(rptdocument);

            IReportDocument reportDocument = birtReportEngine.openReportDocument(rptdocument);
            IRenderTask renderTask = birtReportEngine.createRenderTask(reportDocument);

            PDFRenderOption pdfRenderOption = new PDFRenderOption();
            pdfRenderOption.setOption(IPDFRenderOption.REPAGINATE_FOR_PDF, new Boolean(true));
            pdfRenderOption.setOutputFormat("pdf");
            pdfRenderOption.setOutputStream(byteArrayOutputStream);
            renderTask.setRenderOption(pdfRenderOption);

            renderTask.render();
            renderTask.close();
        } catch (EngineException e) {
            logger.error("Error while running report task: {}.", e.getMessage());
            // TODO add custom message to thrown exception
            throw new RuntimeException();
        }

        return byteArrayOutputStream;
    }

    /**
     * Takes a String of parameters started by '?', delimited by '&', and with
     * keys and values split by '=' and returnes a Map of the keys and values
     * in the String.
     *
     * @param reportParameters a String from a HTTP request URL
     * @return a map of parameters with Key,Value entries as strings
     */
    public Map<String, String> parseParametersAsMap(String reportParameters) {
        Map<String, String> parsedParameters = new HashMap<String, String>();
        String[] paramArray;
        if (reportParameters.isEmpty()) {
            throw new IllegalArgumentException("Report parameters cannot be empty");
        } else if (!reportParameters.startsWith("?") && !reportParameters.contains("?")) {
            throw new IllegalArgumentException("Report parameters must start with a question mark '?'!");
        } else {
            String noQuestionMark = reportParameters.substring(1, reportParameters.length());
            paramArray = noQuestionMark.split("&");
            for (String param : paramArray) {
                String[] paramGroup = param.split("=");
                if (paramGroup.length == 2) {
                    parsedParameters.put(paramGroup[0], paramGroup[1]);
                } else {
                    parsedParameters.put(paramGroup[0], "");
                }

            }
        }
        return parsedParameters;
    }
}

报表对象类(Report.java)

package com.example.core.model;

import com.example.core.service.ReportRunner;

import java.io.ByteArrayOutputStream;
import java.util.List;

/**
 * A Report object has a byte representation of the report output that can be
 * used to write to any output stream. This class is designed around the concept
 * of using ByteArrayOutputStreams to write PDFs to an output stream.
 *
 *
 */
public abstract class Report {

    protected String name;
    protected String parameters;
    protected ByteArrayOutputStream reportContent;
    protected ReportRunner reportRunner;

    public Report(String name, String parameters, ReportRunner reportRunner) {
        this.name = name;
        this.parameters = parameters;
        this.reportRunner = reportRunner;
    }

    /**
     * This is the processing method for a Report. Once the report is ran it
     * populates an internal field with a ByteArrayOutputStream of the
     * report content generated during the run process.
     * @return Returns itself with the report content output stream created.
     */
    public abstract Report runReport();

    public ByteArrayOutputStream getReportContent() {
        return this.reportContent;
    }

    public String getName() {
        return name;
    }

    public String getParameters() {
        return parameters;
    }
}

BIRTReport 对象类 (BIRTReport.java)

package com.example.core.model;

import com.example.core.service.ReportRunner;

public class BIRTReport extends Report {

    public BIRTReport(String name, String reportParameters, ReportRunner reportRunner) {
        super(name, reportParameters, reportRunner);
    }

    @Override
    public Report runReport() {
        this.reportContent = reportRunner.runReport(this);
        return this;
    }
}

构建文件(build.gradle)

buildscript {
    ext {
        springBootVersion = '1.3.2.RELEASE'
    }
    repositories {
        jcenter()

    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'com.example.simple-birt-runner'
    version = '1.0.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

ext {
    springBootVersion = '1.3.0.M5'
}

repositories {
    jcenter()
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")


    // BIRT Runtime and ReportEngine dependencies
    // These were pulled from the Actuate download site at http://download.eclipse.org/birt/downloads/ for version 4.5.0
    compile fileTree(dir: 'lib', include: '*.jar')
    /*compile("org.eclipse.birt.runtime:org.eclipse.birt.runtime:4.4.2") {
        exclude group: "org.eclipse.birt.runtime", module: "org.apache.poi"
        exclude group: "org.eclipse.birt.runtime", module: "org.eclipse.orbit.mongodb"
    }*/

    compile("org.springframework.boot:spring-boot-starter-tomcat")

    // include any runtime JDBC driver dependencies here

    testCompile("org.springframework.boot:spring-boot-starter-test")
}

依赖关系

获取 Birt Viewer lib 目录中的所有依赖项并将它们放在类路径中。以下是外部依赖项的完整列表:

com.ibm.icu_54.1.1.v201501272100.jar
com.lowagie.text_2.1.7.v201004222200.jar
derby.jar
flute.jar
javax.wsdl_1.5.1.v201012040544.jar
javax.xml.stream_1.0.1.v201004272200.jar
javax.xml_1.3.4.v201005080400.jar
net.sourceforge.lpg.lpgjavaruntime_1.1.0.v201004271650.jar
org.apache.batik.bridge_1.6.0.v201011041432.jar
org.apache.batik.css_1.6.0.v201011041432.jar
org.apache.batik.dom.svg_1.6.0.v201011041432.jar
org.apache.batik.dom_1.6.1.v201505192100.jar
org.apache.batik.ext.awt_1.6.0.v201011041432.jar
org.apache.batik.parser_1.6.0.v201011041432.jar
org.apache.batik.pdf_1.6.0.v201105071520.jar
org.apache.batik.svggen_1.6.0.v201011041432.jar
org.apache.batik.transcoder_1.6.0.v201011041432.jar
org.apache.batik.util.gui_1.6.0.v201011041432.jar
org.apache.batik.util_1.6.0.v201011041432.jar
org.apache.batik.xml_1.6.0.v201011041432.jar
org.apache.commons.codec_1.6.0.v201305230611.jar
org.apache.commons.logging_1.1.1.v201101211721.jar
org.apache.lucene.core_3.5.0.v20120725-1805.jar
org.apache.poi_3.9.0.v201405241750.jar
org.apache.xerces_2.9.0.v201101211617.jar
org.apache.xml.resolver_1.2.0.v201005080400.jar
org.apache.xml.serializer_2.7.1.v201005080400.jar
org.eclipse.birt.runtime_4.5.0.jar
org.eclipse.core.contenttype_3.5.0.v20150421-2214.jar
org.eclipse.core.expressions_3.5.0.v20150421-2214.jar
org.eclipse.core.filesystem_1.5.0.v20150421-0713.jar
org.eclipse.core.jobs_3.7.0.v20150330-2103.jar
org.eclipse.core.resources_3.10.0.v20150423-0755.jar
org.eclipse.core.runtime.compatibility_3.2.300.v20150423-0821.jar
org.eclipse.core.runtime_3.11.0.v20150405-1723.jar
org.eclipse.datatools.connectivity.apache.derby.dbdefinition_1.0.2.v201107221459.jar
org.eclipse.datatools.connectivity.apache.derby_1.0.103.v201212070447.jar
org.eclipse.datatools.connectivity.console.profile_1.0.10.v201109250955.jar
org.eclipse.datatools.connectivity.db.generic_1.0.1.v201107221459.jar
org.eclipse.datatools.connectivity.dbdefinition.genericJDBC_1.0.2.v201310181001.jar
org.eclipse.datatools.connectivity.oda.consumer_3.2.6.v201403131814.jar
org.eclipse.datatools.connectivity.oda.design_3.3.6.v201403131814.jar
org.eclipse.datatools.connectivity.oda.flatfile_3.1.8.v201403010906.jar
org.eclipse.datatools.connectivity.oda.profile_3.2.9.v201403131814.jar
org.eclipse.datatools.connectivity.oda_3.4.3.v201405301249.jar
org.eclipse.datatools.connectivity.sqm.core_1.2.8.v201401230755.jar
org.eclipse.datatools.connectivity_1.2.11.v201401230755.jar
org.eclipse.datatools.enablement.hsqldb.dbdefinition_1.0.0.v201107221502.jar
org.eclipse.datatools.enablement.hsqldb_1.0.0.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.iseries.dbdefinition_1.0.3.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.iseries_1.0.2.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.luw.dbdefinition_1.0.7.v201405302027.jar
org.eclipse.datatools.enablement.ibm.db2.luw_1.0.3.v201401170830.jar
org.eclipse.datatools.enablement.ibm.db2.zseries.dbdefinition_1.0.4.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.zseries_1.0.2.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2_1.0.0.v201401170830.jar
org.eclipse.datatools.enablement.ibm.informix.dbdefinition_1.0.4.v201107221502.jar
org.eclipse.datatools.enablement.ibm.informix_1.0.1.v201107221502.jar
org.eclipse.datatools.enablement.ibm_1.0.0.v201401170830.jar
org.eclipse.datatools.enablement.msft.sqlserver.dbdefinition_1.0.1.v201201240505.jar
org.eclipse.datatools.enablement.msft.sqlserver_1.0.3.v201308161009.jar
org.eclipse.datatools.enablement.mysql.dbdefinition_1.0.4.v201109022331.jar
org.eclipse.datatools.enablement.mysql_1.0.4.v201212120617.jar
org.eclipse.datatools.enablement.oda.ws_1.2.6.v201403131825.jar
org.eclipse.datatools.enablement.oda.xml_1.2.5.v201403131825.jar
org.eclipse.datatools.enablement.oracle.dbdefinition_1.0.103.v201206010214.jar
org.eclipse.datatools.enablement.oracle_1.0.0.v201107221506.jar
org.eclipse.datatools.enablement.postgresql.dbdefinition_1.0.2.v201110070445.jar
org.eclipse.datatools.enablement.postgresql_1.1.1.v201205252207.jar
org.eclipse.datatools.enablement.sap.maxdb.dbdefinition_1.0.0.v201107221507.jar
org.eclipse.datatools.enablement.sap.maxdb_1.0.0.v201107221507.jar
org.eclipse.datatools.modelbase.dbdefinition_1.0.2.v201107221519.jar
org.eclipse.datatools.modelbase.derby_1.0.0.v201107221519.jar
org.eclipse.datatools.modelbase.sql.query_1.1.4.v201212120619.jar
org.eclipse.datatools.modelbase.sql_1.0.6.v201208230744.jar
org.eclipse.datatools.sqltools.data.core_1.2.3.v201212120623.jar
org.eclipse.datatools.sqltools.parsers.sql.lexer_1.0.1.v201107221520.jar
org.eclipse.datatools.sqltools.parsers.sql.query_1.2.1.v201201250511.jar
org.eclipse.datatools.sqltools.parsers.sql_1.0.2.v201107221520.jar
org.eclipse.datatools.sqltools.result_1.1.6.v201402080246.jar
org.eclipse.emf.common_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore.change_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore.xmi_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore_2.11.0.v20150512-0501.jar
org.eclipse.equinox.app_1.3.300.v20150423-1356.jar
org.eclipse.equinox.common_3.7.0.v20150402-1709.jar
org.eclipse.equinox.preferences_3.5.300.v20150408-1437.jar
org.eclipse.equinox.registry_3.6.0.v20150318-1503.jar
org.eclipse.help_3.6.0.v20130326-1254.jar
org.eclipse.osgi.services_3.5.0.v20150519-2006.jar
org.eclipse.osgi_3.10.100.v20150529-1857.jar
org.eclipse.update.configurator_3.3.300.v20140518-1928.jar
org.mozilla.javascript_1.7.5.v201504281450.jar
org.w3c.css.sac_1.3.1.v200903091627.jar
org.w3c.dom.events_3.0.0.draft20060413_v201105210656.jar
org.w3c.dom.smil_1.0.1.v200903091627.jar
org.w3c.dom.svg_1.1.0.v201011041433.jar

应用程序属性(application.yml)

birt:
  report:
    output:
      dir: ${birt_temp_file_output_dir}
    input:
      dir: ${birt_report_input_dir}
  logging:
    level: ${birt_logging_level}


server:
  port: 8080
  context-path: /simple-birt-runner


birt:
  logging:
    level: SEVERE

logging:
  level:
    org:
      springframework:
        web: ERROR

用于运行的Dockerfile(Dockerfile)

FROM java:openjdk-8u66-jre
MAINTAINER Kent O. Johnson <[email protected] /cdn-cgi/l/email-protection>

COPY com.example.simple-birt-runner-*.jar /opt/soft/simple-birt-runner.jar

RUN mkdir -p /reports/input \
    && mkdir /reports/output \
    && mkdir -p /reports/log/engine

WORKDIR /opt/soft

CMD java -jar -Xms128M -Xmx4G simple-birt-runner.jar

EXPOSE 8080

用于运行映像的 Docker 撰写文件 (docker-compose.yml)

simple-birt-runner:
  image: soft/simple-birt-runner-release
  ports:
  - "8090:8080"
  environment:
  - birt_temp_file_output_dir=/reports/output
  - birt_report_input_dir=/reports/input
  - birt_logging_directory=/reports/log/engine
  - birt_logging_level=SEVERE
  volumes_from:
  - birt-report-runner-data
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot 应用程序中的 BIRT 的相关文章

  • createImage(int width, int height) 的问题

    我有以下代码 作为游戏的一部分每 10 毫秒运行一次 private void gameRender if dbImage null createImage returns null if GraphicsEnvironment isHea
  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何根据运行的 jar 的结果让我的 ant 任务通过或失败?

    我正在运行 CrossCheck 无浏览器 js 单元测试 作为 ant 脚本的一部分 如果 CrossCheck 测试失败 我希望 ant 报告失败 这是 build xml 中的相关部分
  • 来自十六进制代码的 Apache POI XSSFColor

    我想将单元格的前景色设置为十六进制代码中的给定颜色 例如 当我尝试将其设置为红色时 style setFillForegroundColor new XSSFColor Color decode FF0000 getIndexed 无论我在
  • Jackson XML ArrayList 输出具有两个包装器元素

    我在 Jackson 生成的 XML 输出中得到了两个包装器元素 我只想拥有一个 我有一个 Java bean Entity Table name CITIES JacksonXmlRootElement localName City pu
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • Java Swing For mac 中的 DJ Native Swing 浏览器

    我有一个用 Swing 制作的 Java 应用程序 并且使用了一个 DJ Native Swing 浏览器 当我尝试在 OS X 上使用它时 它抛出了一个NoClassDefFoundError尽管我添加了 swt jar 但始终如此 有人
  • 内部存储的安全性如何?

    我需要的 对于 Android 我需要永久保存数据 但也能够编辑 并且显然是读取 它 用户不应访问此数据 它可以包含诸如高分之类的内容 用户不得对其进行编辑 我的问题 我会 并且已经 使用过Internal Storage 但我不确定它实际
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • “无法实例化活动”错误

    我的一个 Android 应用程序拥有大约 100 000 个用户 每周大约 10 次 我会通过 Google 的市场工具向我报告以下异常情况 java lang RuntimeException Unable to instantiate
  • Hamcrest Matchers - 断言列表类型

    问题 我目前正在尝试使用 Hamcrest Matchers 来断言返回的列表类型是特定类型 例如 假设我的服务调用返回以下列表 List
  • Android:无法发送http post

    我一直在绞尽脑汁试图弄清楚如何在 Android 中发送 post 方法 这就是我的代码的样子 public class HomeActivity extends Activity implements OnClickListener pr
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • 在浏览器刷新中刷新检票面板

    我正在开发一个付费角色系统 一旦用户刷新浏览器 我就需要刷新该页面中可用的统计信息 统计信息应该从数据库中获取并显示 但现在它不能正常工作 因为在页面刷新中 java代码不会被调用 而是使用以前的数据加载缓存的页面 我尝试添加以下代码来修复

随机推荐

  • 如何在Flutter中获取当前时区区域(tz数据库名称)

    我是 flutter 新手 我的其余 api 将当前时区设置为欧洲 伦敦 我不知道如何在颤振中获取当前时区 stackoverflow 上有一个关于这个主题的问题 但没有用户给出答案 Flutter 时区 作为 ZoneId https s
  • Foundation 5 网格推拉

    我正在使用 Foundation 5 并尝试在移动屏幕上实现以下 DIV 布局 A B C D E 我希望在桌面屏幕上显示如下
  • 使用 AndroidPlot 自定义图表上的点

    任何使用过 AndroidPlot 库的人都会告诉我如何在图表上绘制自定义点 到目前为止 我正在使用 LineAndPointRenderer 类并将线条设置为透明 我想至少改变点的大小 但如果可能的话有一个自定义图像 P S 拥有 150
  • JavaScript - 测试整数

    我有一个文本字段 允许用户输入他们的年龄 我正在尝试使用 JavaScript 对此字段进行一些客户端验证 我已经有了服务器端验证 但是 我似乎无法验证用户是否输入了实际的整数 我目前正在尝试以下代码 function IsValidAge
  • 编辑单元格时刷新行

    我对这个 JTable 有问题 我像这样编辑一个单元格 然后我按 Enter 键提交更改 在这里 我希望表 GUI 能够刷新新值 但它们没有显示 只有当我像这样更改选择时才会显示 fireTableCellUpdated inRow inC
  • 用于运行任务名称中包含连字符的 Ant 任务的命令行

    任务名称以连字符 开头
  • 如何在同一个按钮上使用反应路由器和反应滚动?

    我想在同一个导航链接上使用反应路由器和反应滚动 如果我在主页上 我希望按钮具有反应滚动行为 如果我在不同的页面上 按钮需要返回主页 然后滚动到首选组件 反应滚动行为 这是我的想法 但它不能正常工作 import Link from reac
  • 使用 kubernetes nginx-ingress 反向代理具有 SNI 支持的站点

    我正在使用 kubernetes nginx ingress 设置反向代理 但我不知道如何将 nginx 参数添加到配置中 具体来说 proxy ssl 服务器名称 http nginx org en docs http ngx http
  • 如何在其他代码行同时执行的同时播放声音?

    我希望我的代码能够执行此操作 但要在后台播放音乐 import time while True print ligma time sleep 1 5 我试过这个 import time import winsound while True
  • 为什么我的数组加载后会清空?

    我一定错过了一些基本的东西 但我似乎无法保持我的数组加载 它加载成功 但当它出现在另一个函数中时 它变成空的 我的目标是从位置数组中随机选择一个城市 地图视图加载了我的所有注释 但是当我在注释出现后调用 pickRandomNumber 时
  • 无法连接到 Poloniex

    我正在尝试连接到 Poloniex 为了进行连接 我使用 WynthShop 和以下代码 public class Program public static void Main string args var channelFactory
  • Oracle Database12c ORA 01918 和连接错误

    我已经安装了 Oracle 12c 但在创建和使用第一个数据库时遇到问题 我运行 SQL Developer 并使用 hr 用户 但它一直告诉我该帐户已锁定 我搜索了 stackoverflow 答案和官方文档 并尝试使用以下方法解锁它 A
  • WPF ShowDialog 在第二次调用时立即返回 null

    我认为这是 WPF 框架中的一个错误 没有深入了解我的程序以及为什么我要做我正在做的事情 我编写了一个简单的测试应用程序来证明我的理论 这个问题能否得到证实 在将应用程序放入其运行循环之前执行一系列对话框有哪些可能的解决方法 using S
  • 如何在 Modelica 中构建液体平衡连接器?

    帖子状态 200313 得到了代码 DEMO v42 的答案 我接受了赏金 200310 我评论了昨天建议的两篇关键论文 还是不明白如何更新DEMO v41 200309 我想强调的是 关键问题是如何在代码DEMO v41 如果可能的话 中
  • CodeIgniter框架中的库和模型有什么区别?

    我是 CI 新手 之前我曾在 RoR 和 Symfony 中广泛工作过 我无法理解为什么 CI 提供了库和模型 我检查的大多数 CI 代码通常使用库作为模型的包装器 模型专门用于与数据库对话 有人可以阐明这一点吗 对此可能还有其他的思想流派
  • Django:精确查找的 QuerySet 值必须使用切片限制为一个结果

    我正在开发一个项目 管理员可以将团队分配给经理 但它不起作用 我不知道它将如何工作 因为它会引发一个错误 指出 精确查找的 QuerySet 值必须使用切片限制为一个结果 这是我的 model py class manager models
  • 如何在WPF中制作UIElement的屏幕截图

    我在创建 scatterview 的屏幕截图时遇到问题 我的屏幕截图总是包含黑框 这是我的 XAML 代码
  • 在 Azure Active Directory 上启用 CORS

    我尝试在 Angular 6 应用程序中使用以下方法以编程方式从 Azure Active Directory 获取访问令牌 let body1 new FormData body1 append resource environment
  • NSButton 的弹出菜单实现

    我该怎么办 我在想 NSMenu popUpContextMenu menu withEvent event forView NSButton sender Yup 按钮动作调用 NSMenu popUpContextMenu menu w
  • Spring Boot 应用程序中的 BIRT

    我需要在现有的 Spring Boot Web 应用程序中创建报告功能 函数 建议使用 BIRT 我可以将其与 Spring Boot Web 应用程序集成 我找到了下面的文章 并且能够在 Spring Boot 启动项目中运行报告 使用h