CX Works

CX Works brings the most relevant leading practices to you.
It is a single portal of curated, field-tested and SAP-verified expertise for SAP Customer Experience solutions

Migrating to an SAP Commerce Cloud Responsive Storefront

26 min read

Migrating to an SAP Commerce Cloud Responsive Storefront.

The release of SAP Commerce version 5.4 introduced a new B2C Responsive Storefront, followed by a new B2B Responsive Storefront in version 6.0. With both of the main accelerator storefronts responsive in the 6.4 release the mobile-related elements--which were used in the old approach of building storefronts-were completely removed.  This article describes the process of migrating a B2C storefront created prior to 5.4.x to the responsive storefront that shipped with SAP Commerce version 6.7.x.

As outlined in Choosing Which Storefront to Use for Your SAP Commerce Cloud Solution, there are now more options when it comes to storefronts. If you are planning to migrate from a legacy storefront you might want to determine whether the responsive storefront is the best fit for your requirements.

Table of Contents

Background

SAP Commerce 6.0 introduced a new way of working with responsive storefronts. As opposed to legacy approach that was serving completely different pages, stylesheets and scripts based on what device was used (mobile or desktop) the new approach utilizes a new frameworks and CSS features that allows using one single point-of-truth and reuse the same files. 

The legacy approach caused a lot of additional work to keep both the desktop and mobile channels up to date with new features, since every small change to one channel would have to be mirrored in the second one including files, scripts and CSS styles. This approach was very time consuming, both during development and maintenance. 

The new approach utilizes Bootstrap framework and CSS media queries to handle and show proper content for proper channels, styled accordingly to requirements for such view that is now contained in a single JSP file, styled in one CSS/LESS file and has related javascripts stored in one file. This approach reduces the effort and work needed to maintain both themes and makes it way clearer to see what is happening.

Estimations

The impact on migrating to the Responsive Storefront will vary depending on which SAP Commerce version is being used as the source. This is due to technical changes between older and newer versions of the platform containing different base libraries' versions, pre-processors, CMS Components changes, and deprecations or removals. The impact will be heavier as more custom code is written and unfortunately some of out-of-the-box components used in projects will need to be taken care of during the migration process.

Next, a pure responsive storefront should be generated in your target version and compare it to the pure version of Accelerator in your source version. This may help identify similarities and components that can easily  be reused with no additional work. This will result in a general hint of the required effort on top of migrating your existing customizations.

JSPs, tags and fragments

The main concern for this part of migration is basically all custom work done in the project as opposed to out of the box, but another layer of complexity is likely to come up if the source version used the old architecture of split themes for mobile and desktop.

As long as no change was performed to out-of-the-box components during project customization, this should not be an issue, but keep in mind that it's not rare for those components to get altered by project teams - in such case the migration becomes much more difficult, since all. changes have to be detected  and manually mirrored in the new responsive storefront.

For every custom JSP and tag file that are present in storefront extension, assume that there is additional work needed rather than just copying it over to the new storefront. This is due to changes in out-of-the-box stylesheets. The major factor here is the legacy mobile/desktop, current responsive approach, and other general changes in the styling of out of the box components that may interfere with custom styles.

Controllers

Keep in mind that storefront migration also affects storefront controllers. Codebase changes in out-of-the-box platform throughout different versions may cause various problems when combined with custom controllers, which reuse or extend the platform code. Some customer solutions contain heavily customized controllers, adding complex logic that sometimes might not be trivial at all to migrate or reflect in new storefront.
During the analysis and estimation one should identify all custom controllers, their dependencies to the platform controllers and impact on storefront components behavior (including JSPs, tags and fragments) since it is a common approach to steer the behavior based on controllers behavior.

The key point is that some of the custom controllers may limit or even completely rule out using the new accelerator code, which might require a lot of work to fix properly.

Stylesheets

SAP Commerce version 6.1 introduced a new way to handle styling of pages. Instead of using plain old CSS the platform now offers a LESS pre-processor that eases the work with styling. Even though this will lead to less maintenance in the long term, such an improvement brings another level of complexity and possible issues to the migration process.

It is very common for a project to only use plain CSS stylesheets and we highly recommend you port them to utilize the LESS approach. However, this requires a lot of work and if the situation requires a rapid migration then the old .css files needs to work well with the new approach if migrated to correct folder structure. The reason behind recommending and moving all styles to LESS files is that this allows future development and migrations to benefit from the approach and comply with SAP Commerce platform standards.

Javascript

