How to embed generated group names in HTML files programmatically?

484 views
Skip to first unread message

Tim Bessie

unread,
Feb 2, 2012, 8:52:46 PM2/2/12
to wro4j
Hi all!

So we're looking for a way to do some cache-busting through naming all
combined resources based on their MD5 hash (or something along those
lines).

Currently, combined resources are run through the YUI compressor and
named myCombinedResource_productReleaseVersion.js (for example).

References in JSPs to these sources are made using JSTL of the form:
<script src="abc_${productReleaseVersion}.js"/> (for example).

The problem with this is, for every release, every combined resource
must be reloaded by users. What we'd like to do is have each resource
be named abc_CHECKSUM.js, which CHECKSUM is the checksum of the file.
This way, only files that have changed since the last release would
have different names, and force the browser to reload them. I'm
assuming here that not all browser/server setups will properly check
to see if the timestamp on the resource has changed, so this name
change will force the reload.

The problem with this is, how to embed the value of CHECKSUM for any
given generated/combined resource (since they will each be different
per file).

Can wro4j do this? The examples all seem to depend on including
resources based on unchanging, known names.

- Tim

Alex Objelean

unread,
Feb 6, 2012, 1:27:42 PM2/6/12
to wr...@googlegroups.com
Are you looking for a runtime or build-time solution?
Currently the cache-busting solution is supported for build-time solution only (maven plugin). 
For a runtime solution, you have to do some coding on your own, until this feature is available out of the box (need time or contributions to complete this one).

In any case, I can provide you with some support regarding how you can use it. Just describe your use-case in more details.

Cheers,
Alex 


- Tim

--
You received this message because you are subscribed to the Google Groups "wro4j" group.
To post to this group, send email to wr...@googlegroups.com.
To unsubscribe from this group, send email to wro4j+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/wro4j?hl=en.


Tim Bessie

unread,
Feb 17, 2012, 1:32:25 PM2/17/12
to wro4j
Thanks for your help - well, I suppose it depends upon what you mean
by run-time vs build time.

The JavaScript and CSS file combining/crunching/naming is done at
build time, but looking up the name of each of these files is done at
runtime.

Currently, using the Maven plugin we're using (along with the YUI
compressor), we're just having a single variable that creates a
timestamp, and combined/compressed files are named myFile-
timestamp.ext, so all places in the runtime code that needs to
reference the file can reference it as myFile-${timestamp}.ext.

Since what we'd like to do is to have each file (myFile1.ext,
myFile2.ext, etc) be named differently (i.e. myFile1-${myFile1-
checksum}.ext and $myFile2-${myCompressedFile-checksum}.ext), we'd
need to keep a table (or perhaps wro4j does this automatically) that
maps myFile1.ext to its name-with-checksum and myFile2.ext to ITS
name- with-checksum and make that lookup available to our code, in
JSPs, etc.

All file combining, compressing, and naming is done at build time.
 All we need to know at runtime is what each new name is for each file
(they will all be different).  Currently, we have something like this,
as an example:

.../js/javascriptFile1.js
.../js/javascriptFile2.js
...
.../js/javascriptFileN.js

These are combined and compressed (using YUI compressor maven plugin)
at build time into various combinations for various pages:

.../js/combinedJSFile1-timestamp.js
.../js/combinedJSFile2-timestamp.js
...
.../js/combinedJSFileN-timestamp.js

where 'timestamp' is the same for all files.

We have JSP's that include references like: the following (we're using
JSTL to make data model variables available to our JSP pages):

... src="/js/combinedJSFile1-${timestamp}"

and we have Spring MVC code that adds the munged filenames to list of
JavaScript and CSS files to be included on the next page to be served
(with the value of 'timestamp' available to this code in order to do
this).  This timestamp is placed into a properties file to be
accessible to the JSPs and code.

Instead of the above, we'd like to be able to generate files like this
at build time:

.../js/combinedJSFile1-checksum1.js
.../js/combinedJSFile2-checksum2.js
...
.../js/combinedJSFileN-checksumN.js

where 'checksum' is the DIFFERENT for all files.  We will need JSP's
that include references like:

... src="/js/combinedJSFile1-${checksums['combinedJSFile1']}"

(or something along those lines) and also have that mapping available
to the Spring MVC code when generating its inclusion lists.  This
hints at some properties file that contains this mapping, and which is
generated by your maven plugin, and is read in at server start time so
that it can be referenced by the app.

Sorry for the long description - I just wanted to make it very clear
what I'm trying to do. :-)

- Tim

