3

I'm writing a simple reporting web application using JAX-RS and AngularJS deployed to IBM WebSphere Application Server. Since it is really very simple I try to keep as little dependencies as possible, so I am not using any fancy framework server-side.

For serving static resources I wrote this controller. I keep them in src/main/resources folder.

@Path("/")
public class Assets {

    @GET
    @Path("{path:.*\\.js}")
    public Response javascript(@PathParam("path") String resourceName) {
        return serveResource(resourceName, "application/javascript");
    }

    private Response serveResource(String resourceName, String contentType) {
        InputStream inputStream =
            getClass().getClassLoader().getResourceAsStream(resourceName);

        return Response.ok(inputStream)
                .header(HttpHeaders.CONTENT_TYPE, contentType)
                .build();
    }
}

So far so good.

As I use several JavaScript libraries (jQuery, Underscore.js, AngularJS), I wanted to make use of WebJars. According to documentation on webjars.org:

With any Servlet 3 compatible container, the WebJars that are in the WEB-INF/lib directory are automatically made available as static resources. This works because anything in a META-INF/resources directory in a JAR in WEB-INF/lib is automatically exposed as a static resource.

When I put corresponding WebJars into my pom.xml, things stopped working. This is what I found out so far:

  • WebJars are, of course, present in the resulting .war package, in WEB-INF/lib folder.
  • ClassLoader used in my serveResource method claims in has all WebJars in its classpath.
  • The ClassLoader's implementation is com.ibm.ws.classloader.CompoundClassLoader.
  • None of the resources in present in WebJars in META-INF/resources folder is visible to the ClassLoader. None.

How can I make the class loader see the resources in the WebJars?

ᄂ ᄀ
  • 5,669
  • 6
  • 43
  • 57
Karel Smutný
  • 1,100
  • 1
  • 9
  • 17

1 Answers1

1

For serving files form JAR META-INF/resources you need WebSphere v8.5.
Check this page for more details - Web container configuration for JavaServer Pages static file access

Use the following methods to locate your static files:

URL ServletContext.getResource(String path)
Set ServletContext.getResourcePaths(String path) 

META-INF/resources directories of fragments under the WEB-INF/Lib directory in the application WAR file

After searching pre-fragment document roots, the web container searches web fragments. A web fragment comprises a JAR file in an application WEB-INF/lib directory. The JAR might include static resources in a META-INF/resources directory that are defined within the JAR file. To prevent the web container from searching META-INF/resources directories, set the com.ibm.ws.webcontainer.SkipMetaInfResourcesProcessing web container custom property to true. The default value for the custom property is false.

com.ibm.ws.webcontainer.SkipMetaInfResourcesProcessing = true

UPDATE
Try to change your method to something like this (pseudo code, no exception handling):

public Response javascript(@PathParam("path") String resourceName, 
                           @Context ServletContext servletContext) {

    // make sure resource name starts with / and should be relative path to META-INF/resources
    URL url = serveltContext.getResource(resourceName);  
    InputStream inputStream = url.openStream();

    return Response.ok(inputStream)
            .header(HttpHeaders.CONTENT_TYPE, "application/javascript")
            .build();
}

See ServletContext.getResource and URL.openStream

Gas
  • 17,601
  • 4
  • 46
  • 93
  • Thanks. I don't have `ServletContext` class in my dependencies (it is really very simple application). Is there a way around it? If not, what dependency should I add? – Karel Smutný Oct 07 '14 at 08:57
  • @KarelSmutný Updated answer with sample code. Dependency should be on javaee-api 6.0. – Gas Oct 07 '14 at 10:15