Technical Blog

1 Post tagged with the directory tag

      

Introduction

Asset management has changed significantly in EP 6.1 to make deployment of multiple stores easier. With EP 6.1, multiple stores may be run in a single WAR file, hence there is no need to copy WAR instances to deploy a new store. Asset types, which include images, CSS, JavaScript, email templates, storefront velocity templates, VM_global_libraries and Message Resource property files, have been moved out of the WAR deployment location and into a new directory elsewhere on the file system. The previous structure of the assets directory has also changed.

 

The assets root directory structure is as follows:

 

- assets

+ cmassets

+ digitalassets

+ images

+ import

+ storeassets

+ themes

 

The absolute path for assets is specified in your deployment's COMMERCE/SYSTEM/ASSETS/assetLocation setting. EP6.1 also introduces the "Settings Framework," a new component that contains system and store configuration settings that used to be captured in commerce-config.xml and other files. The COMMERCE/SYSTEM/ASSETS/assetLocation setting value must be configured before you start your storefront application to point at your assets root directory, for example c:\assets or /opt/assets.

 

  • The cmassets directory is also new in EP 6.1 and contains the Commerce Manager specific files, such as user account email templates and the import report email template.
  • The digitalassets directory has been around for several releases and still contains the downloadable digital product files.
  • The images directory is also not new and contains your product display images.
  • The import directory was introduced in EP 6.0 and contains all import CSV files used by the Commerce Manager. Please note that these files are not used by the Import/Export tool, which is a separate component.
  • The storeassets directory is new in EP 6.1 and only contains the PowerReviews required by each store. This directory is specific to each store, but does not form part of a theme.
  • The themes directory is new and serves as the root directory for all themes used by your stores. Themes are used to define the look and feel of stores in EP. You can create multiple themes and associate these with one or more stores. You can also customize theme elements (images, CSS, JavaScript) for individual stores without affecting other stores that use the same theme.

 

 

A theme consists of a set of Velocity templates and resources required to display a storefront (stylesheets, images, properties files, etc.). Each theme is stored in its own directory under the assets/themes directory:

 

- assets

+ cmassets

+ digitalassets

+ images

+ import

+ storeassets

- themes

  + electronics

  + mytheme1

  + mytheme2

  + ...

 

Each theme must contain a default directory. This directory contains the templates and the template-resources directories. The templates directory contains the Velocity templates used by the Velocity Engine to render HTML pages. The template-resources directory contains the stylesheets, Javascript and image files referred to by the rendered HTML pages.

 

- assets

+ cmassets

+ digitalassets

+ images

+ import

+ storeassets

- themes

  - electronics

    - default

      - template-resources

        + images

        + js

        + stylesheet

      - templates

        - velocity

          + index.vm

Within these directories, you can use any directory structure you want to organize files, but keep in mind the file-based fallback mechanism used within themes.

 

 

Themes can be customized to suit the needs of individual stores. To customize a theme for a specific store, create a directory under the theme and set the directory name to the store code. For example, to customize mytheme1 for the SNAPITUP store, create a directory named SNAPITUP under mytheme1. The directory structure should look similar to the following:

 

- assets

+ themes

- mytheme1

  + default

  + SNAPITUP

 

In the store-specific directory, only create copies of the files that you want to customize. The copies must exist in the same relative directory structure within the store-specific directory. For example, to customize the mytheme1/default/template-resources/images/image-not-available.png image for the SNAPITUP store, place the custom version of image-not-available.png in mytheme1/SNAPITUP/template-resources/images.

 

- assets

- themes

  - mytheme1

    - default

      - template-resources

        - images

          + image-not-available.png (default image)

          + ... all other shared images

    - SNAPITUP

      - template-resources

        - images

          + image-not-available.png (store overriding image)

 

It is not necessary to copy the entire contents of the default directory into the store-specific directory. You only need to include copies of the files that you are customizing. The application looks for files in the store-specific directory first; if it does not find a file in the store-specific directory, it then looks for it in the default directory. In other words, your customized copy of the file or image acts as an override for the default file or image. This file-based overriding mechanism is used for images, stylesheet, JavaScript and Velocity template files.  Access to these resources is handled by resource controllers, which in turn use resource retrieval strategies for greater flexibility.

 

WEB-INF/conf/spring/web/url-mapping.xml

<bean id="SimpleUrlHandlerMapping"

    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

  <property name="mappings">

      <props>

      <prop key="/images/**/*">storeThemeAssetResourceController</prop>

      <prop key="/stylesheet/**/*">storeThemeAssetResourceController</prop>

      <prop key="/js/**/*">storeThemeAssetResourceController</prop>

      </props>

  </property>

</bean>

<!-- Resource controllers for resource retrieval -->