Due to changes in base libraries and its versions ( for e example, jQuery) each piece of custom javascript written specifically for the project needs to be reviewed. This rule applies to every javascript file that exists in custom extensions and possible javascript changes in out-of-the-box javascript code. Since there is a possibility to embed custom scripts inside JSP files, this also needs to be taken into consideration, reviewed and estimated. Keep in mind that this kind of customization makes it impossible to minify the embedded script during the regular storefront build process and we recommend you extract the script from JSP and create a separate file for it.

CMS Components

This is probably the most complicated and costly part of the migration process, since many existing components have been reworked, deprecated, or deleted over different versions. This is a concern for the storefront experience itself, but in some cases it will only affects the management of those components in SmartEdit.

The main change regarding CMS components is the navigation itself, where the whole structure was reworked and different components should be used in current versions of the platform than was previously used. This impacts the storefront experience and editing the navigation in CMSCockpit or SmartEdit. If your project contained simple navigation that properly reused out-of-the-box navigation and contained no custom work, then this part will have little impact. Unfortunately, the majority of projects have custom code and logic in the navigation, which adds more complexity and increases the impact. If you choose to copy-over the navigation from the source version of the project being migrated, then it will most likely result in non-editable content.

Given the constant development for SmartEdit it is hard to provide an estimate of the impact it will have on your project. The product documentation for SmartEdit contains support for each of the existing or historical components (for example here is the page for 1808 components). Keep in mind that some of the existing components (such as RotatingImagesComponent) were dropped and it is pretty easy to migrate the storefront part by copying over the JSP file and stylesheets, but implementing such a component in SmartEdit is not trivial. See the sections on customization for the SmartEdit page.

Migration how to - background

Given the significant differences between how the legacy storefronts and the responsive storefront are developed, as well as the various levels of customizations for each particular project, there is no migration tool for storefronts. In the sections below we provide a description of the steps you can take to perform a storefront migration between an SAP Commerce storefront prior to the introduction of the responsive storefront (i.e. 5.3.x) and a version with mobile-related elements removed (i.e. 6.7.x). This is described using the example of a few storefront features implemented for purpose of this article.

Legacy Storefront Setup

This section describes, the example storefront features which were implemented in an out-of-the-box B2C Accelerator for SAP Commerce 5.3.0.8. The Following section describes the process of migrating these features to newer platform version. The implemented features were:

  • New CMS page template and new CMS page.
  • New CMSParagraphComponents and SimpleBannerComponent added as the content for the created page.
  • Custom tag with clickable toggle element and text message.
  • Custom CSS stylesheets with differences between mobile and desktop UI experiences.
  • Custom JavaScript files with example functionality of hiding/showing page fragment by clicking toggle element.

