Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:oracle_apex_jasper_reports

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
prog:oracle_apex_jasper_reports [2016/07/07 09:59]
gpipperr [Quellen]
prog:oracle_apex_jasper_reports [2016/07/11 22:30] (aktuell)
gpipperr [Quellen]
Zeile 1: Zeile 1:
 +=====Oracle APEX 5 und Jasper Reports 6 zusammen installieren und nützen=====
  
 +Aus HTML Anwendungen ist das Drucken meist eine Herausforderung, hier ist leider auch APEX keine Ausnahme.
 +
 +Eine Möglichkeit ist das Erstellen eines Berichts als PDF, der dann ausgedruckt werden kann.
 +
 +Ein hervorragendes, leider aber auch ein etwas arg kostenpflichtiges, Tool ist das zu der Oracle BI Publisher => [[:oracle_bi_publisher#oracle_bi_publisher|Reporting mit der Oracle Datenbank]].
 +
 +Steht dieser nicht zur Verfügung ist es eine Alternative ein Open Source Produkt wie [[http://community.jaspersoft.com/|Jasper Report]] einzusetzen. 
 +
 +Eine sehr gute Anleitung + Software dazu bzgl. einer tiefen Apex Integration findet sich hier => http://www.opal-consulting.de/apex/f?p=20090928:7:0::NO:7::
 +
 +Im ersten Schritt versuche ich das aber mal mit dem derzeitigen APEX 5 und PL/SQL in der 12c Board Mitteln zu lösen.
 +
 +
 +----
 +
 +==== Aufsetzen einer Jasper Reports Umgebung====
 +
 +Voraussetzung:
 +
 +Eine Umgebung mit Tomcat und den ORDS für Oracle Apex ist bereits installiert, siehe  => [[prog:oracle_rest_data_service_tomcat|Oracle ORDS 3.0 (Oracle REST Data Services) mit dem Apache http und Tomcat unter Windows 2012 betreiben - SSL verwenden]] und eine Oracle Datenbank steht zur Verfügung.
 +
 +Leider lässt sich adhoc das Repository von Jasper NICHT in der Oracle Datenbank anlegen.
 +
 +
 +Auf diese existierenden Umgebung wird nun eine Community Jasper Report 6.2 Applikation aufgesetzt.
 +
 +
 +Download der Software über http://community.jaspersoft.com/download
 +
 +  * JasperReports® Server   => jasperreports-server-cp-6.2.1-bin.zip und jasperreports-server-cp-6.2.1-windows-x64-installer
 +  * JasperReports  Library  => jasperreports-6.2.2.jar
 +  * Jaspersoft® Studio      => TIBCOJaspersoftStudio-6.2.2.final-windows-x86_64.zip
 +
 +Dazu ist einen Community Mitgliedschaft notwendig.
 +
 +==== Standalone Jasper Umgebung====
 +
 +Ziel ist es das alles unter Oracle läuft, leider wird das aber nativ nicht unterstütz .
 +
 +Daher im ersten Schritt auf einer Testmaschine über den Windows Installer "jasperreports-server-cp-6.2.1-windows-x64-installer.exe" eine erste Version des Report Servers mit einer Postgresql  DB als Repository aufgesetzt.
 +
 +  * Exe starten next  - next 
 +  * Lizenzbedingungen akzeptieren  - next 
 +  * Custom install auswählen - next 
 +  * Programm Verzeichnis auswählen wie d:\srv\jasper6
 +  * "I want to use an existing Tomcat" auswählen   - next 
 +  * "I want to use the bundled PostgreSQL database" auswählen - next 
 +  * Tomcat Server Port angeben,in unsere Fall 8081 - next
 +    * Wenn Tomcat noch läuft diesen erst stoppen? hilft nicht daher jetzt oben 8081 angeben Bug? 
 +    * Port muss unterschiedlich sein, ist aber ein Bug im Installer!
 +  * Database Server Port angeben 5432 - next
 +  * Tomcat Verzeichnis auswählen - in unseren Fall D:\srv\apache-tomcat-8.0.33 - next
 +  * Samples mit installieren - Next
 +  * Installation starten mit Next
 +  * Installation läuft ca. 5min
 +  * Finish
 +
 +Nun den Tomcat wieder starten, Jasper wird deployed, leider klappt es aber gar nicht ....
 +
 +Jetzt heißt es den Fehler suchen....
 +
 +<code>
 +09-Jun-2016 22:25:10.943 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
 + org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'themeSource' defined in ServletContext resource [/WEB-INF/applicationContext-themes.xml]: Cannot resolve reference to bean 'themeCache' while setting bean property 'themeCache'; 
 +</code>
 +
 +=>> postgresql war nicht gestartet!  Starten mit "D:\srv\jasper6\postgresql\scripts\servicerun.bat START", falls das nicht funktioniert prüfen ob der Dienst installiert ist, fehlt dieser mit "serviceinstall.bat INSTALL" installieren!
 +
 +Siehe dazu auch zur Installation => http://community.jaspersoft.com/wiki/installation-steps-installer-distribution
 +
 +
 +Das wir in unserer Umgebung den [[prog:oracle_rest_data_service_tomcat|Apache http Server mit mod_jk]] einsetzen ( und das ganze über SSL sichern), die entsprechenden Anweisung in die Conf Files einbauen, damit der Jasper Report aufgerufen werden kann.
 +
 +apex.conf:
 +<code apache>
 +..
 +JKMount /jasperserver/* worker1
 +..
 +</code>
 +
 +
 +
 +
 +
 +=== Login in den Jasper Report Server ===
 +
 +Login mit dem User jasperadmin / pwd jasperadmin , diese SOFORT anpassen!
 +
 +Local Test mit <nowiki>http://localhost:8080/jasperserver/login.html</nowiki> 
 +Produktiv aufrufen mit <nowiki>https://<myapex_server>/jasperserver/login.html</nowiki> 
 +
 +Nun noch eine Datasource für die Oracle Datenbank anlegen, unter "Data Source" "Add Resource" "Data Source"
 +
 +Als erstes über "Select Driver" den Oracle JDBC Treiber hochladen und dann die Connection zur DB konfigurieren.
 +
 +
 +=== Repository nach Oracle verschieben ===
 +
 +Aus den Sourcen lässt sich das SQL für das Repository ermitteln, evtl. lässt sich daraus eine Oracle Version "basteln".
 +
 +Dazu die Datei "jasperreports-server-cp-6.2.1-bin.zip" auf den Server kopieren und dort zum Beispiel nach "d:\install\jasper" und dort entpacken. Unter "buildomatic\install_resources\sql" finden sich die SQL Scripte für MySQL.
 +
 +Diese müssen nun auf die Oracle Syntax angepasst werden. 
 +
 +Alles wird nun in der Oracle gleich wie in der Postgresql  eingerichtet und dann wird die DB Connection umgezogen.
 +
 +Mal sehen ob das so einfach dann klappt.
 +
 +demnächst mehr
 +
 +
 +----
 +
 +==== Report Designer starten====
 +
 +Die Datei "TIBCOJaspersoftStudio-6.2.2.final-windows-x86_64.zip" entpacken und Ordner "jaspersoftstudio" in ein Verzeichnis wie "D:\tools" verschieben.
 +
 +
 +Über "Jaspersoft Studio.exe" kann nun das angepasste Eclipse gestartet werden.
 +
 +Als erstes wird ein Data Adapter benötigt, dazu muss aber zuvor der Pfad zu den JDBC Jars von Oracle definiert werden.
 +
 +  * {{ :prod:jasper:jasperstudio_oracle_v01.png?300 | Pfad zur JDBC Lib festlegen}}
 +  * {{ :prod:jasper:jasperstudio_oracle_v02.png?300 | Verbindung einrichten}}
 +
 +
 +Nun kann über "File" und der Auswahl eines Templates gleich der erste Bericht erzeugt werden, dabei darauf achten das der zuvor angelegte DataAdapter auch ausgewählt wird.
 +
 +Nach dem ersten Report diesen auf den Server hochladen, dazu im Studio eine Server Verbindung anlegen und dort den Bericht hochladen.
 +
 +----
 +
 +===== Integration in Apex =====
 +
 +Die einfachste Integration ist das Weiterleiten der URL an den Report Server von Jasper.
 +
 +Allerdings ist dann das Ganze nicht direkt integriert, mit den Benutzerrechten und dem Passwort dazu ist das nicht so einfach.
 +
 +Besser ist eine tiefe Integration und der Aufruf des Berichts über die [[http://community.jaspersoft.com/documentation/tibco-jasperreports-server-rest-api-reference/v621/rest-api-overview|REST Schnittstelle zum Jasper Server]].
 +
 +Dies kann nun per JavaScript in der Oberfläche erfolgen oder per UTL_HTTP über PL/SQL in der Datenbank.
 +
 +
 +Als erstes mit einem Rest Tool wie http://www.wiztools.org/ testen, wie die Rest Api von Jasper so funktioniert.  Dazu
 +restclient-ui-3.5-jar-with-dependencies.jar herunterladen und testen.
 +
 +
 +=== JavaScript ===
 +=> <fc #800000>"Visualize.js currently does not support JasperReports Server Community Edition"</fc>
 +==Visualize.js==
 +
 +  * http://community.jaspersoft.com/wiki/visualizejs-getting-started
 +  * http://community.jaspersoft.com/wiki/visualizejs-tutorials
 +
 +
 +
 +==== APEX - PL/SQL ====
 +
 +Die Integration in Apex erfolgt dadruch, das im Backend, d.h. in der Datenbank ein REST Call an den Jasper Server versandt wird, dies Call liefert den Bericht im gewünschten Format zurück, Diese Bericht wird dann in einer BLOB Variable gespeichert, der Inhalt dieser Variable wird dann an den Browser gestreamt.
 +
 +
 +{{ :prod:jasper:jasper_apex_reporting_integratoin_v01.png |APEX Jasper Integration}}
 +
 +
 +
 +===APEX_WEB_SERVICE verwenden===
 +
 +siehe https://docs.oracle.com/cloud/latest/db121/AEAPI/apex_web_service.htm#AEAPI537
 + 
 +Mit Hilfe von "apex_web_service.make_rest_request" wird die API von Jasper Reports angesprochen.
 +
 +
 +Zuvor eine ACL hinterlegen, das wir überhaupt aus der DB auf den Report Server zugreifen dürfen.
 +
 +ACL:
 +<code sql>
 +   DECLARE
 +      v_apex_server VARCHAR2(256):= '10.10.10.180';
 +    BEGIN
 +        DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
 +               host       => v_apex_server
 +            ,  lower_port => 80
 +            ,  upper_port => 80
 +            ,  ace        => xs$ace_type(privilege_list => xs$name_list('connect'),
 +                                         principal_name => 'apex_050000',
 +                                         principal_type => xs_acl.ptype_db)
 +        );
 +    END;
 +    /
 +</code>
 +
 +
 +Ein erster Test, der aber leider für diesen Einsatzzweck nicht erfolgreich ist, das Dokument wird als CLOB zurückgeben, das führt leider zu einer Zeichensatzwandlung und damit ist das Dokument hin:
 +<code plsql>
 +DECLARE
 +   v_file           clob;
 +   v_blob           blob;
 +   v_rest_url       VARCHAR2(2000);
 +   v_server_url     VARCHAR2(300):='http://10.10.10.180/jasperserver/';
 +   -- use this to get resource infos for this report
 +   v_resoure_path   VARCHAR2(300):='rest_v2/resources/';
 +   -- get the report
 +   v_report_path    VARCHAR2(300):='rest_v2/reports/';
 +   -- Which Report   
 +   v_report_name    VARCHAR2(200):='Primavera/PrimaTest';
 +   -- 
 +   v_user           VARCHAR2(32):='gpi';
 +   v_pwd            VARCHAR2(32):='gpi';
 +   -- read the clob
 +   v_buffer         VARCHAR2(32767);
 +   v_buffer_raw     RAW(32000);
 +   v_amount         NUMBER;
 +   v_offset         NUMBER;
 +   v_file_length    PLS_INTEGER;
 +   -- set the data
 +   v_mime_type      VARCHAR2(32):='application/pdf';
 +BEGIN
 +   -- create the URL
 +   v_rest_url:=v_server_url||v_report_path||v_report_name||'.pdf';
 + 
 +   DBMS_OUTPUT.put_line('--Info  -- get the report with '||v_rest_url);
 + 
 +   v_file := apex_web_service.make_rest_request(   p_url     => v_rest_url
 +                        ,  p_http_method => 'GET'
 +                        ,  p_parm_name   => apex_util.string_to_table('project_id')
 +                        ,  p_parm_value  => apex_util.string_to_table('1')
 +                        ,  p_username    => v_user
 +                        ,  p_password    => v_pwd );
 + 
 +   v_file_length:=DBMS_LOB.getlength (v_file);
 +   DBMS_OUTPUT.put_line('--Info  -- get the file ::'||SUBSTR(v_file,0,100)||' Length:'||v_file_length);
 + 
 +   -- create blob
 +   DBMS_LOB.createtemporary(v_blob, TRUE);
 + 
 +   -- read the file
 +   -- alternativ  dbms_lob.converttoblob
 +   v_amount := 32000;
 +   v_offset := 1;
 +   BEGIN
 +       LOOP
 +    -- read as clob
 +    DBMS_LOB.read( v_file, v_amount, v_offset, v_buffer );
 +    DBMS_OUTPUT.put_line('info -- read:'||TO_CHAR(v_offset));
 +    -- convert to blob
 +    v_buffer_raw := UTL_RAW.cast_to_raw(v_buffer);
 +    DBMS_LOB.writeappend(v_blob, UTL_RAW.LENGTH(v_buffer_raw), v_buffer_raw);
 +    -- next loop
 +    v_offset := v_offset + v_amount;
 +    v_amount := 32000;
 +       END LOOP;
 +   EXCEPTION
 +       WHEN NO_DATA_FOUND THEN
 +        NULL;
 +   END;
 +   --- 
 +   v_file_length:=DBMS_LOB.getlength (v_blob);
 +   BEGIN
 +    --send the file via APEX
 + OWA_UTIL.mime_header (NVL (v_mime_type, 'application/pdf'), FALSE);
 + HTP.p ('Content-length: ' || v_file_length);
 + htp.p('Content-Disposition:  attachment; filename="'|| v_report_name ||'.pdf"');
 + owa_util.http_header_close;
 + wpg_docload.download_file (v_blob);
 + apex_application.stop_apex_engine;
 + EXCEPTION WHEN OTHERS THEN
 + htp.prn('error: '||SQLERRM);
 + apex_application.stop_apex_engine;
 +   END;
 +END;
 +/
 +</code>
 +
 +Der Bericht kann nun über SQL*Plus testweise aufgerufen werden!
 +
 +Für HTTPS muss allerdings noch eine Wallet hinterlegt werden!
 +
 +
 +Jetzt muss das nur noch in Apex eingebunden werden.
 +
 +Auf die Schnelle in einer neuen leeren Apex Seite im Pre-Rendering Bereich im Before Header als Prozesse obigen Code hinterlegt, leider gibt das noch Bruch, wie befürchtet, schlägt hier etwas mit Zeichensatzwandel zu.
 +
 +<fc #800000>Da ein CLOB zurückgeben wird kommt es zu ersten Zeichensatzwandlungen, schlecht .... so funktioniert das nicht!</fc>
 +
 +
 +=== Lösung mit UTL_HTTP ===
 +
 +Um nun ein BLOB als Ergebniss zu erhalten, muss mit UTL_HTTP gearbeitet werden.
 +
 +ACL auf dem APEX Schema Owner setzen!
 +<code sql>
 +   DECLARE
 +      v_apex_server VARCHAR2(256):= '10.10.10.180';
 +    BEGIN
 +        DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
 +               host       => v_apex_server
 +            ,  lower_port => 80
 +            ,  upper_port => 80
 +            ,  ace        => xs$ace_type(privilege_list => xs$name_list('connect'),
 +                                         principal_name => 'GPI_APEX_SCHEMA',
 +                                         principal_type => xs_acl.ptype_db)
 +        );
 +    END;
 +    /
 +</code>
 +
 +
 +
 +So gehts, sehr grob, aber muss jetzt Abend essen kochen:
 +
 +<code plsql>
 +declare
 +    -- URL to call
 +    v_url      varchar2(2000):='http://10.10.10.180/jasperserver/rest_v2/reports/Primavera/PrimaTest.pdf';
 +
 +    -- Login data
 +    v_username varchar2(2000):='gpi';
 +    v_password varchar2(2000):='gpi';
 +    v_realm    varchar2(2000):=null;
 +    v_scheme   varchar2(256):=null;
 +
 +    -- get the URL Data 
 +    v_req      utl_http.req;
 +    v_resp     utl_http.resp;
 +    v_blob     blob;
 +    v_buf_blob blob;
 +  
 +    v_file_length pls_integer :=0;
 +    v_mime_type varchar2(34)  :='application/pdf';
 +    v_report_name varchar2(45):='primatest.pdf';
 +    v_error_log   varchar2(32000):='<html><body>';
 +    v_error       boolean := true;
 +begin
 + 
 +  -- Handle the http return code in this script
 +  utl_http.set_response_error_check(false);
 +  
 +  -- Start the http request
 +  v_req := utl_http.begin_request(v_url);
 +  -- use in this example http basic authen. scheme
 +  utl_http.set_authentication(v_req, v_username, v_password); 
 +  
 +  -- do the request 
 +  v_resp := utl_http.get_response(v_req);
 +  
 +  -- check if the login was sucessfull
 +  if (v_resp.status_code = utl_http.http_unauthorized) then
 +    -- check the answer of the server 
 + utl_http.get_authentication(v_resp, v_scheme, v_realm, false);
 + v_error_log:=v_error_log||'-- Info : web server is protected '||utl_tcp.CRLF;
 +    v_error_log:=v_error_log||'-- Info : Scheme ' || v_scheme || ' realm ' || v_realm || ' user credential nessesary'||utl_tcp.CRLF;
 +    -- end the request
 + utl_http.end_response(v_resp);
 +    v_error:=true;
 +  elsif (v_resp.status_code = utl_http.http_proxy_auth_required) then
 +    utl_http.get_authentication(v_resp, v_scheme, v_realm, false);
 +    v_error_log:=v_error_log||'-- Info : web proxy is protected '||utl_tcp.CRLF;
 +    v_error_log:=v_error_log||'-- Info : Scheme ' || v_scheme || ' realm ' || v_realm || ' user credential nessesary'||utl_tcp.CRLF;
 +    -- end the request
 + utl_http.end_response(v_resp);
 +    v_error:=true;
 +  elsif (v_resp.status_code = utl_http.HTTP_NOT_FOUND ) then
 +    utl_http.end_response(v_resp);
 +    v_error_log:=v_error_log||'-- Info : get 404 Page not found  '||v_url||utl_tcp.CRLF;
 +    v_error:=true;
 +  elsif (v_resp.status_code > 299 ) then
 +    utl_http.end_response(v_resp);
 +    v_error_log:=v_error_log||'-- Info : Get this result from the webserver:  '||to_char(v_resp.status_code)||utl_tcp.CRLF;
 +    v_error:=true;   
 +  else
 +    v_error:=false;
 +  end if;
 +  
 +  -- create the  blob to hold the result of the request
 +  dbms_lob.createtemporary( v_blob, true );
 +  -- readhe responmse 
 +  --
 +  begin
 +     loop
 +       utl_http.read_raw( v_resp, v_buf_blob );
 +       dbms_lob.append( v_blob, v_buf_blob );
 +     end loop;
 +   exception
 +     when utl_http.end_of_body
 +     then
 +       null;
 +  end; 
 +  -- close the response
 +  utl_http.end_response(v_resp);
 + 
 +  -- send the data
 +  v_file_length:=dbms_lob.getlength (v_blob);
 +  v_error_log:=v_error_log||'-- Info :  lenght resut '|| ': ' || to_char(v_file_length)||utl_tcp.CRLF;
 +  
 +  -- if no error send the blob as pdf
 +  if   v_error = false then 
 +    begin
 +     owa_util.mime_header (v_mime_type, false);
 + htp.p ('content-length: ' || v_file_length);
 + htp.p('content-disposition:  attachment; filename="'|| v_report_name ||'.pdf"');
 + owa_util.http_header_close;
 + wpg_docload.download_file (v_blob);
 + exception when others then
 + v_error_log:=v_error_log||'-- Info : Error Send File: '||sqlerrm;
 + v_error:=true;  
 +    end;
 +   end if;
 +   if v_error = true then 
 +    owa_util.mime_header ('text/html', false);
 +    owa_util.http_header_close;
 +    v_error_log:=v_error_log||'</pre></body></html>';
 +    htp.p(v_error_log);
 +    -- to debug strange results
 + --if v_blob is not null then 
 +    --  wpg_docload.download_file (v_blob);
 +    --end if;
 +   end if;
 +   -- end the apex process
 +   apex_application.stop_apex_engine;
 +
 +exception when others then
 +   owa_util.mime_header ('text/html', false);
 +   owa_util.http_header_close;
 +   v_error_log:=v_error_log||SQLERRM||' </pre></body></html>';
 +   htp.p(v_error_log);
 +   apex_application.stop_apex_engine;
 +end;
 +</code>
 +
 +Die Authorisierung finden Sie hier => Handling HTTP Authentication mit UTL_HTTP https://docs.oracle.com/database/121/ARPLS/u_http.htm#i1013202
 +
 +
 +
 +
 +**Schlussfolgerung:**
 +
 +D.h. wir können mit "apex_web_service" den Login vorbereiten, das dabei erzeuge Cookie muss dann in den PL/SQL Scope gespeichert und gesichert werden.
 +
 +
 +Synchron:
 +
 +  * Dann können wir gleich synchron mit UTL_HTTP den Bericht rufen und aus der DB verwenden.
 +
 +Asynchron:
 +  * Hier können wir wieder mit apex_web_service alles vorbereiten und dann den eigentliche Bericht mit UTL_HTTP abholen
 +
 +
 +Jetzt nähern wir uns stark der Lösung von Dietmar mit UTL_HTTP, eine einfache Umsetzen mit APEX_WEB_SERVICE sehe ich hier auf die schnelle nicht, da es anscheinend keine  Möglichkeit gibt, den Return einer Rest Calls als BLOB zu erhalten, jeder Verarbeitung eines CLOB führt aber zu Zeichensatzprobleme und zerstöret damit die Stuktur einer PDF Daten.
 +
 +
 +----
 +
 +==== Quellen ====
 +
 +PLSQL
 +
 +  * https://oracle-base.com/articles/misc/retrieving-html-and-binaries-into-tables-over-http
 +  * https://oracle-base.com/articles/misc/apex_web_service-consuming-soap-and-rest-web-services
 +  * http://kubilaykara.blogspot.de/2015/03/oracle-apexwebservice-rest-api-call.html
 +  * http://www.slideshare.net/KimBergHansen/oracle-36496025
 +
 +Apex Integration:
 +
 +  * http://www.opal-consulting.de/apex/f?p=20090928:4:0
 +  * http://www.opal-consulting.de/downloads/free_tools/JasperReportsIntegration/
 +  * http://www.opal-consulting.de/downloads/free_tools/JasperReportsIntegration/Opal-Consulting-JasperReportsIntegration.pdf
 +
 +
 +  * http://wphilltech.com/wp-content/uploads/2013/09/2013-09-OOW-St.Hilaire-JasperReports.pdf
 +  * http://community.jaspersoft.com/wiki/jaspersoft-tech-talks-episode-6-embedding-jaspersoft-your-php-application
 +
 +
 +
 +Jasper Allgemein
 +
 +
 +User:
 +
 +  * http://www.meetup.com/de-DE/TIBCO-Jaspersoft-Munich
 +
 +Integration 
 +
 +  * http://blog.jimdhughes.com/2015/06/02/rest-calls-to-jasperserver-from-node-js/
 +  * http://community.jaspersoft.com/questions/543926/rest-api-blank-pdf
 +
 +  * http://www.jaspersoft.com/resource/free-oreilly-book-embedding-analytics-modern-applications
 +
 +Oracle als Repostitory verwenden
 +
 +  * http://community.jaspersoft.com/questions/813885/how-configure-jasper-server-oracle-11g
 +  * http://community.jaspersoft.com/documentation/jasperreports-server-install-guide/v56/manually-creating-jasperreports-server-database
 +  * https://www.youtube.com/watch?v=YyvwaEYmMXg
 +
 +Apex Allgemein:
 +  * http://davidsgale.com/apex-how-to-download-a-file/
"Autor: Gunther Pipperr"
prog/oracle_apex_jasper_reports.txt · Zuletzt geändert: 2016/07/11 22:30 von gpipperr