Hi Experts,
Hope you are going well. I'm facing a dilemma and today I want to share it with you. Here is the problem. I have a JSF application which has its resources stored in 50 different locations and even more. The resource resolution logic is different for each case and the solution I came up with is to create a custom ResourceHandler to handle each case. So here is the basic structure of my 50 custom resource handlers and even more.
public class MyCustomResourceHandler extends ResourceHandlerWrapper{
private final ResourceHandler wrapped;
public MyCustomResourceHandler(ResourceHandler wrapped) {
this.wrapped=wrapped;
}
@Override
public Resource createResource(String resourceName)
{
return createResource(resourceName, null);
}
@Override
public Resource createResource(String resourceName, String libraryName)
{
//my logic here
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
Nothing new, I have just reused an overused and widespread technique to have only the ability to register a new implementation of the createResource(String resourceName, String libraryName) method into my application. But sadly I'm not able to register statically my 50 custom resource handlers and even more.
<application>
<resource-handler>com.my.package.MyResourceHandler</resource-handler>
</application>
So let's use the programmatic approach and let's write 50 times and even more this redundant code
Application application=FacesContext.getCurrentInstance().getApplication();
application.setResourceHandler(new MyCustomResourceHandler1(application.getResourceHandler()));
Having now this tragical experience, I can conclude that when creating a custom resource handler in the goal to register only a new implementation of the createResource(String resourceName, String libraryName) method into its application, a developer must repeat himself and rewrite over and over a well-known knowledge. That is why I'm asking for the automation of the job and for a fragmentation of the ResourceHandler concept into the concept of a ResourceResolver or a ResourceProvider, one can register in the resource handler.
public interface ResourceResolver {
public Resource createResource(String resourceName, String library);
}
One important thing is we can implement this concept without a change in how the resource request is handled and without the use of the chain of responsiblities pattern. We have just to add this interface and an addResourceResolver(resolver) method in the ResourceHandler class and behind the scenes we can do the job with this generic class (archetype)
public class ResourceHandlerImpl<T extends ResourceResolver> extends ResourceHandlerWrapper{
private final T resolver;
private final ResourceHandler wrapped;
public ResourceHandlerImpl(T resolver) {
this.resolver=resolver;
this.wrapped=FacesContext.getCurrentInstance().getApplication().getResourceHandler();
}
@Override
public Resource createResource(String resourceName)
{
return createResource(resourceName, null, null);
}
@Override
public Resource createResource(String resourceName, String libraryName)
{
Resource resource=resolver.createResource(resourceName, libraryName);
return resource!=null ? resource : wrapped.createResource(resourceName, libraryName);
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
a call to the addResourceResolver(resolver) method will be transcoded behind the scenes into : application.setResourceHandler(new ResourceHandlerImpl(resolver));
and the developer is left with this tiny code :
public MyResourceResolver implements ResourceResolver {
public Resource createResource(String resourceName, String library) {
//
}
}
and programmaticaly with this
resourceHandler.addResourceResolver(new MyResourceResolver());
You are free to comment.
Regards
Lamine