On Feb 6, 10:27 am, Alex Objelean <alex.objel...@gmail.com> wrote:
> Are you looking for a runtime or build-time solution?
> Currently the cache-busting solution is supported for build-time solution
> only (maven plugin).
> For a runtime solution, you have to do some coding on your own, until this
> feature is available out of the box (need time or contributions to complete
> this one).
>
> In any case, I can provide you with some support regarding how you can use
> it. Just describe your use-case in more details.
>
> Cheers,
> Alex
>

Alex Objelean

unread,
Feb 17, 2012, 2:03:46 PM2/17/12
to wr...@googlegroups.com
You can achieve this with groupNameMappingFile property:
Extracted from mavenPlugin wiki page:

groupNameMappingFile - (available since 1.4.0) is an optional parameter. When provided, it should be the path to the properties file where the mapping between original group names and renamed(by NamingStrategy) are described. The generated file can be used to identify the name of aggregated bundle name. 

The file will hold the mapping between original (predictable) bundle name (ex: group1.js) and the name of the file renamed using one of the fingerprint encoder strategy. This allows client code to include the right resource into the final html and use far expiring headers, thus achieving aggressive resource caching. 

Example of the mapping file content:

all=all-asdf832323
common=common-njj3n128
util=util-21827391jhd

Loading this file from your application, you can easily retrieve the new resource name (containing checksum encoded).

Let me know if you need more help.

Cheers,
Alex

Tim Bessie

unread,
Feb 17, 2012, 3:05:12 PM2/17/12
to wro4j
Thanks Alex! I shall attempt to put this to work and let you know if
I encounter any difficulties!

- Tim

On Feb 17, 11:03 am, Alex Objelean <alex.objel...@gmail.com> wrote:
> You can achieve this with groupNameMappingFile property:
> Extracted from mavenPlugin wiki page<http://code.google.com/p/wro4j/wiki/MavenPlugin>
> :
>
> *groupNameMappingFile* - (available since 1.4.0) is an optional parameter.
> When provided, it should be the path to the properties file where the
> mapping between original group names and renamed(by NamingStrategy<http://code.google.com/p/wro4j/wiki/OutputNamingStrategy>)

Tim Bessie

unread,
Feb 17, 2012, 3:41:30 PM2/17/12
to wro4j
By the way - since we are doing the naming at build time using WRO4J
itself, how are we to create this mapping file?
It sounds like we have to create it ourself, but it's not a separate
step from WRO4J... that is, I can't quite tell from the documentation
(perhaps I haven't read enough of it yet) if I can tell WRO4J to
generate these files AND generate the mapping file, as an integrated
part of the build (since we won't know ahead of time what these names
will be).

I'm still experimenting, but just wanted to check - do we need to
create this mapping file ourselves as a separate step, or does the
WRO4J maven plugin do that for us? My goal would be for wro.xml to
say "here's a group, name it according to this naming strategy, AND
add the mapping to this file".

- Tim

On Feb 17, 11:03 am, Alex Objelean <alex.objel...@gmail.com> wrote:
> You can achieve this with groupNameMappingFile property:
> Extracted from mavenPlugin wiki page<http://code.google.com/p/wro4j/wiki/MavenPlugin>
> :
>
> *groupNameMappingFile* - (available since 1.4.0) is an optional parameter.
> When provided, it should be the path to the properties file where the
> mapping between original group names and renamed(by NamingStrategy<http://code.google.com/p/wro4j/wiki/OutputNamingStrategy>)

Alex Objelean

unread,
Feb 17, 2012, 3:47:13 PM2/17/12
to wr...@googlegroups.com
Currently, maven plugin doesn't create a file. It just write the mappings to the specified location. If you think creating the file if this doesn't exist is useful, I can fix this for the next release.

The rest works exactly as you described it.

Alex

Tim Bessie

unread,
Feb 17, 2012, 4:00:34 PM2/17/12
to wro4j
Hi again...

A bit confused... is groupNameMappingFiled READ by the plugin, or
CREATED by the plugin?

The doc says:

groupNameMappingFile - (available since 1.4.0) is an optional
parameter. When provided, it should be the path to the properties file
where the mapping between original group names and renamed(by
NamingStrategy) are described. The generated file can be used to
identify the name of aggregated bundle name.

so I'm a little unsure of if "the generated file" means a file that
wro4j creates at the given location which contains the mappings it
itself is creating (and then can be used at runtime), or if it
contains a mapping file that I have to create, and which it uses for
reference.

Also, I just realized another several needs of ours:

1. All CS and JSS files need to be copied to {targetLocation}/
originalName-${checksum}.ext
2. The file in #1, under it's new name needs to be able to be included
in groups
3. Groups themselves need to be includeable in other groups
4. Groups included in served pages need to be referred to in the pages
by their $originalName-${checksum} name, not by their vanilla group
name, otherwise the cache-busting won't always work (since the browser
may think it already has the file and not request it from the server).

Can all of the above be done with the plugin? If the above sounds
unintelligible, I'll try to clarify; meanwhile, I'm trying to do the
above by playing some more with WRO4J so I can ask better-informed
questions. :-)

- Tim

Alex Objelean

unread,
Feb 17, 2012, 4:04:24 PM2/17/12
to wr...@googlegroups.com
The description is a bit wrong (sorry for confusion). 
The plugin writes to the specified location. But it doesn't create the file if that doesn't exist. 

I've created the task which will fix this problem and the file will be created if none exist: http://code.google.com/p/wro4j/issues/detail?id=380

Cheers,
Alex

Tim Bessie

unread,
Feb 17, 2012, 4:13:37 PM2/17/12
to wro4j
Thanks! Always like to make helpful suggestions! :-)