These items were implemented separately for the mobile and desktop UI experiences. The steps to implement these features were:

  1. Generating a new example module by using ant modulegen task
  2. Adding elements which will be used for desktop UI experience:
    1. Adding IMPEX containing new page template, content page, CMS components, content slots and media items

      IMPEX with CMS content for desktop user experience
      INSERT_UPDATE PageTemplate; $contentCV[unique=true]; uid[unique=true]   ; name                 ; frontendTemplateName; restrictedPageTypes(code); active[default=true]
                                ;                        ; ExamplePageTemplate; Example Page Template; example/examplePage ; ContentPage             
       
      INSERT_UPDATE ContentPage; $contentCV[unique=true]; uid[unique=true]; name                ; masterTemplate(uid,$contentCV); label      ; defaultPage[default='true']; approvalStatus(code)[default='approved']; homepage[default='false']
                               ;                        ; examplePage     ; Example Content Page; ExamplePageTemplate           ; examplePage
       
      INSERT_UPDATE ContentSlotName; name[unique=true]; template(uid,$contentCV)[unique=true][default='ExamplePageTemplate']; validComponentTypes(code); compTypeGroup(code)
                                   ; SiteLogo         ;                                                                     ;                          ; logo              
                                   ; HeaderLinks      ;                                                                     ;                          ; headerlinks       
                                   ; SearchBox        ;                                                                     ;                          ; searchbox         
                                   ; MiniCart         ;                                                                     ;                          ; minicart          
                                   ; NavigationBar    ;                                                                     ;                          ; navigation        
                                   ; Footer           ;                                                                     ;                          ; footer            
                                   ; TopHeaderSlot    ;                                                                     ;                          ; wide              
                                   ; TopSection       ;                                                                     ;                          ; wide              
                                   ; MiddleSectionA   ;                                                                     ;                          ; wide              
                                   ; MiddleSectionB   ;                                                                     ;                          ; wide              
       
      INSERT_UPDATE CMSParagraphComponent; $contentCV[unique=true]; uid[unique=true]          ; name               ; content
                                         ;                        ; ExampleParagraphComponentA; Example Paragraph A; Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                                         ;                        ; ExampleParagraphComponentB; Example Paragraph B; Sed metus nisl, vehicula suscipit elit egestas, molestie imperdiet ex. Donec vulputate rhoncus massa et cursus. Suspendisse turpis nulla, dictum vitae purus quis, suscipit pulvinar ipsum. Mauris elit leo, ultricies mollis molestie in, interdum non dolor. Mauris consequat elit luctus nibh vehicula, sed maximus nibh placerat.                 
       
      INSERT_UPDATE SimpleBannerComponent; $contentCV[unique=true]; uid[unique=true]      ; name                    ; urlLink
                                         ;                        ; ExampleBannerComponent; Example Banner Component; https://cx.sap.com/
       
      INSERT_UPDATE ContentSlot; $contentCV[unique=true]; uid[unique=true]     ; name                    ; active; cmsComponents(uid,$contentCV)
                               ;                        ; ExampleBannerSlot    ; Example Banner Slot     ; true  ; ExampleBannerComponent
                               ;                        ; ExampleParagraphSlotA; Example Paragraph Slot A; true  ; ExampleParagraphComponentA
                               ;                        ; ExampleParagraphSlotB; Example Paragraph Slot B; true  ; ExampleParagraphComponentB
       
      INSERT_UPDATE ContentSlotForTemplate; $contentCV[unique=true]; uid[unique=true]                 ; position[unique=true]; pageTemplate(uid,$contentCV)[unique=true][default='ExamplePageTemplate']; contentSlot(uid,$contentCV)[unique=true]; allowOverwrite
                                          ;                        ; SiteLogo-ExamplePage             ; SiteLogo             ;                                                                         ; SiteLogoSlot                            ; true
                                          ;                        ; HomepageLink-ExamplePage         ; HomepageNavLink      ;                                                                         ; HomepageNavLinkSlot                     ; true
                                          ;                        ; NavigationBar-ExamplePage        ; NavigationBar        ;                                                                         ; NavigationBarSlot                       ; true
                                          ;                        ; MiniCart-ExamplePage             ; MiniCart             ;                                                                         ; MiniCartSlot                            ; true
                                          ;                        ; Footer-ExamplePage               ; Footer               ;                                                                         ; FooterSlot                              ; true
                                          ;                        ; HeaderLinks-ExamplePage          ; HeaderLinks          ;                                                                         ; HeaderLinksSlot                         ; true
                                          ;                        ; SearchBox-ExamplePage            ; SearchBox            ;                                                                         ; SearchBoxSlot                           ; true
                                          ;                        ; TopHeaderSlot-ExamplePage        ; TopHeaderSlot        ;                                                                         ; TopHeaderSlot                           ; true
                                          ;                        ; BottomHeaderSlot-ExamplePage     ; BottomHeaderSlot     ;                                                                         ; BottomHeaderSlot                        ; true
       
      INSERT_UPDATE ContentSlotForPage; $contentCV[unique=true]; uid[unique=true]                 ; position[unique=true]; page(uid,$contentCV)[unique=true][default='examplePage']; contentSlot(uid,$contentCV)[unique=true]
                                      ;                        ; ExampleBannerSlot-ExamplePage    ; TopSection           ;                                                         ; ExampleBannerSlot
                                      ;                        ; ExampleParagraphSlotA-ExamplePage; MiddleSectionA       ;                                                         ; ExampleParagraphSlotA
                                      ;                        ; ExampleParagraphSlotB-ExamplePage; MiddleSectionB       ;                                                         ; ExampleParagraphSlotB
       
       
       
      INSERT_UPDATE Media; $contentCV[unique=true]; code[unique=true]             ; @media[translator=de.hybris.platform.impex.jalo.media.MediaDataTranslator]; mime[default='image/jpeg']; folder(qualifier)[default='images']; altText
                         ;                        ; exampleBanner_800x150_800W.jpg; $siteResource/images/banners/example/exampleBanner_800x150_800W.jpg       ;                           ;                                    ; "SAP Customer Experience"
       
      UPDATE SimpleBannerComponent; $contentCV[unique=true]; uid[unique=true]      ; $picture
                                  ;                        ; ExampleBannerComponent; exampleBanner_800x150_800W.jpg
    2. Adding examplePage.jsp file representing desktop page view to examplestorefront\web\webroot\WEB-INF\views\desktop\pages\example folder

      examplePage.jsp
      <%@ page trimDirectiveWhitespaces="true" %>
      <%@ taglib prefix="template" tagdir="/WEB-INF/tags/desktop/template" %>
      <%@ taglib prefix="cms" uri="http://hybris.com/tld/cmstags" %>
      <%@ taglib prefix="common" tagdir="/WEB-INF/tags/desktop/common" %>
      <%@ taglib prefix="example" tagdir="/WEB-INF/tags/desktop/example" %>
       
       
      <template:page pageTitle="${pageTitle}">
          <div id="globalMessages">
              <common:globalMessages/>
          </div>
       
          <cms:pageSlot position="TopSection" var="feature" element="div" class="top-section">
                  <cms:component component="${feature}" />
          </cms:pageSlot>
       
          <div class="span-24 middle-section">
              <cms:pageSlot position="MiddleSectionA" var="feature" element="div" class="span-12">
                  <cms:component component="${feature}" />
              </cms:pageSlot>
       
              <cms:pageSlot position="MiddleSectionB" var="feature" element="div" class="span-12 last">
                  <cms:component component="${feature}" />
              </cms:pageSlot>
          </div>
       
          <div class="span-24">
              <example:toggle/>
          </div>
      </template:page>
    3. Adding custom tag file toggle.tag to examplestorefront\web\webroot\WEB-INF\tags\desktop\example folder

      toggle.tag
      <%@ tag body-content="empty" trimDirectiveWhitespaces="true" %>
      <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
       
      <div class="example-toggle-container">
          <span id="js-example-toggle" class="example-toggle"><spring:theme code="example.toggle"/></span>
      </div>
    4. Adding custom JavaScript file example.js to examplestorefront\web\webroot\_ui\desktop\common\js folder

      example.js
      example = {
          bindAll: function ()
          {
              example.toggleMiddleSection();
          },
       
          toggleMiddleSection: function ()
          {
              var middleSection = $('.middle-section');
              $('#js-example-toggle').click(function (e)
              {
                  middleSection.slideToggle();
              });
          }
      };
       
      $(document).ready(function ()
      {
          example.bindAll();
      });
    5. Updating examplestorefront\web\webroot\WEB-INF\tags\desktop\template\compressible\js.tag file to embed newly created JavaScript file

      <script type="text/javascript" src="${commonResourcePath}/js/example.js"></script>
    6. Adding custom example.css stylesheet to examplestorefront\web\webroot\_ui\desktop\common\css folder

      example.css
      .top-section {
          margin: 5px 0;
      }
       
      .top-section:hover {
          opacity: 0.7;
      }
       
      .middle-section {
          margin: 20px;
      }
       
      .example-toggle-container {
          text-align: center;
          margin: 10px 0;
      }
       
      .example-toggle {
          display: inline-block;
          padding: 10px;
          background-color: #F9B732;
          color: #000;
          border: 2px solid #000;
      }
       
      .example-toggle:hover {
          color: #F9B732;
          background-color: #000;
      }
    7. Updating examplestorefront\web\webroot\WEB-INF\tags\desktop\template\compressible\css.tag file to embed newly created CSS file

      <link rel="stylesheet" type="text/css" media="all" href="${commonResourcePath}/css/example.css"/>
  3. Adding elements which will be used for mobile UI experience:
    1. Importing IMPEX containing new page template, content page, CMS components, content slots and media items

      IMPEX with CMS content for mobile user experience
      INSERT_UPDATE PageTemplate; $contentCV[unique=true]; uid[unique=true]         ; name                        ; frontendTemplateName; restrictedPageTypes(code); active[default=true]
                                ;                        ; MobileExamplePageTemplate; Mobile Example Page Template; example/examplePage ; ContentPage
       
      INSERT_UPDATE ContentPage; $contentCV[unique=true]; uid[unique=true] ; name                       ; masterTemplate(uid,$contentCV); label      ; defaultPage[default='false']; approvalStatus(code)[default='approved']; homepage[default='false']; restrictions(uid,$contentCV)[default='MobileExperienceRestriction']; onlyOneRestrictionMustApply[default='false']
                               ;                        ; mobileExamplePage; Mobile Example Content Page; MobileExamplePageTemplate     ; examplePage;                             ;                                         ;                          ;                                                                    ;
       
      INSERT_UPDATE ContentSlotName; name[unique=true]; template(uid,$contentCV)[unique=true][default='MobileExamplePageTemplate']; validComponentTypes(code); compTypeGroup(code)
                                   ; SiteLogo         ;                                                                           ;                          ; logo
                                   ; SearchBox        ;                                                                           ;                          ; searchbox
                                   ; NavigationBar    ;                                                                           ;                          ; navigation
                                   ; NavigationMenuBar;                                                                           ;                          ; navigation
                                   ; Footer           ;                                                                           ;                          ; footer
                                   ; NavContent       ;                                                                           ; FooterComponent          ; navigation
                                   ; TopHeaderSlot    ;                                                                           ;                          ; mobile
                                   ; NavigationSlot   ;                                                                           ;                          ; mobile
                                   ; BottomHeaderSlot ;                                                                           ;                          ; mobile
                                   ; TopSection       ;                                                                           ;                          ; mobile
                                   ; MiddleSectionA   ;                                                                           ;                          ; mobile
                                   ; MiddleSectionB   ;                                                                           ;                          ; mobile
       
      INSERT_UPDATE CMSParagraphComponent; $contentCV[unique=true]; uid[unique=true]                ; name                      ; content
                                         ;                        ; MobileExampleParagraphComponentA; Mobile Example Paragraph A; Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                                         ;                        ; MobileExampleParagraphComponentB; Mobile Example Paragraph B; Sed metus nisl, vehicula suscipit elit egestas, molestie imperdiet ex. Donec vulputate rhoncus massa et cursus. Suspendisse turpis nulla, dictum vitae purus quis, suscipit pulvinar ipsum. Mauris elit leo, ultricies mollis molestie in, interdum non dolor. Mauris consequat elit luctus nibh vehicula, sed maximus nibh placerat.
       
      INSERT_UPDATE SimpleBannerComponent; $contentCV[unique=true]; uid[unique=true]            ; name                           ; urlLink
                                         ;                        ; MobileExampleBannerComponent; Mobile Example Banner Component; https://cx.sap.com/
       
      INSERT_UPDATE ContentSlot; $contentCV[unique=true]; uid[unique=true]           ; name                           ; active; cmsComponents(uid,$contentCV)
                               ;                        ; MobileExampleBannerSlot    ; Mobile Example Banner Slot     ; true  ; MobileExampleBannerComponent
                               ;                        ; MobileExampleParagraphSlotA; Mobile Example Paragraph Slot A; true  ; MobileExampleParagraphComponentA
                               ;                        ; MobileExampleParagraphSlotB; Mobile Example Paragraph Slot B; true  ; MobileExampleParagraphComponentB
       
      INSERT_UPDATE ContentSlotForTemplate; $contentCV[unique=true]; uid[unique=true]                   ; position[unique=true]; pageTemplate(uid,$contentCV)[unique=true][default='MobileExamplePageTemplate']; contentSlot(uid,$contentCV)[unique=true]; allowOverwrite
                                          ;                        ; MobileSiteLogo-ExamplePage         ; SiteLogo             ;                                                                               ; MobileSiteLogoSlot                      ; true
                                          ;                        ; MobileSearchBox-ExamplePage        ; SearchBox            ;                                                                               ; MobileSearchBoxSlot                     ; true
                                          ;                        ; MobileHomepageLink-ExamplePage     ; HomepageNavLink      ;                                                                               ; MobileHomepageNavLinkSlot               ; true
                                          ;                        ; MobileNavigationBar-ExamplePage    ; NavigationBar        ;                                                                               ; MobileNavigationBarSlot                 ; true
                                          ;                        ; MobileNavigationMenuBar-ExamplePage; NavigationMenuBar    ;                                                                               ; MobileNavigationMenuBarSlot             ; true
                                          ;                        ; MobileFooter-ExamplePage           ; Footer               ;                                                                               ; MobileFooterSlot                        ; true
                                          ;                        ; MobileNavContent-ExamplePage       ; NavContent           ;                                                                               ; MobileNavContentSlot                    ; true
                                          ;                        ; MobileTopHeaderSlot-ExamplePage    ; TopHeaderSlot        ;                                                                               ; MobileTopHeaderSlot                     ; true
                                          ;                        ; MobileNavigationSlot-ExamplePage   ; NavigationSlot       ;                                                                               ; MobileNavigationSlot                    ; true
                                          ;                        ; MobileBottomHeaderSlot-ExamplePage ; BottomHeaderSlot     ;                                                                               ; MobileBottomHeaderSlot                  ; true
       
      INSERT_UPDATE ContentSlotForPage; $contentCV[unique=true]; uid[unique=true]                       ; position[unique=true]; page(uid,$contentCV)[unique=true][default='mobileExamplePage']; contentSlot(uid,$contentCV)[unique=true]
                                      ;                        ; MobileExampleBannerSlot-ExamplePage    ; TopSection           ;                                                               ; MobileExampleBannerSlot
                                      ;                        ; MobileExampleParagraphSlotA-ExamplePage; MiddleSectionA       ;                                                               ; MobileExampleParagraphSlotA
                                      ;                        ; MobileExampleParagraphSlotB-ExamplePage; MiddleSectionB       ;                                                               ; MobileExampleParagraphSlotB
       
       
      INSERT_UPDATE Media; $contentCV[unique=true]; code[unique=true]             ; @media[translator=de.hybris.platform.impex.jalo.media.MediaDataTranslator]; mime[default='image/jpeg']; folder(qualifier)[default='images']; altText
                         ;                        ; exampleBanner_350x100_350W.jpg; $siteResource/images/banners/example/exampleBanner_350x100_350W.jpg       ;                           ;                                    ; "SAP Customer Experience"
       
      UPDATE SimpleBannerComponent; $contentCV[unique=true]; uid[unique=true]            ; $picture
                                  ;                        ; MobileExampleBannerComponent; exampleBanner_350x100_350W.jpg
    2. Adding examplePage.jsp file representing mobile page view to examplestorefront\web\webroot\WEB-INF\views\mobile\pages\example folder

      examplePage.jsp
      <%@ page trimDirectiveWhitespaces="true"%>
      <%@ taglib prefix="template" tagdir="/WEB-INF/tags/mobile/template"%>
      <%@ taglib prefix="nav" tagdir="/WEB-INF/tags/mobile/nav"%>
      <%@ taglib prefix="cms" uri="http://hybris.com/tld/cmstags"%>
      <%@ taglib prefix="example" tagdir="/WEB-INF/tags/mobile/example" %>
      <template:page pageTitle="${pageTitle}">
          <jsp:body>
              <div id="globalMessages">
                  <common:globalMessages />
              </div>
       
              <cms:pageSlot position="TopSection" var="feature" element="div" class="top-section">
                  <cms:component component="${feature}"/>
              </cms:pageSlot>
       
              <div class="middle-section">
                  <cms:pageSlot position="MiddleSectionA" var="feature">
                      <cms:component component="${feature}"/>
                  </cms:pageSlot>
       
                  <cms:pageSlot position="MiddleSectionB" var="feature">
                      <cms:component component="${feature}"/>
                  </cms:pageSlot>
              </div>
       
              <example:toggle/>
       
          </jsp:body>
      </template:page>
      <nav:popupMenu />
    3. Adding custom tag file toggle.tag to examplestorefront\web\webroot\WEB-INF\tags\mobile\example folder

      <%@ tag body-content="empty" trimDirectiveWhitespaces="true" %>
      <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
       
      <div class="example-toggle-container">
          <span id="js-example-toggle" class="example-toggle"><spring:theme code="example.toggle"/></span>
      </div>

    4. Adding custom JavaScript file example.js to examplestorefront\web\webroot\_ui\mobile\common\js folder

      example.js
      example = {
       
          bindAll: function ()
          {
              example.toggleMiddleSection();
          },
       
          toggleMiddleSection: function ()
          {
              var middleSection = $('.middle-section');
              $('#js-example-toggle').click(function (e)
              {
                  middleSection.slideToggle();
              });
          }
      };
       
      $(document).ready(function ()
      {
          example.bindAll();
      });
    5. Updating examplestorefront\web\webroot\WEB-INF\tags\mobile\template\compressible\js.tag file to embed newly created JavaScript file

      <script type="text/javascript" src="${commonResourcePath}/js/example.js"></script>



    6. Adding custom example.css stylesheet to examplestorefront\web\webroot\_ui\mobile\common\css folder

      example.css
      .top-section {
          margin: 5px 0;
      }
       
      .top-section:hover {
          opacity: 0.7;
      }
       
      .middle-section {
          margin: 10px;
      }
       
      .example-toggle-container {
          text-align: center;
      }
       
      .example-toggle {
          display: inline-block;
          padding: 5px;
          background-color: #F9B732;
          color: #000;
          border: 2px solid #000;
      }
       
      .example-toggle:hover {
          color: #F9B732;
          background-color: #000;
      }
    7. Updating examplestorefront\web\webroot\WEB-INF\tags\mobile\template\compressible\css.tag file to embed newly created CSS file

      <link type="text/css" rel="stylesheet" media="screen" href="${commonResourcePath}/css/example.css"/>

  4. Adding ExamplePageController.java page controller

    ExamplePageController.java
    @Controller
    @Scope("tenant")
    @RequestMapping("/example")
    public class ExamplePageController extends AbstractPageController {
        private static final String EXAMPLE_PAGE = "examplePage";
     
        @RequestMapping(method = RequestMethod.GET)
        public String getExample(final Model model) throws CMSItemNotFoundException
        {
            final ContentPageModel exampleCMSPage = getContentPageForLabelOrId(EXAMPLE_PAGE);
            storeCmsPageInModel(model, exampleCMSPage);
            setUpMetaDataForContentPage(model, exampleCMSPage);
            return getViewForPage(model);
        }
    }
  5. Updating base_xx.properties language files in examplestorefront\web\webroot\WEB-INF\messages directory with custom messages

