Cjxcz Odjcayrwl
Cjxcz Odjcayrwl

Reputation: 22867

How to load dynamic resources in JSF?

I would like to load dynamic resource (generated JavaScript, technically configuration in JSON) as dynamic resource, using h:outputScript tag. I'm aware I can do that via writing my own servlet and load it via normal tag scripts, by I would prefer the "JSF-way" of loading resouces.

Is it possible, and how?

Upvotes: 5

Views: 6532

Answers (1)

BalusC
BalusC

Reputation: 1109695

Yes, it's possible. You can achieve this by using a specific resource library name and have a custom ResourceHandler intercept on it and return a custom Resource when a resource of the specific library is been requested.

E.g.

<h:outputScript library="dynamicJs" name="some.js" />

with

public class DynamicJsResourceHandler extends ResourceHandlerWrapper {

    public DynamicJsResourceHandler(ResourceHandler wrapped) {
        super(wrapped);
    }

    @Override
    public Resource createResource(String resourceName, String libraryName) {
        if ("dynamicJs".equals(libraryName)) {
            return new DynamicJsResource(resourceName);
        } else {
            return super.createResource(resourceName, libraryName);
        }
    }

}

and

public class DynamicJsResource extends Resource {

    private String resourceName;

    public DynamicJsResource(String resourceName) {
        this.resourceName;
    }

    @Override
    public String getRequestPath() {
        // TODO: return "/context/javax.faces.resource/" + resourceName + ".xhtml?ln=dynamicJs";
    }

    @Override
    public URL getURL() {
        // TODO: return new URL("http://localhost:8080" + getRequestPath());
    }

    @Override
    public Map<String, String> getResponseHeaders() {
        // TODO: return desired HTTP response headers. 
    }

    @Override
    public InputStream getInputStream() throws IOException {
        // TODO: return InputStream by resourceName.
    }

    @Override
    public boolean userAgentNeedsUpdate(FacesContext context) {
        // TODO: return true when resource has been modified in server side.
    }

}

To get it to run, register it as follows in faces-config.xml:

<application>
    <resource-handler>com.example.DynamicJsResourceHandler</resource-handler>
</application>

If you happen to use JSF utility library OmniFaces, then you can also save the boilerplate code and extend from its org.omnifaces.resourcehandler.DynamicResource instead so you only need to implement getInputStream(). If you don't use OmniFaces, then you can always use its source code as guidance.

Upvotes: 7

Related Questions