- Tim

Alex Objelean

unread,
Feb 17, 2012, 4:40:28 PM2/17/12
to wr...@googlegroups.com
Regarding your other questions described in 4 steps. Answers are inline:

1. All CS and JSS files need to be copied to {targetLocation}/ 
originalName-${checksum}.ext
As long as NamingStrategy is set, the bundled resources will be copied to correct location respecting the naming strategy. [OK] 

2. The file in #1, under it's new name needs to be able to be included 
in groups 
Don't really understand this, but as long as you have a group named g1 which dependes on g2, you don't need to refer the absolute path to the generated resource (the one which has checksum encoded in its name).
3. Groups themselves need to be includeable in other groups 
That works by default. Example (with groovy DSL):
groups {
   g1 {
      group-ref("g2")
   }
   g2 {}
}
4. Groups included in served pages need to be referred to in the pages 
by their $originalName-${checksum} name, not by their vanilla group 
name, otherwise the cache-busting won't always work (since the browser 
may think it already has the file and not request it from the server).  

The NamingStrategy decides the name of the bundled resource. If you use, for example HashEncoderNamingStrategy, then the cache busting will work as expected.

Alex

Tim Bessie

unread,
Feb 17, 2012, 4:44:41 PM2/17/12
to wro4j
Thanks again, Alex - very helpful! I'll let you know my results when
I've got it all integrated.

- Tim

On Feb 17, 1:40 pm, Alex Objelean <alex.objel...@gmail.com> wrote:
> Regarding your other questions described in 4 steps. Answers are inline:
>
> *1. All CS and JSS files need to be copied to {targetLocation}/
> originalName-${checksum}.ext*
> *As long as NamingStrategy is set, the bundled resources will be copied to
> correct location respecting the naming strategy. [OK]** *
> 2. The file in #1, under it's new name needs to be able to be included
> in groups
> *Don't really understand this, but as long as you have a group named g1
> which dependes on g2, you don't need to refer the absolute path to the
> generated resource (the one which has checksum encoded in its name).
> *3. Groups themselves need to be includeable in other groups
> *That works by default. Example (with groovy DSL):*
> *groups {*
> *   g1 {*
> *      group-ref("g2")*
> *   }*
> *   g2 {}*
> *}*
> 4. Groups included in served pages need to be referred to in the pages
> by their $originalName-${checksum} name, not by their vanilla group
> name, otherwise the cache-busting won't always work (since the browser
> may think it already has the file and not request it from the server). * *
> *The NamingStrategy decides the name of the bundled resource. If you use,
> for example HashEncoderNamingStrategy, then the cache busting will work as
> expected.*
> *
> *
> Alex
> *
> *

Tim Bessie

unread,
Feb 17, 2012, 8:32:31 PM2/17/12
to wro4j
Ah, hold on, I hadn't had stack traces turned on - I'd added it to the
wrong maven call.

Here 'tis:


[INFO] Exception occured while processing: Illegal group reference