After a platform build and importing IMPEX resources, the mobile/desktop UI experience storefronts are accessible when visiting the site using given device. The images below show what the pages look like on both the mobile and desktop UI experiences:

The content layout on mobile page is different than the layout on desktop page – in this example on small screens there is one column of text and on larger screens there are two columns of text. The content is also different – in this case the displayed banner is different depending on the UI experience. There are also differences in applied styles - different toggle element and paragraph paddings.

General Migration Approach

Because of differences in structure of storefront extensions between platform versions 5.3.x and 6.7.x, the general approach to migrating the storefront can be divided into a few main steps:

  1. Determining the level of customization and performing analysis of implemented storefront features source files for both desktop and mobile UI experiences, such as JSP views, tags and fragments, controllers, CSS stylesheets, JavaScript files and CMS content in IMPEX files.
  2. Generating new storefront extension by running ant modulegen or ant extgen task in the new platform version.
  3. Basing on the analysis from first point, the custom files and resources have to be extracted, placed in the respective directories of new generated storefront extension, and adjusted to requirements of new responsive UI experience if needed.

Migration of Implemented Features

This section describes the process of migrating the previously described custom storefront features. As mentioned before, the storefront is migrated from platform 5.3.x version to 6.7.x version. To perform the migration of implemented custom featured following steps have to be performed:

  1. Generating a new set of custom extensions basing on default B2C Accelerator by invoking ant modulegen task.
  2. Creating new custom theme exampletheme, basing on existing alpha theme. For more information, see Creating New Themes.
  3. Because the responsive storefront does not require creating separate CMS pages for different UI experiences, only one CMS page has to be migrated. In this case, the mobile-related CMS content does not need to be included and the remaining desktop-related content is to be taken as basis for creating CMS content for responsive storefront. To enable responsiveness few modifications have to be added to these IMPEX scripts.

    Firstly instead of using SimpleBannerComponent a new SimpleResponsiveBannerComponent can be used. This component allows to map media files to media formats, which are specific to a responsive UI experience. Secondly, a mediaFormat attribute has to be specified in Media components. Last change in IMPEX is to add new MediaContainer component and add both banner images to it. These three changes are shown in code block below.

    INSERT_UPDATE Media; mediaFormat(qualifier); $contentCV[unique=true]; code[unique=true]     ; @media[translator=de.hybris.platform.impex.jalo.media.MediaDataTranslator][forceWrite=true]; mime[default='image/jpeg']; realfilename          ; folder(qualifier)[default='images']; altText
                       ;
     widescreen            ;                        ; 
    exampleBanner_800W.jpg; 
    $siteResource/images/banners/example/exampleBanner_800x150_800W.jpg                       
     ;                           ; 
    exampleBanner_800W.jpg;                                    ; "SAP Customer Experience"
                       ;
     desktop               ;                        ; 
    exampleBanner_350W.jpg; 
    $siteResource/images/banners/example/exampleBanner_350x100_350W.jpg                       
     ;                           ; 
    exampleBanner_350W.jpg;                                    ; "SAP Customer Experience"
     
    INSERT_UPDATE MediaContainer; qualifier[unique=true]        ; $medias                                      ; $contentCV[unique=true]
                                ; example-banner-media-container; exampleBanner_350W.jpg,exampleBanner_800W.jpg
     
    INSERT_UPDATE SimpleResponsiveBannerComponent; $contentCV[unique=true]; uid[unique=true]      ; name                    ; urlLink            ; $mediaContainer
                                                 ;                        ; ExampleBannerComponent; Example Banner Component; https://cx.sap.com/; example-banner-media-container
  4. As there is only one CMS page to migrate, also only one JSP view has to be migrated to the target version. This can be done by copying examplePage.jsp from examplestorefront\web\webroot\WEB-INF\views\desktop\pages\example folder to examplestorefront\web\webroot\WEB-INF\views\responsive\pages\example folder in new platform. Additionally, some changes have to be made to the file itself. Instead of using span-12 and span-24 CSS classes, the Bootstrap grid system should be used. This provides the responsive behaviour of page elements. Also values of tagdir attributes in taglib elements have to be adjusted to point to responsive directories. If there were more custom JSP views for either pages or CMS components, all of them have to be verified and manually adjusted to enable responsive behaviour. The code block below shows how the original examplePage.jsp was modified to work as a responsive page:

    examplePage.jsp
    <%@ page trimDirectiveWhitespaces="true" %>
    <%@ taglib prefix="template" tagdir="/WEB-INF/tags/responsive/template" %>
    <%@ taglib prefix="cms" uri="http://hybris.com/tld/cmstags" %>
    <%@ taglib prefix="common" tagdir="/WEB-INF/tags/responsive/common" %>
    <%@ taglib prefix="example" tagdir="/WEB-INF/tags/responsive/example" %>
     
     
    <template:page pageTitle="${pageTitle}">
        <div id="globalMessages">
            <common:globalMessages/>
        </div>
        <cms:pageSlot position="TopSection" var="feature" element="div" class="top-section">
            <cms:component component="${feature}" />
        </cms:pageSlot>
            <div class="row">
                <div class="col-md-6">
                    <cms:pageSlot position="MiddleSectionA" var="feature" element="div" class="middle-section">
                        <cms:component component="${feature}" />
                    </cms:pageSlot>
                </div>
                <div class="col-md-6">
                    <cms:pageSlot position="MiddleSectionB" var="feature" element="div" class="middle-section">
                        <cms:component component="${feature}" />
                    </cms:pageSlot>
                </div>
            </div>
            <div class="row">
                <div class="col-xs-12">
                    <example:toggle/>
                </div>
            </div>
        </div>
    </template:page>
  5. Copying file custom tag file toggle.tag from examplestorefront\web\webroot\WEB-INF\tags\desktop\example folder to examplestorefront\web\webroot\WEB-INF\tags\responsive\example folder in the target versionof your code. In this case no additional modifications are needed, as both original tags from mobile and desktop UI experiences are identical. If these tags were different, manual adjustments would be needed to provide responsiveness. If there were any other custom tags, these should be also copied to responsive folder and adjusted manually if needed.
  6. Copying custom JavaScript file example.js from examplestorefront\web\webroot\_ui\desktop\common\js folder toexamplestorefront\web\webroot\WEB-INF\_ui-src\responsive\lib\ybase-0.1.0 folder in new platform. In this case both original JavaScript files are identical, so there is no need for additional customization. In case that there are differences between JavaScript files in mobile and desktop directories, manual modifications have to be done to recreate the original behaviour. Beside copying the JavaScript files to new platform, these files have also to be embedded. This can be done by updating javaScript.tag file by adding line as shown below.

    <script type="text/javascript" src="${commonResourcePath}/js/example.js"></script>

  7. Creating a new example.less file in your target code's examplestorefront\web\webroot\WEB-INF\_ui-src\responsive\themes\exampletheme\less folder (custom generated theme directory). Because the original example.css files in mobile and desktop folders are not identical, so there is a need to combine these two files into one stylesheet that provides the original styling. In this case, the recommended practice is to use features provided by LESS preprocessor, such as declaring variables or chaining inner selectors. Variables should be declared in separate file, for example examplestorefront\web\webroot\WEB-INF\_ui-src\responsive\themes\exampletheme\less\theme-variables.less. Additionally media queries should be used when different views require different styling. The LESS variables declarations and new example.less file are shown below.

    @toggle-primary:    #F9B732;
    @toggle-secondary:  #000000;

    example.less
    .top-section {
        margin: 5px 0;
        &:hover {
            opacity: 0.7;
        }
    }
     
    .middle-section {
        margin: 10px;
        @media screen and (min-width: @screen-desktop) {
            margin: 20px;
        }
    }
     
    .example-toggle-container {
        text-align: center;
        margin: 10px 0;
    }
     
    .example-toggle {
        display: inline-block;
        padding: 5px;
        background-color: @toggle-primary;
        color: @toggle-secondary;
        border: 2px solid @toggle-secondary;
        &:hover {
            color: @toggle-primary;
            background-color: @toggle-secondary;
        }
        @media screen and (min-width: @screen-desktop) {
            padding: 10px;
        }
    }


    Additionally the new LESS files must be imported by updating custom theme examplestorefront\web\webroot\WEB-INF\_ui-src\responsive\themes\exampletheme\less\style.less file.

    @import "example.less";

  8. Copying custom messages from old platform to base_xx.properties language files in examplestorefront\web\webroot\WEB-INF\messages directory in new platform.

    example.toggle = Hide/show text

The new responsive website build process requires generating a _ui folder from files in _ui-src folder. This can be done by executing ant examplestorefront_compileuisrc task. For more information, see Responsive Website Build Process.

After platform build and importing IMPEX resources, the responsive storefronts are accessible when the site is visited. The images below show what the migrated pages now look like on mobile and desktop screens.

Quality

The exploration tests should be performed to verify if the storefront migration was successful. During the tests the page should be accessed by using devices in different screen sizes. The browser developer tools can be used to check how the page looks on different devices. However, if it's possible the page should be checked using phone, tablet, or other, to confirm that the styles and scripts are working correctly on the particular device. Also the behaviour of elements should be tested and the appearance should be examined to confirm that the scripts and styling is properly migrated and adjusted to responsive storefront requirements.


Overlay