mvc-api icon indicating copy to clipboard operation
mvc-api copied to clipboard

Static Asset Support

Open ivargrimstad opened this issue 4 years ago • 8 comments

ivargrimstad avatar May 06 '21 15:05 ivargrimstad

Let's start some discussion about how this could look like in MVC.

Basically the goal would be to provide a way to reference static assets without using any Servlet specific features (because MVC does NOT require Servlet at the moment). This could for example look like this:

<img src="${mvc.asset('files/logo.png')}" alt="logo"/>

The MVC implementation would generate some URL and also make sure to serve the corresponding asset from this URL.

The first question is where the MVC implementation looks for such assets. Maybe simply in META-INF/resources on the classpath? This would be "compatible" with Servlet, without having a hard dependency on it.

Another question is how the MVC implementation should handle the content type of such assets. Should we require the implementation to "guess" it from the corresponding file extension?

This is just a quick summary of what I have in mind regarding this feature. But maybe somebody has a completely different understanding or has some other idea? Feedback welcome! :-)

chkal avatar May 08 '21 11:05 chkal

I like Christians proposals, so +1 for it in general.

Maybe we can additionally make the API more meaningful and provide some "standard" directories so users have a template, like /styles for CSS files or other style related content, /images for image resources and so on. They could be accessed like this:

/css/styles.css can be called with ${mvc.style('styles.css')}

/images/logo.png can be called with ${mvc.image('logo.png')

/custom/somefile.txt can be called with ${mvc.asset('/custom/somefile.txt')}

Those preconfigured directories could be configurable by some property, so we'd have a default template for all users wanting an easy start and a possibility to adapt it to personal needs for advanced topics.

erdlet avatar May 11 '21 17:05 erdlet

Maybe we can additionally make the API more meaningful and provide some "standard" directories so users have a template, like /styles for CSS files or other style related content, /images for image resources and so on. [...] Those preconfigured directories could be configurable by some property, so we'd have a default template for all users wanting an easy start and a possibility to adapt it to personal needs for advanced topics.

I wouldn't see this as a requirement for the first version of this feature. As you already mentioned, this would also require additional configuration parameters to be able to customize these directories. And I personally don't think that having something like ${mvc.image('logo.png') is much better than ${mvc.asset('images/logo.png'). But that's just my personal opinion.

The most important question for me is how to deal with content types. I just tried to figure out how Servlet handles this, but the spec doesn't seem to mention this at all. Or maybe I just don't find the relevant section in the spec document.

Anyone has more insights?

chkal avatar May 24 '21 10:05 chkal

Anyone has more insights?

After I've built and used a mechanism inspired by this issue in an application, I can say that the content type is properly handled by the underlaying container. So I think this isn't a problem.

What I recognized is that the placement of files is more relevant than thought, because there are differences in processing between the servers. So my current approach is to use Class#getResource to resolve the asset file located in WEB-INF/assets. This works fine in Tomcat and WildFly but fails in GF and Payara. So maybe we need to use another path for better compatibility.

erdlet avatar Sep 04 '22 11:09 erdlet

Isn't Class#getResource using the class loader of the class on which you call that method? And depending on which class this is, there maybe issues locating the resources depending on to which class loaders they are visible? I always try to use Thread.getContextClassLoader().getResource() instead, as this seems to correctly use the application's class loader? But I'm not 100% sure if this is correct.

chkal avatar Sep 05 '22 06:09 chkal

Thanks for the information. I'll try to find so time to test your approach. Maybe this is the solution for my problem :)

Anyway, it's weird that only Glassfish seems to have a problem here 🤔

erdlet avatar Sep 05 '22 07:09 erdlet

I guess that's because app servers handle the class loader complexity quite differently!?

chkal avatar Sep 05 '22 08:09 chkal

Maybe 🤷🏻 But let's try it with your approach. That seems promising.

erdlet avatar Sep 05 '22 08:09 erdlet