[INFO]
------------------------------------------------------------------------
[INFO] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: Exception
occured while processing: Illegal group reference
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:
719)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:
556)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:
535)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:
387)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:
348)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:
180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:
328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:
138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at
org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:
60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at
org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: org.apache.maven.plugin.MojoExecutionException: Exception
occured while processing: Illegal group reference
at
ro.isdc.wro.maven.plugin.AbstractWro4jMojo.execute(AbstractWro4jMojo.java:
108)
at
org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:
490)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:
694)
... 17 more
Caused by: java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
at
ro.isdc.wro.model.resource.processor.impl.css.AbstractCssUrlRewritingProcessor.parseCss(AbstractCssUrlRewritingProcessor.java:
106)
at
ro.isdc.wro.model.resource.processor.impl.css.AbstractCssUrlRewritingProcessor.process(AbstractCssUrlRewritingProcessor.java:
65)
at ro.isdc.wro.model.group.processor.PreProcessorExecutor
$3.process(PreProcessorExecutor.java:235)
at ro.isdc.wro.model.group.processor.PreProcessorExecutor
$2.process(PreProcessorExecutor.java:215)
at
ro.isdc.wro.model.group.processor.PreProcessorExecutor.applyPreProcessors(PreProcessorExecutor.java:
174)
at
ro.isdc.wro.model.group.processor.PreProcessorExecutor.processAndMerge(PreProcessorExecutor.java:
82)
at ro.isdc.wro.model.group.processor.GroupsProcessor
$1.processAndMerge(GroupsProcessor.java:78)
at
ro.isdc.wro.model.group.processor.GroupsProcessor.process(GroupsProcessor.java:
59)
at
ro.isdc.wro.manager.WroManager.getContentHashEntry(WroManager.java:
287)
at
ro.isdc.wro.manager.WroManager.serveProcessedBundle(WroManager.java:
175)
at ro.isdc.wro.manager.WroManager.process(WroManager.java:128)
at
ro.isdc.wro.maven.plugin.Wro4jMojo.processGroup(Wro4jMojo.java:213)
at ro.isdc.wro.maven.plugin.Wro4jMojo.doExecute(Wro4jMojo.java:
118)
at
ro.isdc.wro.maven.plugin.AbstractWro4jMojo.execute(AbstractWro4jMojo.java:
106)
... 19 more

Tim Bessie

unread,
Feb 17, 2012, 7:11:09 PM2/17/12
to wro4j
Oh, by the way, with regard to #1 - that's not exactly what I meant;
we sometimes refer to individual resources by name, and these names
have to have the checksum suffix as well (for the same cachebusting
reason).

Does this mean we'd need to create a separate group for each JS and
CSS file that exists, if we want to take advantage of renaming
individual resources like this, and be able to refer to them in JSPs
and in code? i.e. that mapping only happens with groups, not with
individual files, hmm?

- Tim

On Feb 17, 1:40 pm, Alex Objelean <alex.objel...@gmail.com> wrote:
> Regarding your other questions described in 4 steps. Answers are inline:
>
> *1. All CS and JSS files need to be copied to {targetLocation}/
> originalName-${checksum}.ext*
> *As long as NamingStrategy is set, the bundled resources will be copied to
> correct location respecting the naming strategy. [OK]** *
> 2. The file in #1, under it's new name needs to be able to be included
> in groups
> *Don't really understand this, but as long as you have a group named g1
> which dependes on g2, you don't need to refer the absolute path to the
> generated resource (the one which has checksum encoded in its name).
> *3. Groups themselves need to be includeable in other groups
> *That works by default. Example (with groovy DSL):*
> *groups {*
> *   g1 {*
> *      group-ref("g2")*
> *   }*
> *   g2 {}*
> *}*
> 4. Groups included in served pages need to be referred to in the pages
> by their $originalName-${checksum} name, not by their vanilla group
> name, otherwise the cache-busting won't always work (since the browser
> may think it already has the file and not request it from the server). * *
> *The NamingStrategy decides the name of the bundled resource. If you use,
> for example HashEncoderNamingStrategy, then the cache busting will work as

Tim Bessie

