Resource optimization with maven resources plugin
Posted by michpetrov in Michal Petrov's Blog on Nov 27, 2012 9:05:17 AMIn RichFaces 4.X custom skins do not work with resource optimization resulting in RF components not being properly styled. This is because your application expects a resource file named packed.css that contains styles for these components. This file is bundled with the predefined skins but not with your custom skin.
However you can generate that file with the resource plugin.
Get the URL
First make you sure you have resource optimization enabled in your web.xml:
<context-param> <param-name>org.richfaces.resourceOptimization.enabled</param-name> <param-value>true</param-value> </context-param>
Your application is expecting to find the file on a specific URL, you need to find it and then generate the file on that location. The link to the missing file will look similar to this:
{code}<link type="text/css" rel="stylesheet" href="/richfaces-photoalbum/org.richfaces.resources/javax.faces.resource/org.richfaces.staticResource/4.2.3.Final/PackedCompressed/photoalbum/packed/packed.css">{code}
The important part is org.richfaces.staticResource/4.2.3.Final/PackedCompressed, you will need this to set up the plugin.
Set up the plugin
Create a richfaces.version property in your pom.xml if you haven’t already (this makes it easier when you upgrade to a new version),
<properties> <richfaces.version>4.2.3.Final</richfaces.version> … </properties>
and put this inside the <build> element:
<plugin> <groupId>org.richfaces.cdk</groupId> <artifactId>maven-richfaces-resources-plugin</artifactId> <version>${richfaces.version}</version> <configuration> <skins> <!-- the name of your skin --> <skin>photoalbum</skin> </skins> <excludedFiles> <exclude>^\Qorg.richfaces.renderkit.html.images.\E.*</exclude> <exclude>^\Qorg.richfaces.renderkit.html.iconimages.\E.*</exclude> </excludedFiles> <includedContentTypes> <include>text/css</include> <include>image/.+</include> </includedContentTypes> <fileNameMappings> <property> <name>^.*showcase.*/([^/]+\.css)$</name> <value>org.richfaces.showcase.css/$1</value> </property> <property> <name>^.+/([^/]+\.(png|gif|jpg))$</name> <value>org.richfaces.images/$1</value> </property> <property> <name>^.+/([^/]+\.css)$</name> <value>org.richfaces.css/$1</value> </property> </fileNameMappings> </configuration> <executions> <execution> <id>process-resources</id> <goals> <goal>process</goal> </goals> <configuration> <!-- the actual name of this file is not important but it should be inside the META-INF folder --> <staticResourceMappingFile>${project.build.outputDirectory}/META-INF/richfaces/photoalbum-packedcompressed-resource-mappings.properties</staticResourceMappingFile> <!-- the URL part goes after /META-INF/resources/ --> <resourcesOutputDir>${project.build.outputDirectory}/META-INF/resources/org.richfaces.staticResource/${richfaces.version}/PackedCompressed/</resourcesOutputDir> <!-- replace completely with the URL part --> <staticResourcePrefix>org.richfaces.staticResource/${richfaces.version}/PackedCompressed</staticResourcePrefix> <pack>true</pack> <compress>true</compress> <excludedFiles> <exclude>^javax.faces</exclude> <exclude>^\Qorg.richfaces.renderkit.html.images.\E.*</exclude> <exclude>^\Qorg.richfaces.renderkit.html.iconimages.\E.*</exclude> <exclude>^jquery\.js$</exclude> </excludedFiles> </configuration> </execution> <!-- If you are in Development stage the compression is ignored, include this execution to generate uncompressed files --> <execution> <id>process-resources-packed</id> <goals> <goal>process</goal> </goals> <configuration> <staticResourceMappingFile>${project.build.outputDirectory}/META-INF/richfaces/photoalbum-packed-resource-mappings.properties</staticResourceMappingFile> <!-- the directory is named “Packed”, not “PackedCompressed” as in the previous execution --> <resourcesOutputDir>${project.build.outputDirectory}/META-INF/resources/org.richfaces.staticResource/${richfaces.version}/Packed/</resourcesOutputDir> <staticResourcePrefix>org.richfaces.staticResource/${richfaces.version}/Packed</staticResourcePrefix> <pack>true</pack> <compress>false</compress> <!-- do not compress --> <excludedFiles> <exclude>^javax.faces</exclude> <exclude>^\Qorg.richfaces.renderkit.html.images.\E.*</exclude> <exclude>^\Qorg.richfaces.renderkit.html.iconimages.\E.*</exclude> <exclude>^jquery\.js$</exclude> </excludedFiles> </configuration> </execution> </executions> </plugin>
Excuse the weird highlighting.
The important tags are resourcesOutputDir and staticResourcePrefix. Change them according to the URL part for the missing file (and replace the RichFaces version with ${richfaces.version}).
Now you can run the maven build and all necessary files will be generated. Enjoy your custom skin.
Notes
Plugin execution not covered by lifecycle configuration: org.richfaces.cdk:maven-richfaces-resources-plugin:4.2.3.Final:process (execution: process-resources-packed, phase: process-classes)
Your IDE may complain complain like (JBDS does) this but you can ignore that.
Troubleshooting
Skin not found
WARNING: Error creating resource org.richfaces.renderkit.html.BaseGradient
javax.faces.FacesException
at org.richfaces.application.DependencyInjectionServiceImpl.inject(DependencyInjectionServiceImpl.java:361)
at org.richfaces.resource.ResourceFactoryImpl.injectProperties(ResourceFactoryImpl.java:197)
at org.richfaces.resource.ResourceFactoryImpl.createHandlerDependentResource(ResourceFactoryImpl.java:320)
at org.richfaces.resource.ResourceFactoryImpl.createDynamicResource(ResourceFactoryImpl.java:468)
at org.richfaces.resource.ResourceFactoryImpl.createResource(ResourceFactoryImpl.java:412)
at org.richfaces.cdk.resource.handler.impl.DynamicResourceHandler.createResource(DynamicResourceHandler.java:85)
at org.richfaces.cdk.resource.handler.impl.AbstractResourceHandler.createResource(AbstractResourceHandler.java:42)
at org.richfaces.cdk.task.ResourceTaskFactoryImpl$ResourcesRendererCallable.createResource(ResourceTaskFactoryImpl.java:71)
at org.richfaces.cdk.task.ResourceTaskFactoryImpl$ResourcesRendererCallable.renderResource(ResourceTaskFactoryImpl.java:83)
at org.richfaces.cdk.task.ResourceTaskFactoryImpl$ResourcesRendererCallable.call(ResourceTaskFactoryImpl.java:155)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor23.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.richfaces.application.DependencyInjectionServiceImpl.invokeMethod(DependencyInjectionServiceImpl.java:187)
at org.richfaces.application.DependencyInjectionServiceImpl.inject(DependencyInjectionServiceImpl.java:354)
... 17 more
Caused by: org.richfaces.skin.SkinNotFoundException: Skin with name photoalbum not found
at org.richfaces.skin.AbstractSkinFactory.getSkin(AbstractSkinFactory.java:161)
at org.richfaces.cdk.skin.SkinFactoryImpl.getSkin(SkinFactoryImpl.java:49)
at org.richfaces.renderkit.html.BaseGradient.initialize(BaseGradient.java:124)
... 22 more
Caused by: java.util.concurrent.ExecutionException: org.richfaces.skin.SkinNotFoundException: Skin with name photoalbum not found
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at org.richfaces.skin.AbstractSkinFactory.getSkin(AbstractSkinFactory.java:157)
... 24 more
Caused by: org.richfaces.skin.SkinNotFoundException: Skin with name photoalbum not found
at org.richfaces.skin.AbstractSkinFactory.loadProperties(AbstractSkinFactory.java:133)
at org.richfaces.skin.AbstractSkinFactory.buildSkin(AbstractSkinFactory.java:107)
at org.richfaces.skin.AbstractSkinFactory$SkinBuilder.call(AbstractSkinFactory.java:56)
at org.richfaces.skin.AbstractSkinFactory$SkinBuilder.call(AbstractSkinFactory.java:47)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at org.richfaces.skin.AbstractSkinFactory.getSkin(AbstractSkinFactory.java:156)
at org.richfaces.cdk.skin.SkinFactoryImpl.getSkin(SkinFactoryImpl.java:49)
at org.richfaces.resource.CompiledCSSResource.getSkinHashCode(CompiledCSSResource.java:142)
at org.richfaces.resource.CompiledCSSResource.writeState(CompiledCSSResource.java:217)
at org.richfaces.util.Util.saveResourceState(Util.java:468)
at org.richfaces.cdk.resource.handler.impl.DynamicResourceHandler.createResource(DynamicResourceHandler.java:89)
... 12 more
…
If you encounter this error during the maven build (the actual stacktrace will be far longer) your custom skin is missing from the classpath. To fix it add the directory containing the skin as a resource to pom.xml:
<build> <resources> <resource> <directory>path/to/your/skin</directory> </resource> … </resources> … </build>
Comments