Generating aggregate content-packages for CRX

Your typical CQ or CRX project is multi-module, right? You have the typical collection of modules = artifacts = bundles and content packages: content, samplecontent, uiapp, core, taglib – you name them.

For cutting releases, it’s convenient to have just a single, defined artifact that aggregates all project artifacts into one, has a single version number, and is easily installed.

Including OSGi bundles for installation in a content package is easy enough, including content packages in other content packages on the other hand is not so common (but also easy enough). Here’s how it works:

  • configure maven-vault-plugin
  • add the packages to include as dependencies
  • copy the packages into the aggregate package
  • adjust your vlt filter config
  • set the assembly package configuration (as usual)

configure maven-vault-plugin:

As always, configure maven-vault-plugin. Just use a different group than for your other packages, e.g. by appending ” Releases”. Also, set your module’s packaging to content-bundle.

<plugin>
    <groupId>com.day.jcr.vault</groupId>
    <artifactId>maven-vault-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <group>MyProject Releases</group>
        <requiresRoot>true</requiresRoot>
 
        <install>true</install>
        <verbose>true</verbose>
 
        <packageFile>${project.build.directory}/${project.build.finalName}.zip</packageFile>
 
        <version>${project.version}</version>
    </configuration>
</plugin>

add the packages to include as dependencies:

Just list them as regular dependencies, with the appropriate type (typically content-bundle).

<dependencies>
    <dependency>
        <groupId>my-project-groupid</groupId>
        <artifactId>uiapp</artifactId>
        <version>${project.version}</version>
        <type>content-package</type>
    </dependency>
    <dependency>
        <groupId>my-project-groupid</groupId>
        <artifactId>content</artifactId>
        <version>${project.version}</version>
        <type>content-package</type>
    </dependency>
    <dependency>
        <groupId>my-project-groupid</groupId>
        <artifactId>samplecontent</artifactId>
        <version>${project.version}</version>
        <type>content-package</type>
    </dependency>
</dependencies>

copy the packages into the aggregate package:

Configure maven-dependency-plugin to copy the dependencies to /etc/packages/MyProject as shown below.
You need to list out your artifacts in includeArtifacts.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-packages</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>
                    ${project.build.directory}/vault-work/jcr_root/etc/packages/MyProject
                </outputDirectory>
                <overWriteIfNewer>true</overWriteIfNewer>
                <includeArtifactIds>
                    uiapp,samplecontent,content
                </includeArtifactIds>
            </configuration>
        </execution>
    </executions>
</plugin>

adjust your vlt filter config (as usual):

Of course, your aggregate package needs to have an appropriate filter.xml, like so:

<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
    <filter root="/etc/packages/MyProject"/>
</workspaceFilter>

set the assembly package configuration (as usual):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <id>package-zip</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <descriptors>
                    <descriptor>src/main/assembly/package.xml</descriptor>
                </descriptors>
            </configuration>
        </execution>
    </executions>
</plugin>
<assembly>
    <id>zip</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
 
 
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/vault-work</directory>
            <outputDirectory/>
        </fileSet>
    </fileSets>
 
</assembly>

That’s it – now build your bundle with mvn package and you’ll get a neatly wrapped content bundle that contains your content bundles.

handling OSGi bundles

You can include your OSGi bundles directly in this bundle as well, or you can include them in your inner content bundles. Either way works. Above example takes the latter approach (so it cannot be seen and the examples are cleaner :)

adding metadata

As this is a regular content bundle, you can easily add custom content with release information, e.g. a file /etc/myapp-releaseinfo.txt that contains build number, etc.

Posted in Uncategorized | Tagged , , | Leave a comment

FireCurl: copy a cURL command line from the Firebug net panel

I want exactly what my browser gets – at exactly the same price

Continue reading

Posted in Uncategorized | Leave a comment

Building an XPI using Maven

For FireCurl, I wanted to use maven to do the packaging of the resulting XPI file.

Following below suggestions, you’ll be able to use the following for your Mozilla Extension project:

# to build a new XPI
mvn package
 
# to cycle versions in the POM, tag and build
mvn release:prepare

Automatic submission to AMO is missing so far.
Continue reading

Posted in Uncategorized | Tagged , , | Leave a comment

Installing a jar file to your local maven repository (fast)

There’s mvn:install-file, yes.
But it happens pretty often that the jar file you want to install already has a pom.xml in it that contains the information required on the command line and can be reused so that all you really should need to specify is the jar file you want to install.
The way it is, things are particularly inconvenient if you need to get 150+ jar files into your local repository.

Although this should go into mvn:install, here’s a quick-fix. Just call it with the filename of the jar file to install. Um, and do this in a tmp space, this leaves clutter.

#!/bin/bash
 
filename=$1
 
if [ "x$filename" = "x" ]; then
	echo "please feed me a file"
	exit 1;
fi
 
POM=$(jar tf $filename | grep pom.xml)
if [ "$?" -ne "0" ]; then
	echo "no pom.xml in file $filename. cannot automatically install this"
	exit 2;
fi
 
POM=$(echo $POM | head -1)
echo "proceeding with POM $POM"
 
jar xf $filename $POM
 
mvn install:install-file -Dfile=$filename -DpomFile=$POM

And here’s the complete goodness for shuffling all artefacts from a running CQ instance into your local maven repository:

#!/bin/sh
 
[ -z "$CRX_URL" ] && CRX_URL=http://localhost:4502
[ -z "$CRX_CREDENTIALS" ] && CRX_CREDENTIALS=admin:admin
 
