Environment: Oracle database 11.2.0.3, APEX 4.1.1, GlassFish 3.1.2 Open Source Edition (Web Profile), Oracle Linux 6.2
Update: Apache FOP support has been deprecated in ORDS 19.2. So please don’t upgrade to ORDS 19.2 (or higher) if you still rely on Apache FOP for PDF generation.
Apache FOP (XSL-FO Processor) can be used together with APEX to allow PDF printing of classic or interactive reports. In this blog post, I will explain how you can deploy and configure FOP in APEX 4.1.1 with GlassFish 3.1.2.
Apache FOP can be installed on a Java application server by deploying the fop.war web archive, which can be found in the /utilities/fop folder inside the APEX installation files. However, the fop.war file does not work out of the box on GlassFish 3.1.2.
I faced two different kind of errors in my installation:
1) package oracle.xml.parser.v2 does not exist: this is because GlassFish can’t find the xmlparserv2.jar file which can be found in $ORACLE_HOME/lib.
2) java.lang.IllegalStateException: getOutputStream() has already been called: this has something to do with getOutputStream() being used more than once; I’m far from a Java specialist, but I found a workaround for this problem on the internet.
This is the solution:
First, we need to extract the original fop.war file (I used the jar utility from my Java 6 JDK installation):
$ /u01/app/java/java6/bin/jar -xf fop.war
You should see the following:
$ ls -la
-rw-r–r– 1 oracle oinstall 1792 May 4 12:44 apex_fop.jsp
-rw-r–r– 1 oracle oinstall 7016135 May 4 12:44 fop.war
drwxr-xr-x 4 oracle oinstall 4096 May 4 14:00 WEB-INF
Next, copy the xmlparserv2.jar file from $ORACLE_HOME/lib into the WEB-INF/lib folder:
$ cp -p /u01/app/oracle/product/11.2.0/db_1/lib/xmlparserv2.jar WEB-INF/lib
Now we need to modify the two apex_fop.jsp files in the top folder and under WEB-INF/classes. Add the following 2 lines just before the final “driver.run();” call:
out.clear();
out = pageContext.pushBody();
The full apex_fop.jsp file should look like this:
Now we are going to recreate the fop.war file:
$ /u01/app/java/java6/bin/jar -cvf fop.war apex_fop.jsp WEB-INF
We are now ready to deploy the fop.war file in GlassFish:
– start up the GlassFish admin console (default: port 4848)
– click on Standalone Instances -> your instance
– click on Applications -> Deploy -> local packaged file… and browse to the “fop.war” file (see screenshot below)
– click on OK; “fop” should now appear in the list of Deployed Applications
After this, you can already test your Apache FOP deployment by opening http://<servername>:<port>/fop/apex_fop.jsp in a web browser. If you see a Java NullPointerException error, things are looking good ;-)
Finally, we need to tell APEX where to find the print server:
– log in to the APEX workspace “internal” with the username “admin”
– click on Manage Instance -> Instance Settings
– fill in the Report Printing part (see screenshot below):
Print Server: External (Apache FOP)
Print Server Host Address: localhost
Print Server Port: (your APEX port)
Print Server Script: /fop/apex_fop.jsp
That’s it! Now try to print a report as PDF in APEX; it should work fine!
Matthias
Reblogged this on APEX World and commented:
Great POST!!!!
Thanks :-)
You’re welcome!! It’s a great POST and should be shared
This setup works with glassfish 3.1.1.?
I appreciate your attention!
Yes, I just tried it on GlassFish 3.1.1 and it’s also working!
Good luck :-)
Matthias
Hi,
All settings were performed as directed in the post, but did not work is giving the following error when generating printing.
Error: ORA-20001: The printing engine could not be reached because either the
URL specified is incorrect or a proxy URL needs to be specified.
is_internal_error: true
apex_error_code: APEX.UNHANDLED_ERROR
ora_sqlcode: -20001
ora_sqlerrm: ORA-20001: ORA-20001: The printing engine could not be reached because either the
URL specified is incorrect or a proxy URL needs to be specified.
error_backtrace:
ORA-06512: em “APEX_040100.WWV_FLOW_PRINT_UTIL”, line 117
ORA-06512: em “APEX_040100.WWV_FLOW_RENDER_QUERY”, line 1619
ORA-06512: em “APEX_040100.WWV_FLOW_RENDER_QUERY”, line 1681
ORA-06512: em “APEX_040100.WWV_FLOW”, line 7261
I can not find the solution.
Can you help me?
Thanks!
Hello Claudio,
You probably need to give your APEX_040100 user network access, as explained in the APEX 4.1 installation guide. Access to network services is by default disabled in Oracle 11g.
You can do this by executing the following PL/SQL code with user SYS as SYSDBA:
DECLARE
ACL_PATH VARCHAR2(4000);
ACL_ID RAW(16);
BEGIN
-- Look for the ACL currently assigned to '*' and give APEX_040100
-- the "connect" privilege if APEX_040100 does not have the privilege yet.
SELECT ACL INTO ACL_PATH FROM DBA_NETWORK_ACLS
WHERE HOST = '*' AND LOWER_PORT IS NULL AND UPPER_PORT IS NULL;
-- Before checking the privilege, ensure that the ACL is valid
-- (for example, does not contain stale references to dropped users).
-- If it does, the following exception will be raised:
--
-- ORA-44416: Invalid ACL: Unresolved principal 'APEX_040100'
-- ORA-06512: at "XDB.DBMS_XDBZ", line ...
--
SELECT SYS_OP_R2O(extractValue(P.RES, '/Resource/XMLRef')) INTO ACL_ID
FROM XDB.XDB$ACL A, PATH_VIEW P
WHERE extractValue(P.RES, '/Resource/XMLRef') = REF(A) AND
EQUALS_PATH(P.RES, ACL_PATH) = 1;
DBMS_XDBZ.ValidateACL(ACL_ID);
IF DBMS_NETWORK_ACL_ADMIN.CHECK_PRIVILEGE(ACL_PATH, 'APEX_040100',
'connect') IS NULL THEN
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(ACL_PATH,
'APEX_040100', TRUE, 'connect');
END IF;
EXCEPTION
-- When no ACL has been assigned to '*'.
WHEN NO_DATA_FOUND THEN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL('power_users.xml',
'ACL that lets power users to connect to everywhere',
'APEX_040100', TRUE, 'connect');
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('power_users.xml','*');
END;
/
COMMIT;
Let me know if this helps,
Matthias
I remember that I am using the apex listener.
Hi,
Worked
Thanks!
thanks a lot it was very helpfull
Would you be able to provide additional information about the error: Error: ORA-20001: The printing engine could not be reached because either the
URL specified is incorrect or a proxy URL needs to be specified.? I have verified that I have network access for my user apex_040100. I can get as far as the java null exception, but when I attempt to print a report it states the error above.
Thanks!
That’s strange… Granting network access privileges should get rid of that error. I would think that there is something wrong with your ACL’s…
What do the following queries return? What version of Oracle database do you use?
select acl , host , lower_port , upper_port from DBA_NETWORK_ACLS;
select acl , principal , privilege , is_grant from DBA_NETWORK_ACL_PRIVILEGES;
Matthias
I ran into the same problem and found that the printer port that was set for the APEX instance was wrong. I set it to 8080 and it started working.
As SYS user:
SQL> ALTER SESSION SET CURRENT_SCHEMA = APEX_040100;
To check current printer port setting:
SQL> SELECT APEX_INSTANCE_ADMIN.GET_PARAMETER(‘PRINT_SVR_PORT’) port from dual;
PORT
——-
7777
To change port setting:
SQL> BEGIN
APEX_INSTANCE_ADMIN.SET_PARAMETER(‘PRINT_SVR_PORT’, 8080);
END;
/
SQL> commit;
I also had a problem with “^M” end-of-line characters in the fop.war file. I just did a “dos2unix” command on the files and that fixed the run-time Java error I was getting.
Other than these two problems that were my fault these instructions worked perfectly. Thanks.
Does this work with custom Report Layouts?
I tried your setup and printed a report query with a generic layout which worked just fine. With a custom layout though, I get the following error.
org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.checkDOMNSErr(CoreDocumentImpl.java:2526)
Sorry, I never tried it with a custom layout… Could well be that this doesn’t work!
Matthias
No problem.
Thanks for the prompt reply! I’ll post an update here if/when I get it to work.
Mitt.
Ok, thanks!
Hello Matthias, i follow this instruccion and when create a pdf file from apex, this file has 1kb and its imposible to open whith acrobat reader.
Can you help me ?
Thanks
I open de pdf file whith notepad and the error message is “error de informe:
ORA-20001: No se ha podido acceder al motor de impresión debido a que la dirección URL especificada es incorrecta o a que se debe especificar una dirección URL de proxy.”
My configuration is
Print Server : Apache FOP
Protocol = HTTP
Direccion = localhost or http://localhost i try with both
Port: 8080
Script = /fop/apex_fop.jsp
Hmm, then there must be something wrong with the deployment. What happens when you open the page apex_fop.jsp with a web browser?
Beautiful post. Your solution worked perfectly in my APEX 4.2.6 installation using Glassfish.
Thanks so much.