I've successfully implemented a custom post processor filter with the help of the wro4j documentation.
Its job is to generate and prepend SASS vars to a group of SASS files which are then handed off to the rubySassCss filter for transpiling, and it's doing this job well.
The problem is that I wanted to hand the job of determining the SASS vars off to a custom ThemeManager
@Service
managed by Spring. I hadn't considered that the filter wouldn't be able to see the autowired @Service but that seems to be the case.
When I @Autowire
the @Service
into a controller, it works fine, but when I try the same thing with the filter I get a NPE when attempting to use it.
Is there a way to make the @Service
visible to the filters or am I approaching this the wrong way?
Thanks for any help.
UPDATE:
It's taken some doing and attacking from a lot of angles, but I seem to be having success with autowiring my themeManagerService into the app configuration where I have my WRO filterRegistrationBean bean. I then pass the themeManagerService bean as a second argument to my custom ConfigurableWroManagerFactory.
Living in the custom WroManagerFactory is a reference to a custom UriLocator, which takes that themeManagerService as an argument. The custom UriLocator is invoked by a CSS resource containing an arbitrary keyword within a group.
The new UriLocator is able to generate a ByteArrayInputStream from what the themeManagerService provides it and pass it into the pipeline.
Simple.
I'll follow up when this approach pans/fizzles out.
In the end, I was able to provide the spring managed ThemeManagerService directly to the custom post processor, rather than relying on a custom UriLocator. I had tried that early on, but forgot to call super() in the new constructor, so the processor registration system was breaking.
I pass the @Autowired
ThemeManagerService
to my CustomConfigurableWroManagerFactory
when registering the WRO bean:
@Autowired
ThemeManagerService themeManagerService;
@Bean
FilterRegistrationBean webResourceOptimizer(Environment env) {
FilterRegistrationBean fr = new FilterRegistrationBean();
ConfigurableWroFilter filter = new ConfigurableWroFilter();
Properties props = buildWroProperties(env);
filter.setProperties(props);
//The overridden constructor passes ThemeManager along
filter.setWroManagerFactory(new CustomConfigurableWroManagerFactory(props,themeManagerService));
filter.setProperties(props);
fr.setFilter(filter);
fr.addUrlPatterns("/wro/*");
return fr;
}
The constructor injection of ThemeManagerService
into CustomConfigurableWroManagerFactory
means it can be passed along to the custom postprocessor as it's registered by contributePostProcessors
:
public class CustomConfigurableWroManagerFactory extends Wro4jCustomXmlModelManagerFactory {
private ThemeManagerService themeManagerService;
public CustomConfigurableWroManagerFactory(Properties props,ThemeManagerService themeManagerService) {
//forgetting to call super derailed me early on
super(props);
this.themeManagerService = themeManagerService;
}
@Override
protected void contributePostProcessors(Map<String, ResourcePostProcessor> map) {
//ThemeManagerService is provided as the custom processor is registered
map.put("repoPostProcessor", new RepoPostProcessor(themeManagerService));
}
}
Now, the post processor has access to ThemeManagerService
:
@SupportedResourceType(ResourceType.CSS)
public class RepoPostProcessor implements ResourcePostProcessor {
private ThemeManagerService themeManagerService;
public RepoPostProcessor(ThemeManagerService themeManagerService) {
super();
this.themeManagerService = themeManagerService;
}
public void process(final Reader reader, final Writer writer) throws IOException {
String resourceText = "/* The custom PostProcessor fetched the following SASS vars from the ThemeManagerService: */\n\n";
resourceText += themeManagerService.getFormattedProperties();
writer.append(resourceText);
//read in the merged SCSS and add it after the custom content
writer.append(IOUtils.toString(reader));
reader.close();
writer.close();
}
}
This approach is working as expected/intended so far. Hope it comes in handy for someone else.
Wro4j is a great tool and much appreciated.