curl -H x-crxde-version:1.0 -H x-crxde-os:mac -H x-crxde-profile:default -u $CRX_CREDENTIALS $CRX_URL/bin/crxde.classpath.xml > .classpath
FILE_LIST=`cat .classpath | sed -n '/lib/s/.*WebContent\(.*\)\".*/\1/p'`
for file in $FILE_LIST; do
	echo "Downloading $file"
	curl -u $CRX_CREDENTIALS $CRX_URL$file -O
done
 
for filename in *.jar; do
	POM=$(jar tf $filename | grep pom.xml)
	if [ "$?" -ne "0" ]; then
		echo "no pom.xml in file $filename. cannot automatically install this"
	else
		POM=$(echo $POM | head -1)
		echo "proceeding with POM $POM"
 
		jar xf $filename $POM
 
		mvn install:install-file -Dfile=$filename -DpomFile="$POM"
	fi
done
Posted in Uncategorized | Tagged , | Leave a comment

Content cake with data raisins

(This post is also available on dev.day.com)

In your typical CMS setup, most of the content is actively managed as such. But you often come across scenarios where other data needs to appear on a page, e.g. prices or product data that are provided by external sources and change on their own schedule.

There are various way to handle such a requirement, each with its own upsides and downsides.

Continue reading

Posted in Uncategorized | Leave a comment

Exploiting Firefox Bookmark Keywords and %s for CQ5, CRX (and whatever)

Having a hard time bookmarking all the relevant URLs to CRX, CRX Explorer, Felix Console, &c. for all of those dozens of development, staging, production, stresstest, and so on environments?

Here’s a simple hack for Firefox:

  • create a bookmark to the most common URL, including the endpoint in the system, and susbstitute the changing part with %s e.g. http://%s.cq-vpn.company.com/crx/browser/index.jsp
  • Go to the bookmark’s preferences and give it a keyword, e.g. crxb.

After that, all you need to type into the URL bar is crxb author-1.development to get to http://author-1.development.cq-vpn.company.com/crx/browser/index.jsp

Granted, no big science here, but helps to get there quickly without maintaining dozens of bookmarks.

Posted in Uncategorized | Leave a comment

Poor man’s Voice 2 RTM on the iPhone (non-Jott)

We buggers in the old world can’t use Jott. Sigh. I wish I could talk to my phone and have a task appear on RTM. Just that alone. I tried to sign up, as my mobile plan gives me free US calls, but alas: you actually need a US number to even sign up for Jott.

So what then? The best alternative I found was to use Dragon Dictation on the iPhone. It’s an impressive Voice-to-Text Application and allows you to copy to the clipboard, send by mail, post to twitter and facebook.

Continue reading

Posted in Uncategorized | Leave a comment

.bat Scripted Content Backups in CQ 5.x

Here’s just a trivial bit of script that builds a defined content package and pulls it from the server.

The curl part is pretty easy and didn’t take much after a brief look in Firebug (although I do miss a “copy as curl command” content menu entry in Firebug’s net panel ;-).

What was harder was to find a way to put a timestamp into a filename in a windows .bat file. I’m sure there are smarter ways to do this (including but not limited to installing bash ;-), but here’s what I came up with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Rem set group and package name as in package manager
Set GROUP=packagegroup
Set PACKAGE=packagename
Set HOST=hostname
 
Set CURRDATE=%TEMP%\CURRDATE.TMP
Set CURRTIME=%TEMP%\CURRTIME.TMP
 
DATE /T > %CURRDATE%
TIME /T > %CURRTIME%
 
Set PARSEARG="eol=; tokens=1,2,3,4* delims=/, "
For /F %PARSEARG% %%i in (%CURRDATE%) Do SET YYYYMMDD=%%l%%k%%j
 
Set PARSEARG="eol=; tokens=1,2,3* delims=:, "
For /F %PARSEARG% %%i in (%CURRTIME%) Do Set HHMM=%%i%%j%%k

Rem -k is only needed if you have a self-signed cert
curl -k -u admin:admin -o backup-%YYYYMMDD%%HHMM%.html -F cmd=build https://%HOST%/etc/packages/%GROUP%/%PACKAGE%.zip/jcr:content.console.html
curl -k -u admin:admin -o backup-%YYYYMMDD%%HHMM%.zip https://%HOST%/etc/packages/%GROUP%/%PACKAGE%.zip.res/%PACKAGE%.zip
Posted in Uncategorized | Tagged , | Leave a comment

Social Media: don’t invade, don’t shout or babble

After I checked in at the airport on foursquare recently, I received a reply from the airport via twitter, wishing me a good flight. OK, thanks @Airport_FRA – have a great day and take care.

This interaction was one permutation of an often-seen interpretation and implementation of personal interaction through social media. Some thoughs on this:

  • Social media are the consumers’ domain.
  • Make it easy to spread your message, don’t invade.
  • Listen and respond, don’t shout or babble.

Continue reading

Posted in Uncategorized | Leave a comment

Location based DRM: just a bad dream?

Last night, I went to see Sting in Frankfurt. He’s currently on tour with the Royal Philharmonic Concert Orchestra, and it was a great concert.

As usual, audio and video recording was forbidden, and just as usual everyone ignored it, taking pictures and videos with their mobiles.

Although I cannot see why exactly people do this, spending time with their devices instead of listening, I have a feeling that certain rights owners must be freaking out about this, but it would go too far to forbid mobile phones at concerts.

So I started wondering if at some point we’ll see some kind of location based DRM? Granted, not all devices have geolocation information, but for one thing coverage is getting greater (especially for devices which can shoot good videos), and there’s also some near-range communication technology that could be exploited (like Wifi, Bluetooth, RFID). Doesn’t have to be based on GPS.

Maybe this is far-fetched, but looking at the effort that is put into preventing people from digitizing what their eyes can see and their ears can see, it doesn’t seem completely out of range.

Posted in Uncategorized | Leave a comment