primefaces-extensions / primefaces-extensions.github.com

Organization repo, only for homepage, wiki and issue tracker
https://primefaces-extensions.github.io/
68 stars 22 forks source link

CustomExporterFactory could not be instantiated #728

Closed adjiandov closed 5 years ago

adjiandov commented 5 years ago

Hello, I am switching from the dataExporter to the extensions exporter component, because I need better implementation for lazy-loaded data. I would like to export in batches instead of the whole data, due to huge memory consumption. I followed the steps in the showcase in order to have a custom exporter, but when I tried to export I encountered the following error: java.util.ServiceConfigurationError: org.primefaces.extensions.component.exporter.ExporterFactory: Provider CustomExporterFactory could not be instantiated.

Here is the content of the org.primefaces.extensions.component.exporter.ExporterFactory file: path.to.my.factory.implementation.CustomExporterFactory

My CustomExporterFactory looks like the following: `public class CustomExporterFactory implements ExporterFactory { CustomExporterFactory() { }

public Exporter getExporterForType(String type) {
    Object exporter = null;

    try {
        CustomExporterFactory.ExporterType exporterType = CustomExporterFactory.ExporterType.valueOf(type.toUpperCase());
        switch(exporterType) {
        case PDF:
            exporter = new PDFExporter();
            break;
        case XLSX:
            exporter = new LazyExcelExporter();
            break;
        default:
            exporter = new PDFExporter();
        }

        return (Exporter)exporter;
    } catch (IllegalArgumentException var4) {
        throw new FacesException(var4);
    }
}

public static enum ExporterType {
    PDF,
    XLSX;

    private ExporterType() {
    }
}

}`

The part in my xhtml file is like following: ` <p:commandLink title="export" id="export-table-data" styleClass="top-small-space Fright" ajax="false" rendered="true" immediate="true" onclick="PrimeFaces.monitorDownload(showMonitor, hideMonitor)">

                <pe:exporter type="xlsx" pageOnly="false" target="table-id" fileName="sampleFile"/>
            </p:commandLink>

`

What I didn't quite understood is this part of the showcase example: `

` Is this mandatory? If yes, do I need to have my own ExporterController class in an ApplicationScope?

Thank you

melloware commented 5 years ago

I would say yes you need to follow those instructions and that example exactly: https://www.primefaces.org/showcase-ext/sections/exporter/customExporter.jsf

Including the <f:setPropertyActionListener value="true" target="#{exporterController.customExporter}" />

adjiandov commented 5 years ago

Hi Melloware, Thanks for the reply. Would this mean then that I would need to also have an ExportController bean, since there is none provided? I thought setting this property is only to distinguish later on if I want to use the custom exporters or not in the CustomExportFactory. I just added this line in my xhtml and now it is complaining that it cannot resolve exporterController (which I understand, because it is non-existent).

melloware commented 5 years ago

I have to admit this is one component I don't use and don't often touch in the PFE suite. I have never really studied it. The showcase code is available here: https://github.com/primefaces-extensions/showcase

I would download it and run it locally and study it to see how to make yours work.

adjiandov commented 5 years ago

Perfect, Thank you melloware :)

adjiandov commented 5 years ago

Hi melloware, were you able to run it locally? I see that the issue is closed, but there is no comment how to make this component work.

melloware commented 5 years ago

Did you download the showcase and run it? What is not working?

adjiandov commented 5 years ago

Hi melloware, I did a little investigation on the showcase project and found the following.

ExporterFactory factory = (ExporterFactory) context.getExternalContext().getApplicationMap().get(KEY);

On this line in the showcase the applicationMap contains the key which is the filename under the services package as described in the showcase example. However in my project the applicationMap is not populated with the mentioned filename and therefore the CustomExportFactory is not instantiated. What is the reason for that. Am I missing some configuration in order to have the applicationMap populated with the file under META-INF/services?

melloware commented 5 years ago

Not sure since like I said this is the only component in this suite I don't really touch. I can see that key is declared as:

private static final String KEY = ExporterFactoryProvider.class.getName();

And you are sure your file is called that exactly?

\src\main\resources\META-INF\services\org.primefaces.extensions.component.exporter.ExporterFactory

Other than that all I can say is it works in the Showcase you just have to find what is missing with your setup.

melloware commented 5 years ago

What container are you using? is it possible its not picking up your META-INF/services directives? Make sure the file is actually being included in your WAR file in the correct directory?

adjiandov commented 5 years ago

This was an issue with the class loader. In the copy/pasting from the DefaultExporterFactory, somehow a constructor with package protected modifier ended up in my CustomExporterFactory, which caused the above-mentioned error. Thank you for your time and if someone else experiences this, the CustomExporterFactory, does not need any constructor.

melloware commented 5 years ago

Thanks for posting your solution.