CSS Customization of extensions and cockpits

In most of the projects there is a requirement to differentiate the servers by colour. This helps to prevent that a customer makes changes on the wrong system. Although SAP Hybris doesn't offer this functionality out-of-the-box, it can be easily implemented.

Advantages of this method

  • A minimum number of files has to be changed
  • All the extensions use the same CSSs
  • Each new group of servers requires only one CSS file
  • Uses the standard Hybris customize mechanismus

Disadvantages of this method

  • Only customized CSS files are supported.

Prerequisites

  •  This method assumes that you are using the Areco Deployment Scripts Manager. If this isn't the case, you must create a property which indicates to what environment the server is.

Requirements

There were four groups of servers: Production (PRODUCTION), QA (INT), Testing for the developers (TEST) and the machines of the developers (DEV). These were the deployment environments defined by the Areco Deployment Manager. Each group had it own property file with the setting deploymentscripts.environment.current.

The customer wanted to have different background colours for each group of servers. In production the original background had to be shown.

CSS Files stored in the frontend

For each server group a CSS file was created and the images were uploaded:

bin/custom/webB2C/web/webroot/templates/resources/css/customize/DEV/environment.css
body {
    background: #5F021F url(../../img/T-System.png) repeat top left;
}
 
bin/custom/webB2C/web/webroot/templates/resources/css/customize/TEST/environment.css
body {
    background: #5F021F url(../../img/T-System.png) repeat top left;
}
 
bin/custom/webB2C/web/webroot/templates/resources/css/customize/INT/environment.css
body {
    background: #255DBD url(../../img/Q-System.png) repeat top left;
}
 
bin/custom/webB2C/web/webroot/templates/resources/css/customize/PRODUCTION/environment.css
(empty file because no changes were required)

The directory of the CSSs was accesible for every user, even the anonymous ones. And the setting b2c.baseUrl had the external url to the webB2C extension in any server group.

Customization of a Frontend using JSP

With the current environment and the external URL of the CSS files it was possible to load the CSS on runtime:

package com.acme.service.util.customization;
 
import de.hybris.platform.util.Config;
import org.apache.log4j.Logger;
import org.areco.ecommerce.deploymentscripts.core.impl.FlexibleSearchDeploymentEnvironmentDAO;
 
/**
 * It returns the location of the CSS containing styles which depend on the environment.
 *
 * All methods must be static because they are called from ZK and JSPs.
 * 
 */
public class EnvironmentStyleSheetResolver
{
  /*
    Logger of this class.
   */
  private static final Logger LOG = Logger.getLogger(EnvironmentStyleSheetResolver.class);
 
  public static String getURL() {
    final String url = Config
        .getString("b2c.baseUrl", "http://acme.com")
        + "/static/templates/resources/css/customize/" + Config.getString(FlexibleSearchDeploymentEnvironmentDAO.CURRENT_ENVIRONMENT_CONF, "PRODUCTION")
        + "/environment.css";
    if (LOG.isTraceEnabled())
    {
      LOG.trace("Url: '" + url + "'");
    }
    return url;
  }
}

Then the following code was added to all our Web Apps in the base template:

bin/custom/webB2C/web/webroot/templates/decorators/main.jsp
<%@page import="com.acme.service.util.customization.EnvironmentStyleSheetResolver" %>
 
<!-- Environment CSS -->
<link rel="stylesheet" href="/<%=EnvironmentStyleSheetResolver.getURL()%>">

The link to this style sheet was the last one because it had to override the original CSSs of the web app.

Cockpits

The old cockpit framework was based on ZK which had an expression language:

<!-- Environment CSS -->
<?xel-method prefix="essr" name="getURL"
     class="com.acme.service.util.customization.EnvironmentStyleSheetResolver"
            signature="string getURL()"?>
<style src="/${essr:getURL()}" />

Although the declaration of the static method could be done in zk.xml, the above code is easier to understand for non-ZK-developers than a configuration parameter. This code was added to the following files in the extension which uses the print cockpit:

bin/custom/acmePrint/web/webroot/index.zul
<?xml version="1.0" encoding="UTF-8"?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>

<?page title="hybris Product Cockpit" ?>
<div width="100%" height="100%" style="overflow: hidden;">
        
        <include src="/cockpit/commonCSA.zul" visible="false"/>
        
        <window xmlns="http://www.zkoss.org/2005/zul" 
                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:h="http://www.w3.org/1999/xhtml" 
                        xmlns:zk="http://www.zkoss.org/2005/zk"
                        xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd "
                        id="mainWin" mode="embedded" height="100%" sclass="hywin" use="de.hybris.platform.cockpit.components.impl.MainWindow"
                        shadow="false">
        
            <!-- Environment CSS -->
            <?xel-method prefix="essr" name="getURL"
                    class="com.acme.service.util.customization.EnvironmentStyleSheetResolver"
                    signature="string getURL()"?>
            <style src="/${essr:getURL()}" />
        </window>