<bean id="storeThemeAssetResourceController"

    class="com.elasticpath.sfweb.controller.impl.AssetResourceControllerImpl"

    parent="abstractEpController">

  <property name="resourceRetrievalStrategy"

            ref="storeThemeAssetRetrievalStrategy"/>

</bean>

Message Sources use a property based overriding mechanism, as opposed to the file based overriding for other types of assets like images. Message Sources are a collection of property files, which associate message keys to message text in different languages. Take, for example, the globals.firstname property key that's located in 2 files, one referencing the English message and the other the French message.

- assets

- themes

  - mytheme1

    - default

      - templates

        + globals.properties  : globals.firstname=First Name

        + globals_fr.properties: globals.firstname=Prenom

 

To override the French globals.firstname message for the SNAPITUPUK store, one need only override one property, not the entire property file. In this case the global_fr.properties file need only contain a single property entry for globals.firstname.

 

- assets

- themes

  - mytheme1

    - default

    - templates

        + globals_fr.properties: globals.firstname=Prenom (default)

    - SNAPITUP

      - templates

        + globals_fr.properties: globals.firstname=Prénom (overriding)

 

In fact, the file name need not even start with "globals" as all properties are loaded into a collection at which point file names are no longer relevant. The only requirement is that it contain the language code. For example, having the globals.firstname property override in a file named no-name-in-particular_fr.properties, will have the same effect. If no language code is present, English is assumed.  For reference, see the Message Source configuration in the Storefront and Commerce Manager web applications.

 

WEB-INF/conf/spring/views/velocity/velocity.xml

<bean id="messageSource"

    class="com.elasticpath.commons.util.impl.StoreThemeMessageSource" >

  <property name="messageSourceCache">

      <ref bean="messageSourceCache"/>

  </property>

  <property name="storeConfig">

      <ref bean="threadLocalStorage"/>

  </property>

  <property name="globalMessageSource">

      <ref bean="globalMessageSource"/>

  </property>

  <!-- True if you want missing messages to show up

        as just the key used to look for them. e.g. user.firstname.

        False will allow exception to be thrown, and stop template render.

  -->

  <property name="useCodeAsDefaultMessage">

      <value>true</value>

  </property>

</bean>

 


Using Store Editor

 

You can select the theme using the new store editor:

1.  In Commerce Manager, choose *Activity*->*Configuration*.

2.  Under *Stores*, click *Stores*.

3.  Select the store, then click *Edit Store*.

4.  Click the *Theme* tab.

5.  In the _Theme_ box, enter the name of the theme folder. For example, if the theme folder is C:/Program Files/Apache Software Foundation/apache-tomcat-5.5.26/assets/themes/mytheme1, enter mytheme1.

6.  In the Commerce Manager toolbar, click *Save*.


Using Advanced Setting Configuration

 

By default, the demo store is mapped to the electronics theme. To change the theme of a store:

 

1.  In Commerce Manager, choose Activity -> Configuration.

2.  Under System Administration, click System Configuration.

3.  In the Property Name list, select COMMERCE/STORE/theme.

4.  Click New (next to the Defined Values list).

5.  Set the values as follows:

·        Context: The store code. For example, for the SnapItUp demo store, the store code is SNAPITUP.

·        Value: The name of the theme folder. For example, if the theme folder is C:/Program Files/Apache Software Foundation/apache-tomcat-5.5.26/assets/themes/mytheme1, enter mytheme1.

6.  Click Save.

 

 

During the development of EP 6.1 it was clear that we had to find a way to make the Velocity engine's VM_global_library store specific since stores do not always share the same library macros.  In EP 6.0, Spring instantiated a VelocityEngine bean directly to inject into the onePageHelper bean, as OnePageHelperImpl requires a Velocity engine for some functionality. This bean is also injected into the velocityConfig bean which is what the VelocityView class uses to get the Velocity engine (it is effectively a factory). The VelocityView class retrieves the Velocity engine once, but we want it to get the appropriate store engine each time the view is asked to render a template.

 

Among other smaller changes, the following classes needed to be added in EP 6.1 to correct the Velocity Engine behavior.

 

<bean id="viewResolver"

class="com.elasticpath.sfweb.view.velocity.StoreVelocityViewResolver">

  <property name="viewClass">

<value>com.elasticpath.sfweb.view.velocity.StoreVelocityViewImpl</value>

  </property>

  <property name="velocityConfigurer" ref="velocityConfigurer"/>

  ...

</bean>

<bean id="velocityConfigurer"

    class="com.elasticpath.sfweb.view.velocity.StoreVelocityConfigurer">

  <property name="storeConfig" ref="threadLocalStorage"/>

  <property name="velocityPropertiesMap" ref="velocityPropertiesMap"/>

</bean>

 

StoreVelocityConfigurer

 

This is a subclass of VelocityConfigurer which keeps a Map of velocity engines keyed by store code. This class just overrides the getVelocityEngine() method and uses an injected store config to retrieve the appropriate VelocityEngine instance from the map. It will call createVelocityEngine() if there is no value for the store currently in the map.

 

StoreVelocityViewResolver

 

This is a subclass of VelocityViewResolver which is store aware. It has setters for a StoreConfig and VelocityConfigurer which will typically be injected by Spring. This class overrides the buildView method and passes the store config and velocity configurer through to the StoreVelocityViewImpl class so it can render the store-specific view.  The old "global" WEB-INF/VM_global_library.vm library has been removed. You now have a VM_global_library in the templates/velocity directory of a theme or store-specific theme override. This will fall back exactly like the other assets.

 

- assets

- themes

  - mytheme1

    - default

      - templates

        - velocity

          + VM_global_library.vm (default fall-back)

    - SNAPITUP

      - templates

        - velocity

            + VM_global_library.vm (store specific override)

 

Store Specific Report Templates

 

Report Design files (*.rptdesign) are typically bundled as part of the Commerce Manager plugin. Packing Slip reports are store specific though, and had to be moved out of the plugin and uses the theme to take advantage of the file-based overriding mechanism.

 

- assets

- themes

  - mytheme1

    - default

      - templates

        - printartifacts

          + packing_slip.rptdesign (default report design)

    - SNAPITUP

      - templates

        - printartifacts

            + packing_slip.rptdesign (store specific override)

 

 

The com.elasticpath.cmweb.controller.impl.CacheInvalidationControllerImpl defined in the CM Server is useful to invalidate caches of various types based on an invalidation strategy. The default configuration, as displayed below and duplicated in the Storefront, uses the TriggeredCacheInvalidationStrategy to invalidate the Velocity engines and message resources.

 

com.elasticpath.cm/WEB-INF/conf/spring/web/url-mapping.xml:

<prop key="/invalidate-cache.ep">cacheInvalidationController</prop>

<bean id="cacheInvalidationController"

    class="com.elasticpath.cmweb.controller.impl.CacheInvalidationControllerImpl">

  <property name="cacheInvalidationStrategy"

            ref="triggeredCacheInvalidationStrategy" />

</bean>

com.elasticpath.cm/WEB-INF/conf/spring/service/serviceCM.xml:

<bean id="triggeredCacheInvalidationStrategy"

class="com.elasticpath.commons.util.impl.TriggeredCacheInvalidationStrategyImpl">

  <property name="invalidatableCaches">

      <bean class="java.util.HashSet">

          <constructor-arg>

              <set>

                  <ref bean="velocityEngineFactory"/>

                  <ref bean="messageSourceCache"/>

              </set>

          </constructor-arg>

      </bean>

  </property>

</bean>

Be sure to have the invalidation URL secured, as it will cause a hit in performance every time the velocity engine is recreated, which reloads all the message property files.

 

 

For information on configuring PowerReviews in Elastic Path, see the PowerReviews Wiki page at https://wiki.elasticpath.com/display/EP61DEPLOY/5+-+PowerReviews+(optional) in the Deployment Guide. For information on the Power Reviews system, see the PowerReviews website at http://www.powerreviews.com.  The Power Reviews component is enabled and disabled by the boolean store-specific setting COMMERCE/STORE/POWERREVIEWS/powerreviewsEnabled. The value of the setting is passed to Velocity code by the powerReviewsEnabledHelper Spring bean defined in com.elasticpath.sf/WEB-INF/conf/spring/service/serviceSF.xml. Power Reviews are rendered by JavaScript code, and examples can be found in the guidedSkuTemplate.vm and productTemplate.vm templates.

 

WEB-INF/conf/spring/web/url-mapping.xml

<bean id="SimpleUrlHandlerMapping"

    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

  <property name="mappings">

      <props>

      <prop key="/power-reviews/pwr/engine/js/**/*">

            storeAssetResourceController</prop>

      <prop key="/power-reviews/pwr/engine/**/*">

            storeAssetResourceController</prop>

      <prop key="/power-reviews/pwr/content/**/*">

            storeAssetResourceController</prop>

      </props>

  </property>

</bean>

<!-- Resource controllers for resource retrieval -->

<bean id="storeThemeAssetResourceController"

    class="com.elasticpath.sfweb.controller.impl.AssetResourceControllerImpl"

    parent="abstractEpController">

  <property name="resourceRetrievalStrategy"

            ref="storeThemeAssetRetrievalStrategy"/>

</bean>

<bean id="storeAssetResourceController"

    class="com.elasticpath.sfweb.controller.impl.AssetResourceControllerImpl"

    parent="abstractEpController">

  <property name="resourceRetrievalStrategy"

            ref="storeResourceRetrievalStrategy"/>

</bean>

0 Comments 0 References Permalink