unread,
Feb 17, 2012, 8:27:09 PM2/17/12
to wro4j
Ok, getting strange errors. For one, even though I have specified
groups that contain ONLY CSS, WRO4J is trying to produce both .css
and .js versions of the groups (or perhaps that is just informational,
since it's logged at the INFO log level that a given file is 0 size).

In any case, the plugin is failing as follows... I can't figure out
what might be causing this (the error is "Exception occured while
processing: Illegal group reference", which isn't particularly helpful
- I've enabled exception display in Maven, but it's not shown):

Errors:

[INFO] [wro4j:run {execution: default}]
[INFO] Executing the mojo:
[INFO] Wro4j Model path: D:\Dev\Projects\Meez\workspace\dirtyclubs\war
\WEB-INF\wro.xml
[INFO] targetGroups: null
[INFO] minimize: true
[INFO] ignoreMissingResources: false
[INFO] wroManagerFactory: com.dm.build.wro4j.MeezWroManagerFactory
[INFO] extraConfig: D:\Dev\Projects\Meez\workspace\dirtyclubs\src\main
\webapp\WEB-INF\wro.properties
[INFO] destinationFolder: D:\Dev\Projects\Meez\workspace\dirtyclubs
\target\crunched\wro
[INFO] jsDestinationFolder: D:\Dev\Projects\Meez\workspace\dirtyclubs
\target\crunched\wro\js
[INFO] cssDestinationFolder: D:\Dev\Projects\Meez\workspace\dirtyclubs
\target\crunched\wro\css
[INFO] groupNameMappingFile: D:\Dev\Projects\Meez\workspace\dirtyclubs
\target/crunched/wro/groupNameMappingFile.properties
[INFO] wroManagerFactory class:
com.dm.build.wro4j.MeezWroManagerFactory
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_account_style_css.css
[INFO] file size: GROUP_account_style_css-cbcc9599.css -> 30938 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro
\css\GROUP_account_style_css-cbcc9599.css (30938 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_account_style_css.js
[INFO] file size: GROUP_account_style_css-0.js -> 0 bytes
[INFO] No content found for group: GROUP_account_style_css.js
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_petz_base_js.css
[INFO] file size: GROUP_petz_base_js-0.css -> 0 bytes
[INFO] No content found for group: GROUP_petz_base_js.css
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_petz_base_js.js
[INFO] file size: GROUP_petz_base_js-ecfaebb8.js -> 250938 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro\js
\GROUP_petz_base_js-ecfaebb8.js (250938 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_earncoinztabs_combined_js.css
[INFO] file size: GROUP_earncoinztabs_combined_js-0.css -> 0 bytes
[INFO] No content found for group: GROUP_earncoinztabs_combined_js.css
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_earncoinztabs_combined_js.js
[INFO] file size: GROUP_earncoinztabs_combined_js-879a77f9.js ->
204401 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro\js
\GROUP_earncoinztabs_combined_js-879a77f9.js (204401 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_export_combined_js.css
[INFO] file size: GROUP_export_combined_js-0.css -> 0 bytes
[INFO] No content found for group: GROUP_export_combined_js.css
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_export_combined_js.js
[INFO] file size: GROUP_export_combined_js-4ad0c860.js -> 242013 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro\js
\GROUP_export_combined_js-4ad0c860.js (242013 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_pm_combined_js.css
[INFO] file size: GROUP_pm_combined_js-0.css -> 0 bytes
[INFO] No content found for group: GROUP_pm_combined_js.css
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_pm_combined_js.js
[INFO] file size: GROUP_pm_combined_js-8b4dd7fb.js -> 50008 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro\js
\GROUP_pm_combined_js-8b4dd7fb.js (50008 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_main_combined_css.css
[INFO] file size: GROUP_main_combined_css-10a3fe79.css -> 31355 bytes
[INFO] D:\Dev\Projects\Meez\workspace\dirtyclubs\target\crunched\wro
\css\GROUP_main_combined_css-10a3fe79.css (31355 bytes)
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\js
[INFO] processing group: GROUP_main_combined_css.js
[INFO] file size: GROUP_main_combined_css-0.js -> 0 bytes
[INFO] No content found for group: GROUP_main_combined_css.js
[INFO] folder: D:\Dev\Projects\Meez\workspace\dirtyclubs\target
\crunched\wro\css
[INFO] processing group: GROUP_roomz_combined_css.css
[INFO]
------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO]
------------------------------------------------------------------------
[INFO] Exception occured while processing: Illegal group reference

Here is how I've got things configured... Maven plugin config:


<plugin>
<groupId>ro.isdc.wro4j</groupId>
<artifactId>wro4j-maven-plugin</artifactId>
<version>1.4.3</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- <targetGroups>all</targetGroups> -->
<minimize>true</minimize>
<destinationFolder>${crunched.dir}/wro/</
destinationFolder>
<cssDestinationFolder>${crunched.dir}/wro/css/</
cssDestinationFolder>
<jsDestinationFolder>${crunched.dir}/wro/js/</
jsDestinationFolder>
<contextFolder>${basedir}/war/</contextFolder>
<wroFile>${basedir}/war/WEB-INF/wro.xml</wroFile>

<wroManagerFactory>com.dm.build.wro4j.MeezWroManagerFactory</
wroManagerFactory>
<ignoreMissingResources>false</ignoreMissingResources>
<groupNameMappingFile>${crunched.dir}/wro/
groupNameMappingFile.properties</groupNameMappingFile>
</configuration>
</plugin>

----------

wro.xml:


<groups xmlns="http://www.isdc.ro/wro">

<group name="GROUP_home_combined_css">
<css>/css/base.css</css>
<css>/css/carousel.css</css>
<css>/css/home.css</css>
</group>
<group name="GROUP_home_unc_combined_css">
<css>/css/base.css</css>
<css>/css/carousel.css</css>
<css>/css/home-unc.css</css>
</group>
<group name="GROUP_welcome_combined_css">
<css>/css/base.css</css>
<css>/css/welcome.css</css>
</group>
<group name="GROUP_main_combined_css">
<css>/css/base.css</css>
<css>/css/main.css</css>
</group>
<group name="GROUP_itempage_combined_css">
<css>/css/base.css</css>
<css>/css/itempage.css</css>
</group>
<group name="GROUP_export_combined_css">
<css>/css/base.css</css>
<css>/css/export.css</css>
</group>
<group name="GROUP_account_combined_css">
<css>/css/base.css</css>
<css>/css/account.css</css>
</group>
<group name="GROUP_account_user_css">
<css>/css/base.css</css>
<css>/css/meezcode.css</css>
<css>/css/account.css</css>
</group>
<group name="GROUP_account_style_css">
<css>/css/base.css</css>
<css>/css/account.css</css>
<css>/css/style.css</css>
</group>
<group name="GROUP_verify_combined_css">
<css>/css/base.css</css>
<css>/css/verify.css</css>
</group>
<group name="GROUP_profile_combined_css">
<css>/css/base.css</css>
<css>/css/main.css</css>
<css>/css/profile.css</css>
</group>
<group name="GROUP_roomz_combined_css">
<css>/css/base.css</css>
<css>/css/roomz.css</css>
</group>
<group name="GROUP_myroomz_combined_css">
<css>/css/base.css</css>
<css>/css/myroomz.css</css>
</group>
<group name="GROUP_games_combined_css">
<css>/css/base.css</css>
<css>/css/games.css</css>
</group>
<group name="GROUP_community_combined_css">
<css>/css/base.css</css>
<css>/css/community.css</css>
</group>
<group name="GROUP_myfriends_combined_css">
<css>/css/base.css</css>
<css>/css/myfriends.css</css>
</group>
<group name="GROUP_video_combined_css">
<css>/css/base.css</css>
<css>/css/carousel.css</css>
<css>/css/video.css</css>
</group>
<group name="GROUP_help_combined_css">
<css>/css/base.css</css>
<css>/css/help.css</css>
</group>
<group name="GROUP_meezcode_combined_css">
<css>/css/base.css</css>
<css>/css/meezcode.css</css>
</group>
<group name="GROUP_upsell_combined_css">
<css>/css/base.css</css>
<css>/css/upsell.css</css>
</group>
<group name="GROUP_poker_combined_css">
<css>/css/base.css</css>
<css>/css/poker.css</css>
</group>
<group name="GROUP_survey_combined_css">
<css>/css/base.css</css>
<css>/css/survey.css</css>
</group>
<group name="GROUP_aim_login_combined_css">
<css>/css/base.css</css>
<css>/css/aim_login.css</css>
</group>
<group name="GROUP_vippage_combined_css">
<css>/css/base.css</css>
<css>/css/vippage.css</css>
</group>
<group name="GROUP_generic_combined_css">
<css>/css/base.css</css>
<css>/css/generic.css</css>
</group>
<group name="GROUP_gift_combined_css">
<css>/css/base.css</css>
<css>/css/gift.css</css>
</group>
<group name="GROUP_getcoinz_combined_css">
<css>/css/base.css</css>
<css>/css/getcoinz.css</css>
</group>
<group name="GROUP_cashcoinztabs_combined_css">
<css>/css/base.css</css>
<css>/css/cashcoinztabs.css</css>
</group>
<group name="GROUP_earncoinztabs_combined_css">
<css>/css/base.css</css>
<css>/css/earncoinztabs.css</css>
</group>
<group name="GROUP_combined_js">
<js>/js/meez.js</js>
<js>/js/shell.js</js>
<js>/js/no_crunch.js</js>
<js>/js/localized_strings.js</js>
<js>/js/hashtable.js</js>
<js>/js/util.js</js>
<js>/js/tab_functions.js</js>
<js>/js/popup_functions.js</js>
<js>/js/views.js</js>
<js>/js/validation_utils.js</js>
<js>/js/login_functions.js</js>
<js>/js/external-auth-functions.js</js>
<js>/js/avatar.js</js>
<js>/js/errormap.js</js>
<js>/js/queue.js</js>
<js>/js/tracking.js</js>
<js>/js/partner_functions.js</js>
<js>/js/appssavvy_functions.js</js>
</group>
<group name="GROUP_home_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/mascot.js</js>
<js>/js/carousel.js</js>
<js>/js/mobile-detect.js</js>
<js>/js/home.js</js>
</group>
<group name="GROUP_home_start_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/carousel.js</js>
<js>/js/mobile-detect.js</js>
<js>/js/home-unc.js</js>
</group>
<group name="GROUP_landing_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/swfobject.js</js>
<js>/js/landing.js</js>
</group>
<group name="GROUP_welcome_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/welcome.js</js>
</group>
<group name="GROUP_main_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/main.js</js>
<js>/js/mall_utils.js</js>
<js>/js/mall_functions.js</js>
<js>/js/applet.js</js>
<js>/js/swfobject.js</js>
</group>
<group name="GROUP_main_choose_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/choose.js</js>
</group>
<group name="GROUP_itempage_combined_js">
<js>/js/meez.js</js>
<js>/js/no_crunch.js</js>
<js>/js/localized_strings.js</js>
<js>/js/hashtable.js</js>
<js>/js/mall_utils.js</js>
<js>/js/util.js</js>
<js>/js/detail_tag.js</js>
<js>/js/palette_functions.js</js>
<js>/js/itempage.js</js>
<js>/js/tracking.js</js>
<js>/js/tab_functions.js</js>
</group>
<group name="GROUP_export_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/pbucket.js</js>
<js>/js/aim.js</js>
<js>/js/swfobject.js</js>
<js>/js/zero-clipboard.js</js>
<js>/js/export.js</js>
</group>
<group name="GROUP_account_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/account.js</js>
</group>
<group name="GROUP_account_user_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/region_functions.js</js>
<js>/js/meezcode_functions.js</js>
<js>/js/account.js</js>
</group>
<group name="GROUP_style_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/style.js</js>
</group>
<group name="GROUP_verify_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/verify.js</js>
</group>
<group name="GROUP_editprofile_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/editprofile.js</js>
</group>
<group name="GROUP_profile_user_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/rating.js</js>
<js>/js/friend.js</js>
<js>/js/applet.js</js>
<js>/js/contest.js</js>
<js>/js/profile.js</js>
</group>
<group name="GROUP_roomz_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/swfobject.js</js>
<js>/js/arcadia.js</js>
<js>/js/rating.js</js>
<js>/js/friend.js</js>
<js>/js/mascot.js</js>
<js>/js/roomz_functions.js</js>
<js>/js/roomz.js</js>
<js>/js/arcadia/meez_core.js</js>
<js>/js/arcadia/meez_redirector.js</js>
<js>/js/arcadia/meez_world.js</js>
<js>/js/arcadia/actions/meez_world_actions.js</js>
<js>/js/arcadia/actions/sites/meez_ext.js</js>
<js>/js/arcadia/actions/sites/guest.js</js>
</group>
<group name="GROUP_petz_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/swfobject.js</js>
<js>/js/arcadia.js</js>
<js>/js/roomz_functions.js</js>
<js>/js/petz.js</js>
<js>/js/arcadia/meez_core.js</js>
<js>/js/arcadia/meez_redirector.js</js>
<js>/js/arcadia/meez_world.js</js>
<js>/js/arcadia/meez_pets.js</js>
<js>/js/arcadia/actions/meez_world_actions.js</js>
<js>/js/arcadia/actions/sites/meez_ext.js</js>
<js>/js/arcadia/actions/sites/guest.js</js>
</group>
<group name="GROUP_myroomz_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/roomz_functions.js</js>
<js>/js/myroomz.js</js>
</group>
<group name="GROUP_games_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/mascot.js</js>
<js>/js/games.js</js>
</group>
<group name="GROUP_games_play_js">
<js>/js/cookie_functions.js</js>
<group-ref>GROUP_combined_js</group-ref>
<js>/js/applet.js</js>
<js>/js/arcadia.js</js>
<js>/js/rating.js</js>
<js>/js/mascot.js</js>
<js>/js/swfobject.js</js>
<js>/js/games.js</js>
</group>
<group name="GROUP_forum_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/forum.js</js>
</group>
<group name="GROUP_video_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/rating.js</js>
<js>/js/mascot.js</js>
<js>/js/carousel.js</js>
<js>/js/video.js</js>
</group>
<group name="GROUP_video_play_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/rating.js</js>
<js>/js/mascot.js</js>
<js>/js/swfobject.js</js>
<js>/js/video.js</js>
</group>
<group name="GROUP_help_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/help.js</js>
</group>
<group name="GROUP_invite_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/invitefriends.js</js>
</group>
<group name="GROUP_myfriends_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/myfriends.js</js>
<js>/js/friend.js</js>
</group>
<group name="GROUP_meezcode_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/meezcode.js</js>
<js>/js/meezcode_functions.js</js>
</group>
<group name="GROUP_upsell_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/upsell.js</js>
</group>
<group name="GROUP_poker_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/poker.js</js>
</group>
<group name="GROUP_survey_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/survey.js</js>
</group>
<group name="GROUP_generic_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/generic.js</js>
</group>
<group name="GROUP_gift_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/gift.js</js>
</group>
<group name="GROUP_vip_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/vip.js</js>
</group>
<group name="GROUP_getcoinz_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/region_functions.js</js>
<js>/js/getcoinz.js</js>
</group>
<group name="GROUP_cashcoinztabs_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/region_functions.js</js>
<js>/js/cashcoinztabs.js</js>
</group>
<group name="GROUP_earncoinztabs_combined_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/region_functions.js</js>
<js>/js/earncoinztabs.js</js>
</group>
<group name="GROUP_aim_base_js">
<js>/js/aim.js</js>
</group>
<group name="GROUP_aim_login_base_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/aim_multi_login.js</js>
</group>
<group name="GROUP_secure_login_js">
<group-ref>GROUP_combined_js</group-ref>
<js>/js/landing.js</js>
</group>
<group name="GROUP_pm_combined_js">
<js>/js/pm_functions.js</js>
<js>/js/popup_functions.js</js>
</group>

</groups>

Alex Objelean

unread,
Feb 18, 2012, 5:32:39 AM2/18/12
to wr...@googlegroups.com
It seems that there is a weird image url background used in one of your css which causes the problem. Could you isolate the problem? 

First, try to run plugin with -X option (debug). You should be able to see some more hints about problematic url. 
Or, just identify the css which has the problem and send the content of that particular css.

Thanks,
Alex

Alex Objelean

unread,
Feb 18, 2012, 5:37:08 AM2/18/12
to wr...@googlegroups.com
The default maven plugin behavior is to merge resources described in groups and create a single bundled resource for each group. If you want to process individual resource, you have to create a group for that resource only. 

It is possible to create a new maven plugin goal which would process each resource individually. The only problem I see with that approach is no clear requirements. I need a very clear use-case with detailed description of requirements in order to be able to implement it properly. Since wro4j is able to process resources from an arbitrary location (not only those living inside your webapp directory), it is hard to define the location of the processed resource...

Cheers,
Alex

Alex Objelean

unread,
Feb 18, 2012, 6:54:26 AM2/18/12
to wr...@googlegroups.com
Found the issue and fixed it. 

Apparently it was caused by an url containing the dollar sign ($). The fix was as suggested here: http://stackoverflow.com/questions/947116/matcher-appendreplacement-with-literal-text

to use Matcher.quoteReplacement when replacing a string containing this kind of characters.

Thanks for discovering it :)

Cheers,
Alex

Alex Objelean

unread,
Feb 18, 2012, 6:57:27 AM2/18/12
to wr...@googlegroups.com
Actually the original description is correct. When groupNameMappingFile property is specified (for maven plugin configuration), the file will be created by the plugin even if it doesn't exist. 

Cheers,
Alex

Tim Bessie

unread,
Feb 21, 2012, 4:19:49 PM2/21/12
to wro4j
Thanks again Alex... my experimentations continue. :-)

- Tim

On Feb 18, 3:57 am, Alex Objelean <alex.objel...@gmail.com> wrote:
> Actually the original description is correct. When *groupNameMappingFile*property is specified (for maven plugin configuration), the file will be

Alex Objelean

unread,
Mar 20, 2013, 6:02:27 AM3/20/13
to wr...@googlegroups.com, tbe...@meez.com, dmf...@gmail.com
There is a file where all those mappings are stored. You can load that property file in memory and use it in jsp to achieve aggressive caching. 
There are also a third party wro4j-taglib implementation available which helps you to achieve that as a runtime solution.

Cheers,
Alex

On Monday, March 18, 2013 11:01:54 PM UTC+2, dmf...@gmail.com wrote:
Hi,

I realize that this is an old thread, but I am interested in implementing aggressive caching as a build-time solution. Is there any way I could get some pointers of where to start?

What I would like to do is store a map of ${original-group-name} => ${new-group-name} in memory and reuse this map in a JSP, and to have wro4j use it. Any tips would be greatly appreciated. Thanks!

Dave Falke

unread,
Mar 20, 2013, 10:24:11 AM3/20/13
to Alex Objelean, wr...@googlegroups.com, tbe...@meez.com
Thanks for the information, Alex. If I'm not mistaken, the file you
are referring to is generated by the Maven plugin. What I was hoping
for was a way to avoid using the Maven plugin, and to compute and add
the checksum at run time. However, I've come to believe that this
would be a bad idea and could result in difficult to track bugs.

Thanks again for your help, and for such a great, well-designed project!
Reply all
Reply to author
Forward
0 new messages