</div>

bin/custom/acmePrint/web/webroot/login.zul
        <window border="none" use="de.hybris.platform.cockpit.components.login.LoginWindow" shadow="false">
                <style src="/cockpit/css/cockpit.css" />
                <style src="/acmePrint/css/acmePrint.css" />

        <!-- Environment CSS -->
          <?xel-method prefix="essr" name="getURL"
                class="com.acme.service.util.customization.EnvironmentStyleSheetResolver"
                signature="java.lang.String getURL()" ?>           <style src="/${essr:getURL()}" />
        </window>

Customization of PrintCockpit and ProductCockpit

As these are standard Hybris extensions the customize ant mechanismus was again used to override the original ZK files. The following files were created as copy of their original counterparts:

config/customize/ext-channel/printcockpit/web/webroot/index.zul
config/customize/ext-channel/printcockpit/web/webroot/login.zul
config/customize/ext-content/productcockpit/web/webroot/index.zul
config/customize/ext-content/productcockpit/web/webroot/login.zul

The same code as above was used.

Customization of HMC and HAC

All the customized hybris extensions are going to access the CSS files stored in the frontend. As these are standard Hybris extensions the customize ant mechanismus was used to override the original JSPs. The following files were created as copy of their original counterparts:

config/customize/platform/ext/hac/web/webroot/WEB-INF/jsp/decorators/main.jsp
config/customize/platform/ext/hac/web/webroot/login.jsp
config/customize/ext-platform-optional/hmc/web/webroot/frame.jsp
config/customize/ext-platform-optional/hmc/web/webroot/index.jsp

Because these extensions cannot accessed the EnvironmentStyleSheetResolver class, the code which was used in these extensions was slightly different:

<%@ page import="de.hybris.platform.util.Config" %>
<link rel="stylesheet" href="/<%=Config.getString("b2c.baseUrl","http://acme.com")%>/static/templates/resources/css/customize/<%=Config.getString("deploymentscripts.environment.current","PRODUCTION")%>/environment.css">

Alternative CSS stored in HMC

If you are only customizing HAC and HMC you can save the CSS files in the HMC extensions and don't touch your front end. To do this, you have to create the files:

config/customize/ext-platform-optional/hmc/web/webroot/css/customize/DEV/environment.css
config/customize/ext-platform-optional/hmc/web/webroot/css/customize/INT/environment.css
config/customize/ext-platform-optional/hmc/web/webroot/css/customize/PRODUCTION/environment.css
config/customize/ext-platform-optional/hmc/web/webroot/css/customize/TEST/environment.css

The CSS styles must override the original ones with different colours like:

/* HMC */
.tbody.page-header {
    height: 71px;
    background-image: none;
    background-color: #50A125;
}
 
tr.page-header {
    height: 71px;
    background-image: none;
    background-color: #50A125;
}
td table.toolbar {
    background-color: #50A125;
}
.page-header-right:before {
    content: "Produktion";
}
.page-header-right {
    font-size: 42px;
    color: red;
    text-shadow: 1px 1px 0 white,
    -1px 1px 0 white,
    1px -1px 0 white,
    -1px -1px 0 white,
    0px 1px 0 white,
    0px -1px 0 white,
    -1px 0px 0 white,
    1px 0px 0 white,
    2px 2px 0 white,
    -2px 2px 0 white,
    2px -2px 0 white,
    -2px -2px 0 white,
    0px 2px 0 white,
    0px -2px 0 white,
    -2px 0px 0 white,
    2px 0px 0 white,
    1px 2px 0 white,
    -1px 2px 0 white,
    1px -2px 0 white,
    -1px -2px 0 white,
    2px 1px 0 white,
    -2px 1px 0 white,
    2px -1px 0 white,
    -2px -1px 0 white;
}
body > form > table {
    background-image: none;
    background-color: #50A125;
}
 
/* HAC */
body.logincontainer {
    background: #50A125 none !important;
}
 
header.span-24 {
    background: #50A125 none !important;
}
 
#loginInfo:after {
    content: "Produktion";
    font-size: 18px;
    color: red;
}

And use the following lines in the JSPs of HAC and HMC:

<%@ page import="de.hybris.platform.util.Config" %>
<link rel="stylesheet" href="/<%=Config.getString("hmc.webroot","")%>/css/customize/<%=Config.getString("deploymentscripts.environment.current","PRODUCTION")%>/environment.css">

Deployment

When the new code had passed the QA process, the Hybris platform was updated in every server to remove the old customization files and the command ant customize was run.

Effort

It took fourteen hours to remove the old customization and develop, test and document the new one.

–Based on Hybris 5.6

Discussion

Enter your comment. Wiki syntax is allowed: