Pluggable styling with SpringSource Slices |
|

Since we announced SpringSource Slices, a number of users and customers have asked about using Slices to make the styling and branding of their Web sites pluggable. In this blog, I'll demonstrate how easy it is with Slices.
Pluggable styling
I have a standard war file, named styled.host.war, that contains a very simple index.html page:
<html> <head> <title>SpringSource Slices Pluggable Styling Demonstration</title> <link rel="StyleSheet" href="styles/main.css" type="text/css" /> </head> <body> <div class="header"> <div class="title">SpringSource Slices</div> <div class="subtitle">Pluggable Styling Demonstration</div> </div> </body> </html>
As you can see, it's looking for a CSS file named styles/main.css. Without a slice in place, this file doesn't exist. Deploying the war to dm Server shows that the page is unstyled:
cp styled.host.war ~/springsource-dm-server-2.0.0.CI-B297/pickup/
[2009-07-10 15:20:46.183] fs-watcher <SPDE0048I> Processing 'CREATED' event for file 'styled.host.war'. [2009-07-10 15:20:46.525] fs-watcher <SPDE0010I> Deployment of 'styled.host' version '1.0.0' completed. [2009-07-10 15:20:46.539] Thread-19 <SPWE0000I> Starting web bundle '/styling'. [2009-07-10 15:20:46.965] Thread-19 <SPWE0001I> Started web bundle '/styling'.

The page can easily be styled by deploying a Slice that specifies the styled host war as its host and provides the required stylesheet:
cp plain.style.slice.war ~/springsource-dm-server-2.0.0.CI-B297/pickup/
[2009-07-10 15:28:30.699] fs-watcher <SPDE0048I> Processing 'CREATED' event for file 'plain.style.slice.war'. [2009-07-10 15:28:30.789] fs-watcher <SPDE0010I> Deployment of 'plain.style.slice' version '1.0.0' completed.
Now if we look at the page, its appearance has changed thanks to the styling provided by the Slice:

Note that there was no need to redeploy or alter the Host war file, the Host simply picked up the new style when the Slice was deployed. Similarly, if we now undeployed the styling Slice, the Host would revert to its unstyled appearance that we saw earlier. Alternatively, we can take things a step further by removing this styling Slice and deploying another one to change the styling, again without having to redploy or alter the Host:
rm ~/springsource-dm-server-2.0.0.CI-B297/pickup/plain.style.slice.war cp green.style.slice.war ~/springsource-dm-server-2.0.0.CI-B297/pickup/
[2009-07-10 15:34:48.948] fs-watcher <SPDE0048I> Processing 'DELETED' event for file 'plain.style.slice.war'. [2009-07-10 15:34:49.038] fs-watcher <SPDE0012I> Undeployment of 'plain.style.slice' version '1.0.0' completed. [2009-07-10 15:36:01.064] fs-watcher <SPDE0048I> Processing 'CREATED' event for file 'green.style.slice.war'. [2009-07-10 15:36:01.146] fs-watcher <SPDE0010I> Deployment of 'green.style.slice' version '1.0.0' completed.

How does it work?
It's incredibly easy to take advantage of this capability of Slices.
The Host
The main host maps Slices' SliceHostFilter to /* in its web.xml file:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>host-filter</filter-name>
<filter-class>com.springsource.osgi.slices.core.SliceHostFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>host-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
This Filter will route any requests with a path that matches any of the Hosts's Slices to the matching Slice. If it doesn't find a matching Slice the request is simply passed through to the Host.
As we saw above in the index.html file, the host is looking for all of its styling within the /styles directory, but doesn't actually provide this content itself.
The styling Slices
Each of the styling Slices is also very simple. In their MANIFEST.MF files they specify their host, using the Slice-Host header, and a context path of /styles, using the Slice-ContextPath header:
Manifest-Version: 1.0 Bundle-SymbolicName: green.style.slice Bundle-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Styling Slice Slice-Host: styled.host;version="[1.0, 2.0)" Slice-ContextPath: /styles
The key thing here is that the configured context path of /styles matches the location in which the Host is looking for its styling. This means that, when the Slice is deployed, the filter in the Host will route requests made to /styles to the Slice. All that's left is for the styling slice to contain whatever resources are required to style the Host. In this case it's the main.css file, which the host references in its index.html, and an image which is referenced from the CSS:

Learning more
The source code for the war files that I've used above is available in the samples/pluggable-styling directory of the Slices Git repository (git://git.springsource.org/slices/slices.git). Also, take a look at Rob's announcement blog which includes details of how to build Slices and install it into dm Server.
Similar Posts
- Modular Web Applications with SpringSource Slices
- Slices Menu Bar Screencast
- Git Migration
- SpringSource dm Server 2.0.2 is released today.
- Announcing dm Server 2.0 M1





Dmitry Sklyut says:
Added on July 10th, 2009 at 12:12 pmWhat about having multiple styles deployed at the same time? Giving users an ability to choose from number of styles, i.e support for themes.
Thanks
Dmitry
Andy Wilkinson (blog author) says:
Added on July 11th, 2009 at 3:22 am@Dmitry, yes, this is possible too. I've added a new sample to Slices' Git repository in the samples/multiple-styles directory that provides a basic illustration of how this would work.
In the sample, there are multiple Slices but, crucially, each is configured with a *different* Slice-ContextPath. This allows the Host to access all of them, rather than only being able to use a single style as was possible in the pluggable styling sample discussed above. I've also updated the Host so that it has a basic style of its own which is defined in the HTML as the default stylesheet. The HTML then lists each of the styles provided by the Slices as an alternate stylesheet as provides a drop-down to allow users to switch between styles. The sample's not perfect as it hardcodes the styles that it expects to be provided by its Slices, but I hope that it illustrates the basic technique.
As you can see from the PetClinic Host, it's possible to determine which Slices are available at runtime, so the multiple styles sample could be updated to only offer users a choice of the styles which are actually available based on the Host's Slices. We plan (under DMS-914) to provide a tag library that, among other things, will make accessing a Host's Slices considerably more elegant than it is at the moment. Once that tag library's available, we'll update the PetClinic sample to make use of it, and probably update this sample to only offer the styles that are actually available.
Gunnar says:
Added on July 13th, 2009 at 1:27 amWouldn't it be better to prefix custom manifest headers with "SpringSource-…" to indicate to people that those aren't official OSGi header?
Andy Wilkinson (blog author) says:
Added on July 13th, 2009 at 1:43 am@Gunnar, there's been some discussion on this topic in the past, and it was raised with the OSGi Alliance. Their decision was not to use a prefix but, instead, to create a public registry of headers to prevent clashes. You can read some more about it in Glyn's blog entry:
http://blog.springsource.com/2008/11/27/springsource-manifest-headers-registered-with-osgi/
We'll be registering the Slices-related headers in the near future, and certainly before the M1 release. I've just raised an issue on the dm Server backlog so that you can track this work: https://issuetracker.springsource.com/browse/DMS-1136
Gunnar says:
Added on July 13th, 2009 at 1:46 amCool, thanks for the link!
Anoop says:
Added on July 14th, 2009 at 2:00 amWill the slices implementation be part of DM Server 2.0.0.M3 ?
Andy Wilkinson (blog author) says:
Added on July 14th, 2009 at 2:46 pm@Anoop, no, it won't. There's a chance that Slices will be part of M4, but while it's still a rapidly-evolving prototype we prefer to keep it a separate add-on. That said, we do have plans to start publishing ready-built zip files which will mean you don't have to build from source yourself: you can just unzip on top of dm Server, update the profile, and you're ready to go.