FOP resources embedded inside included jar library [was Re: WOBootstrap.jar]
FOP resources embedded inside included jar library [was Re: WOBootstrap.jar]
- Subject: FOP resources embedded inside included jar library [was Re: WOBootstrap.jar]
- From: Markus Ruggiero via Webobjects-dev <email@hidden>
- Date: Wed, 22 Apr 2020 13:38:40 +0200
For the record: issue resolved.
It _was_ a class path issue. There are several different class loades involved,
inside the standalone web service app, inside the WO app and in the combination
of the WO app using the standalone jar file as a library. And to make things
work from within Eclipse (where resources are available as files) and deployed
app (resources embedded in jar file), I had to create a CustomPathResolver and
take care of various paths.
---markus---
PS I was able to locate the source to WOBootstrap.java (officially not
available as far as I know). It was of now help in my case anyway.
//----------------- File CustomPathResolver.java -------------------
package com.XXX.coaserver.pdf;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;
import org.apache.xmlgraphics.io.Resource;
import org.apache.xmlgraphics.io.ResourceResolver;
/**
* This class allows access to resources stored either in the file system or in
the class path (inside a jar file).
* <br/>
*
* When running FOP from wihin Eclipse all resources can be referenced via
<code>file:</code>. However when
* packaging the project into a runnable jar file there is no filesystem path
available to any resource inside
* the jar file.
*
* An object of this class is given to FOP. It resolves any request for a
resource by accessing
* the resource from inside the jar file.
*
* This resolver tries different strategies to access a resource<br />
* <dl>
* <dt>URL scheme <code>file:</code></dt>
* <dd>this is the default when FOP reads fop.config and from
there<br />
* tries to access embedded font info file or the fonts
themselves</dd>
* <dt>URL scheme <code>classpath:</code></dt>
* <dd>use this inside XSL files to reference (static) resources
like<br />
* images and logos</dd>
* </dl><br />
*
*
* @see <br />
* Here are the pointers that helped<br /><br />
* @see {@link
https://stackoverflow.com/questions/60578457/accessing-fop-config-data-inside-a-runnable-jar-file}
* @see {@link
https://stackoverflow.com/questions/41661997/set-fopfactorybuilder-baseuri-to-jar-classpath}
* @see {@link
https://stackoverflow.com/questions/17745133/load-a-font-from-jar-for-fop}
*
* <br /><br />
* After (almost) everything worked, a re-ordering of the classpath was
necessary for the Eclipse export: In Edit Buildpath
* in the export order tab move apache-commons above fop<br /><br />
* @see {@link
https://stackoverflow.com/questions/51599091/fop-2-3-problems-wiht-foexternal-graphic}
*
*
* @author ruggiero
*
*/
public class CustomPathResolver implements ResourceResolver {
private static final Logger log = Logger.getLogger(
CustomPathResolver.class );
@Override
public Resource getResource(URI uri) throws IOException {
log.debug("resource URL: " + uri.toString());
String schemeSpecificPart = uri.getSchemeSpecificPart();
log.debug( " scheme specific part of URI: " +
schemeSpecificPart );
String resourceName = FilenameUtils.getName(uri.toString());
log.debug( " resource name: " + schemeSpecificPart );
InputStream inputStream = null;
// if we reference a real file (happens from within Eclipse)
// we test whether such a file is really available and set
// the input stream to that file
// if such file cannot be found we try to load it from the
classpath jar
if ("file".equals( uri.getScheme() )) {
log.debug(" trying to read resource from file
system");
File testFile = new File(uri);
if (testFile != null && testFile.exists()) {
inputStream = new FileInputStream( testFile );
}
if (inputStream == null) {
log.debug(" trying to read resource via
getResourceAsStream() using resource reference fonts/" + resourceName);
inputStream =
getClass().getResourceAsStream("/fonts/" + resourceName);
}
if (inputStream == null) {
log.debug(" trying to read resource via
getResourceAsStream() using resource name " + resourceName);
inputStream =
getClass().getResourceAsStream(resourceName);
}
}
if ( "classpath".equals( uri.getScheme() )) {
log.debug(" trying to read resource from jar file
(classspath:)");
inputStream =
getClass().getResourceAsStream(schemeSpecificPart);
}
// if neither a real file or a classpath reference into the jar
file
// can be found we throw an IOException
if (inputStream == null) {
throw new IOException( " Could not resolve resource
URI: " + uri );
}
return new Resource(inputStream);
}
@Override
public OutputStream getOutputStream(URI uri) throws IOException {
return
Thread.currentThread().getContextClassLoader().getResource(uri.toString()).openConnection().getOutputStream();
}
}
// ---------------------------------
Use the above CustomPathResolver when initiating FOP
// load the config file contents from the jar file
InputStream fopConfigStream = getClass().getResourceAsStream(
"/fopconfig.xml" );
FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder( new
File(".").toURI(), new CustomPathResolver() );
fopFactoryBuilder.setStrictFOValidation( false );
DefaultConfigurationBuilder cfgBuilder = new
DefaultConfigurationBuilder();
Configuration fopConfiguration = cfgBuilder.build( fopConfigStream );
fopFactoryBuilder.setConfiguration(fopConfiguration);
fopFactory = fopFactoryBuilder.build();
fopConfigStream.close();
> On 17 Apr 2020, at 13:50, Markus Ruggiero via Webobjects-dev
> <email@hidden> wrote:
>
> I am fighting a nasty classpath issue (at least I think it is class path
> related).
>
> Build a standard non-WO Java app that uses FOP to generate PDF. This app runs
> as a conventional WebService -> Works
> Export this app to standalone runnable jar-File. -> all fine and running and
> doing its job.
>
> Then I created a Wonder7 App and used the above exported jar-File as Library
> added to the buildpath. The WebService app has a public entry point for
> testing the creation of PDFs. This interface functions properly. The whole
> WebService app is built so that FOP resources (the FOP config file, fonts,
> images) can be referenced with a classpath: schema instead of a file: URI
> schema. This all works perfecly on my Mac and from Eclipse, both as a
> WebService as well as embedded library for the WO App.
>
> https://stackoverflow.com/questions/60578457/accessing-fop-config-data-inside-a-runnable-jar-file
>
> <https://stackoverflow.com/questions/60578457/accessing-fop-config-data-inside-a-runnable-jar-file>
> https://stackoverflow.com/questions/41661997/set-fopfactorybuilder-baseuri-to-jar-classpath
>
> <https://stackoverflow.com/questions/41661997/set-fopfactorybuilder-baseuri-to-jar-classpath>
> https://stackoverflow.com/questions/17745133/load-a-font-from-jar-for-fop
> <https://stackoverflow.com/questions/17745133/load-a-font-from-jar-for-fop>
>
> When I build the WO App and deploy it to a Windows Server (sorry, that't what
> the customer has) the app itself runs fine. And the WebService also functions
> correctly. Only FOP called via the above mentioned one-shot service entry
> point throws up with java.lang.IllegalArgumentException: URI scheme is not
> "file" when that WebService jar is called. I have no idea where/why this
> happens. I suspect class path ordering, which was already an issue that I was
> able to fix with the help of Stackexchange.
>
> https://stackoverflow.com/questions/51599091/fop-2-3-problems-wiht-foexternal-graphic
>
> <https://stackoverflow.com/questions/51599091/fop-2-3-problems-wiht-foexternal-graphic>
>
> However on Windows there is this infamous WOBootstrap.jar that manages the
> class path when deploying. I did not find any source code for it in Wonder
> thus I assume it is an original Apple WebObjects thing.
>
> Two questions:
> 1) is there source code available for WOBootstrap.jar?
> 2) can anyone make sense of the crash?
>
> Thanks a lot
> ---markus---
>
> java.lang.IllegalArgumentException: URI scheme is not "file"
> at java.io.File.<init>(Unknown Source)
> at org.apache.fop.fonts.FontCache.addFont(FontCache.java:335)
> at
> org.apache.fop.fonts.DefaultFontConfigurator.getFontInfo(DefaultFontConfigurator.java:173)
> at
> org.apache.fop.fonts.DefaultFontConfigurator.addFonts(DefaultFontConfigurator.java:136)
> at
> org.apache.fop.fonts.DefaultFontConfigurator.configure(DefaultFontConfigurator.java:89)
> at
> org.apache.fop.render.PrintRendererConfigurator.getCustomFontCollection(PrintRendererConfigurator.java:147)
> at
> org.apache.fop.render.PrintRendererConfigurator.setupFontInfo(PrintRendererConfigurator.java:127)
> at org.apache.fop.render.intermediate.IFUtil.setupFonts(IFUtil.java:170)
> at
> org.apache.fop.render.intermediate.IFRenderer.setupFontInfo(IFRenderer.java:187)
> at org.apache.fop.area.RenderPagesModel.<init>(RenderPagesModel.java:75)
> at
> org.apache.fop.area.AreaTreeHandler.setupModel(AreaTreeHandler.java:135)
> at org.apache.fop.area.AreaTreeHandler.<init>(AreaTreeHandler.java:105)
> at
> org.apache.fop.render.RendererFactory.createFOEventHandler(RendererFactory.java:350)
> at org.apache.fop.fo.FOTreeBuilder.<init>(FOTreeBuilder.java:107)
> at org.apache.fop.apps.Fop.createDefaultHandler(Fop.java:104)
> at org.apache.fop.apps.Fop.<init>(Fop.java:78)
> at org.apache.fop.apps.FOUserAgent.newFop(FOUserAgent.java:182)
> at org.apache.fop.apps.FopFactory.newFop(FopFactory.java:240)
> at com.dsm.coaserver.pdf.PDFCreator.createCoverPage(PDFCreator.java:208)
> at
> com.dsm.coaserver.pdf.PDFCreator.createInitialCfcDocument(PDFCreator.java:161)
> at com.dsm.coaserver.CFCManager.generatePdf(CFCManager.java:78)
> at
> com.dsm.coaserver.PdfMergeService.generatePreview(PdfMergeService.java:99)
> at
> com.dsm.coaconfig.components.PreviewCfCPDF.generateTestPDF(PreviewCfCPDF.java:56)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> at java.lang.reflect.Method.invoke(Unknown Source)
> at
> com.webobjects.foundation.NSKeyValueCoding$ValueAccessor$1.methodValue(NSKeyValueCoding.java:636)
> at
> com.webobjects.foundation.NSKeyValueCoding$_MethodBinding.valueInObject(NSKeyValueCoding.java:1134)
> at
> com.webobjects.foundation.NSKeyValueCoding$DefaultImplementation.valueForKey(NSKeyValueCoding.java:1324)
> at
> com.webobjects.appserver.WOComponent.valueForKey(WOComponent.java:1736)
> at
> com.webobjects.foundation.NSKeyValueCoding$Utility.valueForKey(NSKeyValueCoding.java:447)
> at
> com.webobjects.foundation.NSKeyValueCodingAdditions$DefaultImplementation.valueForKeyPath(NSKeyValueCodingAdditions.java:212)
> at
> com.webobjects.appserver.WOComponent.valueForKeyPath(WOComponent.java:1804)
> at
> com.webobjects.appserver._private.WOKeyValueAssociation.valueInComponent(WOKeyValueAssociation.java:50)
> at
> com.webobjects.appserver.WOComponent.valueForBinding(WOComponent.java:731)
> at
> com.webobjects.appserver._private.WOBindingNameAssociation.valueInComponent(WOBindingNameAssociation.java:44)
> at
> com.webobjects.appserver.WOComponent.valueForBinding(WOComponent.java:731)
> at
> com.webobjects.appserver._private.WOBindingNameAssociation.valueInComponent(WOBindingNameAssociation.java:44)
> at
> com.webobjects.appserver.WOComponent.valueForBinding(WOComponent.java:731)
> at
> com.webobjects.appserver._private.WOBindingNameAssociation.valueInComponent(WOBindingNameAssociation.java:44)
> at
> com.webobjects.appserver._private.WOGenericElement.invokeAction(WOGenericElement.java:137)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver._private.WOConditional.invokeAction(WOConditional.java:86)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver.WOComponent.invokeAction(WOComponent.java:1079)
> at
> er.extensions.components.ERXComponent.invokeAction(ERXComponent.java:161)
> at
> er.extensions.components.ERXNonSynchronizingComponent.invokeAction(ERXNonSynchronizingComponent.java:66)
> at er.coolcomponents.CCSubmitLink.invokeAction(CCSubmitLink.java:63)
> at
> com.webobjects.appserver._private.WOComponentReference.invokeAction(WOComponentReference.java:127)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver.WOComponent.invokeAction(WOComponent.java:1079)
> at
> er.extensions.components.ERXComponent.invokeAction(ERXComponent.java:161)
> at
> er.extensions.components.ERXNonSynchronizingComponent.invokeAction(ERXNonSynchronizingComponent.java:66)
> at
> com.webobjects.appserver._private.WOComponentReference.invokeAction(WOComponentReference.java:127)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver._private.WOConditional.invokeAction(WOConditional.java:86)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver.WOComponent.invokeAction(WOComponent.java:1079)
> at
> er.extensions.components.ERXComponent.invokeAction(ERXComponent.java:161)
> at
> er.extensions.components.ERXNonSynchronizingComponent.invokeAction(ERXNonSynchronizingComponent.java:66)
> at
> com.webobjects.appserver._private.WOComponentReference.invokeAction(WOComponentReference.java:127)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> er.extensions.components._private.ERXWOForm.invokeAction(ERXWOForm.java:217)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver._private.WOComponentContent.invokeAction(WOComponentContent.java:38)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver._private.WOHTMLURLValuedElement.invokeAction(WOHTMLURLValuedElement.java:149)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver.WOComponent.invokeAction(WOComponent.java:1079)
> at
> er.extensions.components.ERXComponent.invokeAction(ERXComponent.java:161)
> at
> com.webobjects.appserver._private.WOComponentReference.invokeAction(WOComponentReference.java:127)
> at
> er.extensions.components._private.ERXSwitchComponent.invokeAction(ERXSwitchComponent.java:120)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeChildrenAction(WODynamicGroup.java:105)
> at
> com.webobjects.appserver._private.WODynamicGroup.invokeAction(WODynamicGroup.java:115)
> at
> com.webobjects.appserver.WOComponent.invokeAction(WOComponent.java:1079)
> at er.directtoweb.pages.ERD2WPage.invokeAction(ERD2WPage.java:749)
> at com.webobjects.appserver.WOSession.invokeAction(WOSession.java:1357)
> at
> com.webobjects.appserver.WOApplication.invokeAction(WOApplication.java:1745)
> at
> er.extensions.appserver.ajax.ERXAjaxApplication.invokeAction(ERXAjaxApplication.java:116)
> at
> er.extensions.appserver.ERXApplication.invokeAction(ERXApplication.java:1971)
> at
> er.extensions.appserver.ERXComponentRequestHandler._dispatchWithPreparedPage(ERXComponentRequestHandler.java:157)
> at
> er.extensions.appserver.ERXComponentRequestHandler._dispatchWithPreparedSession(ERXComponentRequestHandler.java:235)
> at
> er.extensions.appserver.ERXComponentRequestHandler._dispatchWithPreparedApplication(ERXComponentRequestHandler.java:268)
> at
> er.extensions.appserver.ERXComponentRequestHandler._handleRequest(ERXComponentRequestHandler.java:302)
> at
> er.extensions.appserver.ERXComponentRequestHandler.handleRequest(ERXComponentRequestHandler.java:378)
> at
> com.webobjects.appserver.WOApplication.dispatchRequest(WOApplication.java:1687)
> at
> er.extensions.appserver.ERXApplication.dispatchRequestImmediately(ERXApplication.java:2092)
> at
> er.extensions.appserver.ERXApplication.dispatchRequest(ERXApplication.java:2057)
> at
> com.webobjects.appserver._private.WOWorkerThread.runOnce(WOWorkerThread.java:144)
> at
> com.webobjects.appserver._private.WOWorkerThread.run(WOWorkerThread.java:226)
> at java.lang.Thread.run(Unknown Source)
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
References: | |
| >WOBootstrap.jar (From: Markus Ruggiero via Webobjects-dev <email@hidden>) |