Documente Academic
Documente Profesional
Documente Cultură
2 Certified
Development Professional
Study Guide (P_HYCD_62)
@2017 Hybhub
Benoit
Vanalderweireldt
SAP Hybris Commerce 6.2 Developer Study Guide
Benoit Vanalderweireldt
2018-02-01
Contents
1 Introduction 7
1.1 About the author 8
1.2 Requirements 8
1.3 Groovy console 8
1.4 Assessment test 9
1.4.1 Questions 10
1.4.2 Solutions 13
2 WCMS 17
2.1 CMS Items hierarchy 18
2.2 CMSItem CMSRelation 18
2.3 CMSItem types 18
2.4 CMS Components 20
2.4.1 Base Stores and websites 20
2.4.2 Cms component 21
2.5 Restrictions 25
2.6 Personalization 27
2.6.1 Segmentation input rules 27
2.6.2 Segmentation output actions 28
2.6.3 Result scope 28
2.6.4 Evaluation method 28
2.6.5 Create a CMS segment 29
2.7 WCMS cockpit 29
2.8 Point of services 30
2.8.1 Warehouse 30
2.8.2 Store 31
2.9 Warehouse 31
3 Backoffice 33
3.1 Create a new Backoffice application 34
3.2 Create and connect a new widget 35
3.2.1 Widget application context 38
3.3 Dynamic form 39
3.3.1 Example how to update the approval status 39
3.4 Backoffice and tenants 40
4 Cockpit 43
4.1 Create a new cockpit 44
4.2 Cockpit modification 45
2
CONTENTS 3
Introduction
7
8 CHAPTER 1. INTRODUCTION
Dear reader, thank you for choosing SAP Hybris Commerce 6.2 Developer Study Guide to
prepare for your SAP certification. At Hybhub, we would be grateful to have your feedback on this
e-book. Feel free to share your thoughts about this study guide by emailing benoit.v@hybhub.com.
If you disagree or think there are technical errors, please also share it with us.
Requirements
The following prerequisites are required in order to effectively use this study guide :
2. access to http://help.hybris.com
3. access to http://experts.hybris.com
Groovy console
SAP Hybris Commerce has the ability of running a groovy script on a running system. From
your script you are able to access all services, facades and therefore items. It makes the groovy
console the best place to run any sort of quick tests or validate a piece of code on SAP Hybris
(http://groovy-lang.org). To run a groovy script, open http://localhost:9001/console/scripting/
and select groovy as script type.
If rollback mode is on, no data would be persisted, so if you want to manipulate data remember to
switch the mode to commit
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import de.hybris.platform.catalog.CatalogVersionService
import de.hybris.platform.catalog.model.CatalogVersionModel
import de.hybris.platform.core.model.product.ProductModel
pm = fss.getModelByExample(pm)
println pm.getName()
Assessment test
When you prepare for the P_HYCD_62 exam to become a SAP Certified Development Profes-
sional - SAP Hybris Commerce 6.2 Developer you have a lot of questions like:
• How do I know when I’m ready for the exam ?
• How hard are the questions ?
• How do I know what chapter I need to focus on ?
• Where can I find a dump of the final exam ? (not here and I strongly suggest you not
to even try)
10 CHAPTER 1. INTRODUCTION
This chapter, the assessment test or pretest, is designed as a mental dipstick to know how likely
you would be to successfully pass P_HYCD_62 if you were trying today. So let’s get started; try
to answer all the questions under real conditions.
Questions
Pretest - Question 1
What actions are executed when you initialize SAP Hybris from ant?
Pretest - Question 2
Changing SAP Hybris configuration from the project.properties file of your platform project is
considered bad because ?
• This file is ignored after you create a new configuration folder from it
Pretest - Question 3
Is this a valid Flexible Search Query ?
Pretest - Question 4
According to the following extensioninfo.xml what statements are true ?
<requires-extension name="assistedservicestorefront"/>
<requires-extension name="smarteditaddon"/>
<requires-extension name="captchaaddon"/>
<requires-extension name="acceleratorstorefrontcommons"/>
<requires-extension name="hybhubfacades"/>
</extension>
</extensioninfo>
• This extension could define new item types from its hybhubstorefront-items.xml like all other
extensions
Pretest - Question 5
Which of the following Interfaces are valid SAP Hybris Interceptors ?
• de.hybris.platform.servicelayer.interceptor.ValidateInterceptor<MODEL>
• de.hybris.platform.servicelayer.interceptor.PrepareInterceptor<MODEL>
• de.hybris.platform.servicelayer.interceptor.CheckInterceptor<MODEL>
• de.hybris.platform.servicelayer.interceptor.InitAllInterceptor<MODEL>
• de.hybris.platform.servicelayer.interceptor.RemoveInterceptor<MODEL>
• de.hybris.platform.servicelayer.interceptor.DeleteInterceptor<MODEL>
12 CHAPTER 1. INTRODUCTION
Pretest - Question 6
What is the recommended way to create a new extension within SAP Hybris V6 ?
Pretest - Question 7
What bean would I get when I execute spring.getBean("alias") for the following spring configura-
tion?
• bean1
• bean2
• alias
• The configuration is wrong
Pretest - Question 8
Using a standard SAP Hybris configuration, is this a valid item type definition ?
Pretest - Question 9
All CMS item types extend ?
• GenericItem
• CMS Item
• CMSItem or CMSRelation
• CatalogAware
Pretest - Question 10
Next Generation (NG) Cockpit dynamic forms can be used to ?
Pretest - Question 11
What are the rule engine components (select 2) ?
• Promotion Module
• Rule Builder
• Drool Rules
• Rule Processor
Pretest - Question 12
What steps should you follow in order to integrate Hybris with a new payment provider?
Solutions
Pretest - Solution 1
1,4 are correct.
1. The database is never deleted by SAP Hybris even if the configured database user had ti
right to do so.
2. SAP Hybris will delete only tables he knows from its type definition.
14 CHAPTER 1. INTRODUCTION
Pretest - Solution 2
2 is correct.
Keeping your configuration isolated from SAP Hybris out of the box configuration is recommenced.
Pretest - Solution 3
2 is correct.
Aliases need to be defined within the brackets to be attached to attributes otherwise the resolver
doesn’t know about it.
You can search for abstract item types within a Flexible Search Query.
Pretest - Solution 4
2,4 are correct.
To be able to define new item types, an extension needs to have a core module defined. To be able
to add HMC configuration, an extension needs to have an HMC module defined.
Pretest - Solution 5
1,2,5 are correct.
The available interceptors are :
• PrepareInterceptor
• LoadInterceptor
• RemoveInterceptor
• ValidateInterceptor
• InitDefaultsInterceptor
Pretest - Solution 6
3 is correct.
Installer script and the build framework don’t create any extensions. SAP Hybris V6.2 is using
ant to generate new extensions, maven can be used to configure libraries dependencies.
Pretest - Solution 7
2 is correct.
The last configured alias will be used.
Pretest - Solution 8
1 is correct.
An item type definition can have no attribute and extends by default GenericItem, but if it
extends GenericItem it musts define a deployment table for performance reasons. To ignore this
set build.development.mode=false (not recommended).
1.4. ASSESSMENT TEST 15
Pretest - Solution 9
1,3 are correct.
All item types extend GenericItem type. All CMS item types extend either CMSItem or CMSRe-
lation.
Pretest - Solution 10
2,3 are correct.
Dynamic forms are used to add logic within a wizard or editor area.
Pretest - Solution 11
2,4 are correct.
The rule engine consists of two independent components :
rule builder, UI where you create and maintain rules and rule templates rule processor, process and
execute the rules
Pretest - Solution 12
3,4 are correct.
Cybersource is no longer part of the SAP Hybris commerce distribution, and is suitable only for
Cybersource, not any new payment provider.
You need to implement all payment actions (authorization, capture, void...) for the new payment
provider and configure them within a command factory bean.
16 CHAPTER 1. INTRODUCTION
Chapter 2
WCMS
17
18 CHAPTER 2. WCMS
The SAP Hybris Commerce 6.2 Developer certification expects you to know the Web Content
Management System (WCMS) module extensions. In this chapter, readers will learn the differ-
ent CMS components and item hierachy, learn how to create new CMS components and restrictions,
explore the store and website data model and learn how to create and manage warehouses and
point of sales. Finally, you will learn how to create segments using the BTG extension.
The WCMS module includes 3 extensions :
• catalogVersion
• name
• uid
Each CMS component may have multiple versions; default versions are Staged and Online. Hence
all items within the CMS hierarchy are catalog version aware. It gives you the ability to manage any
sort of contents (Medias, Pages, Slots, Nodes...) within one catalog version and then synchronize
your content once it’s ready to go live.
Tip 1: CMS and catalogs
CMSItem and CMSRelation are managed inside a content catalog, this catalog is only a
subtype of the hybris catalog and doesn’t add extra functionalities.
CMSItem CMSRelation
CMSItem types
The uniqueness of the types CMSItem and CMSRelation is guaranteed because of a composed key
between catalogVersion and UID. This also means that each item in a specific content catalog can
be considered unique and therefore only exist once.
2.3. CMSITEM TYPES 19
• You can use CMSItem when you create a new CMS item, for instance a new component or
a new type of pages.
20 CHAPTER 2. WCMS
• You can use CMSRelation when you create a new type which is not a CMS component but
still needs to be catalog version aware
CMS Components
A CMS component is the base type of each component found on a page. A component can be as
simple as a text paragraph or something more complex like a product rotating component. Each
CMS component consists of three things:
Tip 2: Usage
To change how customized item types are rendered within the WCMS cockpit, you
need to create editorArea_myType.xml, contentEditor_myType.xml and wizardCon-
fig_myType.xml.
• a base store
• a website
The following listing will give you a short overview of those two components.
• the theme
• the homepage
• product catalogs
• the warehouses
• delivery countries
• tax groups
• point of services
• SOLR configuration
Cms component
CMS components are reusable components that you use to customize your storefronts. They are
easily configurable from the WCMS cockpit. Out of the box the following components exist :
• Paragraph component
• Banner component
You can explore the cmslib extension to find out more about the out of the box cms components.
Now we will create a new CMS component to display a reminder for a order time limit that must
be complied if you want the item to be delivered the following day:
<typegroup name="hybhubCms">
<itemtype code="OrderDeliveryTimeLimitComponent" extends="SimpleCMSComponent"
֒→ autocreate="true" generate="true">
<description>Simple CMS component that displays a reminder of when the limit
֒→ time to order for next day delivery</description>
<attributes>
<attribute qualifier="message" type="localized:java.lang.String">
<persistence type="property" />
</attribute>
</attributes>
</itemtype>
</typegroup>
22 CHAPTER 2. WCMS
First create a new constant for your component in the class ControllerConstants:
package com.hybhub.storefront.controllers;
//All imports
/**
*/
public interface ControllerConstants
{
// Constant names cannot be changed due to their usage in dependant extensions, thus
֒→ nosonar
/**
* Class with action name constants
*/
interface Actions
{
interface Cms // NOSONAR
String _Prefix = "/view/"; // NOSONAR
String _Suffix = "Controller"; // NOSONAR
/**
* Default CMS component controller
*/
String DefaultCMSComponent = _Prefix + "DefaultCMSComponentController"; //
֒→ NOSONAR
/**
* CMS components that have specific handlers
*/
String OrderDeliveryTimeLimitComponent = _Prefix +
֒→ OrderDeliveryTimeLimitComponentModel._TYPECODE + _Suffix;
}
}
}
package com.hybhub.storefront.controllers.cms;
import de.hybris.platform.servicelayer.time.TimeService;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.hybhub.core.model.OrderDeliveryTimeLimitComponentModel;
import com.hybhub.storefront.controllers.ControllerConstants;
@Controller("OrderDeliveryTimeLimitComponentController")
@RequestMapping(value = ControllerConstants.Actions.Cms.OrderDeliveryTimeLimitComponent)
public class OrderDeliveryTimeLimitComponentController
extends AbstractAcceleratorCMSComponentController
<OrderDeliveryTimeLimitComponentModel>
{
@Resource
private TimeService timeService;
static
{
DATE_LIMIT = new Calendar.Builder().set(Calendar.HOUR_OF_DAY,
֒→ MAX_HOUR_FOR_NEXT_DAY_DELIVERY).set(Calendar.SECOND, 0)
.build().getTime();
}
@Override
protected void fillModel(final HttpServletRequest request, final Model model,
final OrderDeliveryTimeLimitComponentModel component)
{
final Calendar cal = new
֒→ Calendar.Builder().setInstant(timeService.getCurrentTime()).build();
model.addAttribute("nextDayDelivery",
֒→ (Boolean.valueOf(cal.get(Calendar.HOUR_OF_DAY) < MAX_HOUR_FOR_NEXT_DAY_DELIVERY)));
model.addAttribute("nextDayDeliveryMessage",
֒→ MessageFormat.format(component.getMessage(), DATE_LIMIT));
}
}
24 CHAPTER 2. WCMS
Creating a controller is not mandatory. If you don’t do it, then the DefaultCMSCompo-
nentController will be used, it loads all attributes from the item type into your model.
We need to create a JSP to display our cms component and create a new file hybhubstorefront/
web/webroot/WEB-INF/views/responsive/cms/orderdeliverytimelimitcomponent.jsp:
Run ant all, start your server and update your system, then run this (example based on the
electronic store front):
$contentCatalog=electronicsContentCatalog
$contentCatalogName=Electronics Content Catalog
$contentCV=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),Catalo ⌋
֒→ gVersion.version[default=Online])[default=$contentCatalog:Online]
INSERT_UPDATE OrderDeliveryTimeLimitComponent;$contentCV[unique=true];uid[unique=true];name; ⌋
֒→ message[lang=en];&componentRef;
;;orderDeliveryTimeLimitComponent;order Delivery Time Limit Component;"Order before {0} to
֒→ receive your order tomorrow.";orderDeliveryTimeLimitComponent;
INSERT_UPDATE ContentSlot;$contentCV[unique=true];uid[unique=true];name;active;cmsComponents ⌋
֒→ (&componentRef)
;;Section1Slot-Homepage;Section1 Slot for Homepage;true;orderDeliveryTimeLimitComponent
2.5. RESTRICTIONS 25
Tip 4: Usage
You should now see your new CMS component under your home page.
Restrictions
Warning!
Do not get flexible search query restrictions mixed up with CMS restrictions ! One is only
adding filters in the FSQL WHERE clause while the other has its own java implementation.
Restrictions can be applied to any CMSItem. They use a Java implementation to filter visible or
hidden items.
26 CHAPTER 2. WCMS
package de.hybris.platform.cms2.servicelayer.services.evaluator.impl;
import de.hybris.platform.catalog.model.CatalogModel;
import de.hybris.platform.cms2.model.restrictions.CMSCatalogRestrictionModel;
import de.hybris.platform.cms2.servicelayer.data.RestrictionData;
import de.hybris.platform.cms2.servicelayer.services.evaluator.CMSRestrictionEvaluator;
import org.apache.log4j.Logger;
public CMSCatalogRestrictionEvaluator() {
}
catalogModel = context.getCatalog();
}
return catalogaRestrictionModel.getCatalogs().contains(catalogModel);
}
}
}
Warning!
Each restriction evaluator needs to implement
de.hybris.platform.cms2.servicelayer.services.evaluator.CMSRestrictionEvaluator.
2.6. PERSONALIZATION 27
<itemtype code="CMSCatalogRestriction"
֒→ jaloclass="de.hybris.platform.cms2.jalo.restrictions.CatalogRestriction"
extends="AbstractRestriction" autocreate="true" generate="true">
<attributes>
<attribute qualifier="description" type="java.lang.String" redeclare="true">
<persistence type="dynamic"
֒→ attributeHandler="catalogRestrictionDynamicDescription" />
<modifiers write="false" />
</attribute>
</attributes>
</itemtype>
Personalization
The BTG (Behavioral Targeting Group) extension provides the AP module (Advanced Person-
alization). When the module is activated it allows you to customize which CMSItem to render
for a given customer or to add another CMSItem for a given customer. SAP Hybris customer
segmentation groups your customers into multiple subset and activation actions.
Cart Rules
• cart is empty
• total sum of cart
• categories of products in cart
• products in cart
• size of the cart
• quantity of one product in cart
Order rules
• categories of product in last orders
• total sum of all orders
• total order value
• products in last orders
• number of orders in a date range
• last order date
28 CHAPTER 2. WCMS
Customer rules
• belongs to a group
• gender
• country
• postal code
Website rules
• has viewed products
Result scope
When a segment is fulfilled, the result can be stored in two different scopes:
• permanent scope, segment rule results are stored for the user (anonymous users or authenti-
cated users)
Evaluation method
There are two ways to evaluate rules:
• Optimized processing, a segment evaluation would stop as soon as one rule is not fulfilled
Warning!
Performances are heavily impacted by full processing, however when running optimized
processing your reports don’t contain all rule evaluation results.
2.7. WCMS COCKPIT 29
##################################################################
# Configuration 1: Regular Customer Segment
##################################################################
INSERT_UPDATE BTGSegment;uid[unique=true];name;sites(uid);active[default=true];scope(code)[d ⌋
֒→ efault=ONLINE];$contentCatalogVersion
;electronicsRegularCustomerSegment;Regular Customer Segment;electronics
INSERT_UPDATE BTGRule;uid[unique=true];code;segment(uid,
֒→ $contentCatalogVersion);ruleType(code);$contentCatalogVersion
;electronicsRegularCustomerRule;Regular Customer Rule;electronicsRegularCustomerSegment;ORDER
INSERT_UPDATE BTGOperator;uid[unique=true];code;$contentCatalogVersion
;electronicsGreaterOperator;numGreaterThanOrEqual
INSERT_UPDATE BTGNumberOfOrdersRelativeDateOperand;uid[unique=true];value;unit(code);$conten ⌋
֒→ tCatalogVersion
;electronicsNumberOfOrdersOperand;6;MONTH
INSERT_UPDATE BTGIntegerLiteralOperand;uid[unique=true];literal;$contentCatalogVersion
;electronicsOrdersIntegerOperand;4
INSERT_UPDATE BTGExpression;uid[unique=true];leftOperand(uid,
֒→ $contentCatalogVersion);rightOperand(uid, $contentCatalogVersion);operator(uid,
֒→ $contentCatalogVersion);rule(uid, $contentCatalogVersion);$contentCatalogVersion
;electronicsRegularCustomerExpression;electronicsNumberOfOrdersOperand;electronicsOrdersInte ⌋
֒→ gerOperand;electronicsGreaterOperator;electronicsRegularCustomerRule
INSERT_UPDATE
֒→ BTGAssignToGroupDefinition;uid[unique=true];code;target;userGroups(uid);segment(uid,
֒→ $contentCatalogVersion);$contentCatalogVersion
;electronicsBtgAssignToRegularGroup;Add to Regular
֒→ Segment;assignToGroup;regulargroup;electronicsRegularCustomerSegment
WCMS cockpit
SAP Hybris end users can use the WCMS (Web Content Management System) cockpit (based on
the legacy cockpit framework, hopefully future versions will include a revamped WCMS cockpit
using the next generation cockpit framework). It provides an easy way for end users to manage
web content, such as:
• manage pages
• manage cms components
• synchronize components and pages between different catalogs
• manage navigation nodes
• manage advanced personalization (if BTG cockpit is activated)
30 CHAPTER 2. WCMS
Point of services
A point of service can be one of the following types:
• store
• warehouse
A point of service is used to attached a physical facility to an SAP Hybris model. Out of the box,
you only have stores and warehouses, but it is possible to extend this by creating new enumeration
values. To do so add this to your custom extension -items.xml file:
<enumtypes>
<enumtype code="PointOfServiceTypeEnum" autocreate="false"
generate="false">
<value code="SERVICEDESK" />
</enumtype>
</enumtypes>
• an address
• a longitude
• a latitude
• hours of services
Tip 5: POS
Warehouse
Warehouses (here we are talking about point of services of warehouse type) are used to attach an
adress to an exisiting warehouse.
Warning!
Don’t get point of service of type warehouse and warehouse mixed up!
2.9. WAREHOUSE 31
INSERT_UPDATE
֒→ PointOfService;name[unique=true];displayName;warehouses(code);address(&addrID);latitude ⌋
֒→ ;longitude;geocodeTimestamp[dateformat=dd.MM.yyyy];type(code)[default=WAREHOUSE]
;warehouse_s;Warehouse South;warehouse_s;warehouse_s;33,5933317;130,3515247;11.12.2025
Store
Stores are an essential component for the click and collect functionality, customers want to know
if a given product is available at the physical store and if it is they might also want to pick the
product directly there. Stores are also a way for you to publish your stores opening hours and few
extra informations.
To create a new point of service of type store:
INSERT_UPDATE PointOfService;name[unique=true];address(&addrID);latitude;longitude;geocodeTi ⌋
֒→ mestamp[dateformat=dd-MM-yyyy];openingSchedule(code);basestore(uid)[default=$storeUid]; ⌋
֒→ features(code);type(code)[default=STORE]
;WSI-Nakano;WSI-Nakano;35,6894875;139,6917064;29-04-2011;$standardHours
Warehouse
Warehouses are attached to one or more stores, and to stock levels and consignments. They are
used by the stock level service to return a stock level status for a given product and a given base
store.
To define a new warehouse:
$vendor=electro
INSERT_UPDATE StockLevel;available;warehouse(code)[unique=true];inStockStatus(code);maxPreOr ⌋
֒→ der;maxStockLevelHistoryCount;overSelling;preOrder;productCode[unique=true];reserved
;6;warehouse_1;notSpecified;0;-1;0;0;product1;0
Example on how to call the stock level service (if the out-of-the-box electronic store is available,
this should print "inStock"):
println stockLevel
Chapter 3
Backoffice
33
34 CHAPTER 3. BACKOFFICE
The backoffice (or next generation cockpit) replaces the cockpit framework. In future versions, all
existing cockpits (hmc, cs, wcms...) will be replaced by a new one using the backoffice framework.
The key feature of the backoffice framework is the concept of widget. Each widget is an independent
component that can be reused and connected to other widgets. An application orchestrator allows
you to build a new backoffice from the current backoffice itself.
Any backoffice extension has a backoffice folder with the following structure:
• src folder for your backoffice components code (for example, the controllers),
• resources/widgets. Each widget has its own directory with a definition.xml file, a zul a
template, a css style sheet folders for images an localization. The widgets folder may also
contain sub directories for actions and editors.
Tip 6: Usage
For more details, generate a new custom extension using the extgen ant target and use the
ybackoffice template (don’t forget to generate an example widget).
The backoffice has one shared configuration file where users have different business roles. They
would see different perspectives and have different rights. The admin can see all perspectives
and reorganizes them from the orchestrator. To configure a new perspective, you need to edit file
hybhubbackoffice/resources/hybhubbackoffice-backoffice-config.xml (where hybhubbackoffice is the name
of my custom extension built from the ybackoffice template).
Tip 7: Usage
2. create a new UserGroup member of the new BackofficeRole group and the employeegroup
group;
3. create users member of the new group;
4. update your backoffice configuration, add a new perspective by configuring the principal
attribute of contexts to your new backoffice role.
backoffice.cockpitng.additionalResourceLoader.enabled=true
backoffice.cockpitng.uifactory.cache.enabled=false
backoffice.cockpitng.widgetclassloader.resourcecache.enabled=false
backoffice.cockpitng.resourceloader.resourcecache.enabled=false
36 CHAPTER 3. BACKOFFICE
We will Create a widget to filter reviews by status, to do so create a new folder customerreviewse-
lectorbackofficewidget inside your custom backoffice extension (the one created with the ybackoffice
template). This folder will contain our widget configuration, create a file definition.xml with the
following content :
<widget-definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.hybris.com/schema/cockpitng/widget-definit ⌋
֒→ ion.xsd"
id="com.hybhub.backoffice.widgets.customerreviewselectorbackofficewidget">
<name>Customer Review Selector</name>
<description>Customer Review Selector - Select pending reviews, denied reviews or
֒→ approved reviews </description>
<defaultTitle>Customer Review Selector</defaultTitle>
<author>Hybhub</author>
<version>1.0</version>
<view src="customerreviewselectorwidget.zul" />
<keywords>
<keyword>customerreviewselector</keyword>
</keywords>
<controller class="com.hybhub.backoffice.widgets.CustomerreviewbackofficeController"
֒→ />
<settings>
<setting key="type" type="ENUM(Pending,Approved,Rejected)"/>
<setting key="name" type="String"/>
</settings>
<sockets>
<output type="com.hybris.cockpitng.search.data.pageable.Pageable"
֒→ id="reviews"/>
</sockets>
</widget-definition>
3.2. CREATE AND CONNECT A NEW WIDGET 37
And a view hybhubbackofficewidget.zul in the same folder with the following content :
<widget 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:w="http://www.zkoss.org/2005/zk/client"
xmlns:zk="http://www.zkoss.org/2005/zk"
xsi:schemaLocation="http://www.zkoss.org/2005/zul
֒→ http://www.hybris.com/schema/cockpitng/zul/zul.xsd"
height="100%">
package com.hybhub.backoffice.widgets;
import de.hybris.platform.customerreview.enums.CustomerReviewApprovalType;
import de.hybris.platform.customerreview.model.CustomerReviewModel;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Button;
import com.hybhub.services.CustomerReviewSearchService;
import com.hybris.cockpitng.annotations.ViewEvent;
import com.hybris.cockpitng.search.data.pageable.PageableList;
import com.hybris.cockpitng.util.DefaultWidgetController;
@WireVariable
private CustomerReviewSearchService customerReviewSearchService;
@Override
public void initialize(final Component comp)
{
super.initialize(comp);
reviews.setLabel(this.getWidgetSettings().getString("name"));
}
The widgets have their own spring application context (child of the web application context) with
auto-reload capabilities during runtime.
3.3. DYNAMIC FORM 39
Tip 9: Usage
Remember that in order to override a bean you need to load your extensions in the correct
order using extension dependencies within the extensioninfo.xml.
@WireVariable
private UserService userService;
Dynamic form
Dynamic form is a new feature for backoffice applications. They bring more control and interac-
tivity over the data entered from the backoffice. They can be configured directly from the backof-
fice itself or from the backoffice configuration files (myextension/resources/myextension-backoffice-
config.xml). Dynamic forms can perform action on attributes, sections and tabs. You can write
action in Groovy, Bean Shell, Javascript and spel. To customize dynamic forms directly from the
Backoffice, access the application orchestrator (press f4), then select show cockpit-config.xml from
the top right corner. Filter components with editorAreaDynamicForms.
֒→ computedValue="T(de.hybris.platform.catalog.enums.ArticleApprovalStatus).UNAPPROVED" />
</df:dynamicForms>
</context>
Warning!
Now every time you update a product, the approval status is automatically set to unap-
proved.
ArticleApprovalStatus is used for products approval status on Hybris 6.2, this is confusing
but the enum name has no impacts.
backoffice.webroot=/backoffice_junit
<bean id="backofficeFilterChain"
֒→ class="de.hybris.platform.servicelayer.web.PlatformFilterChain">
<constructor-arg>
<list>
<ref bean="log4jFilter"/>
<ref bean="dynamicTenantActivationFilter"/>
<ref bean="backofficeRedirectFilter"/>
<ref bean="sessionFilter"/>
<ref bean="backofficeDataSourceSwitchingFilter"/>
<ref bean="backofficeCatalogVersionActivationFilter"/>
<ref bean="backofficeContextClassloaderFilter"/>
<ref bean="backofficeSecureMediaFilter" />
</list>
</constructor-arg>
Cockpit
43
44 CHAPTER 4. COCKPIT
Sap Hybris has a cockpit framework used to build backend applications. The framework is based
on ZK a RIA framework (rich internet application). ZK has a large set of UI components that can
be used across all backend applications to speed up the development. The cockpit framework is
provided by the cockpit extension.
Warning!
The legacy cockpit framework is slowly being removed by the next generation cockpit
framework, but it won’t be done before mid 2018, for more information have a look at the
deprecation status page on SAP Hybris wiki. Therefore it’s really important to know how
to work with the cockpit framework.
Then, add the new extension into your localextensions.xml file (here hybhubcockpit). Compile
and start your server. Your new cockpit is available at http://localhost:9001/hybhubcockpit. By
default, you will have one perspective for Product models.
4.2. COCKPIT MODIFICATION 45
You can easily add new perspectives by adding a bean reference into the availablePerspectives
property of the UICockpitSession bean (open the file resources/extensionName/extensionName-
web-spring.xml):
<property name="availablePerspectives">
<list>
<ref bean="HybhubcockpitPerspective"/>
<ref bean="HybhubcockpitMediaPerspective" /> <!-- Custom perspective for
֒→ Medias -->
</list>
</property>
Cockpit modification
Within a cockpit, you have different key elements:
• Editor area, displays an item and provides the option to edit it.
46 CHAPTER 4. COCKPIT
47
48 CHAPTER 5. COMMERCE AND ACCELERATOR
An extension is an addon when it requires the addonsupport extension and when the targeted
extension requires the given addon.
5.1. CREATE A NEW ADDON 49
First you need to generate a new extension based on the yaddon template. I called my extension
hybhubaddon and chose com.hybhub.hybhubaddon as a package name:
Buildfile:
֒→ /Users/j.doe/Workspace/workspace-perso/hybris/hybris-6.2.0/hybris/bin/platform/build.xml
[echo] /Workspace/hybris/hybris-6.2.0/hybris/bin/platform/tomcat/bin
.....
[echo] -----
[echo] hybris Platform Environment
[echo] -----
[echo] OS family: unix
[echo] Java platform: Java(TM) SE Runtime Environment, 1.8.0_60-b27
[echo] Java compiler: org.eclipse.jdt.core.JDTCompilerAdapter
[echo] Build target: 1.8
[echo] Compilation mode: strict
[echo] hybris Platform directory: /Workspace/hybris/hybris-6.0.0/hybris/bin/platform
[echo] hybris Platform version: 6.0.0.0-SNAPSHOT
[echo] Ant version: Apache Ant(TM) version 1.9.1 compiled on May 15 2013
[echo] Ant memory settings: -Xmx512m -Dfile.encoding=UTF-8
[echo] -----
.....
extgen:
[input]
[input] Please choose a template for generation.
[input] Press [Enter] to use the default value (ywebservices, ysmarteditmodule, yhacext,
֒→ [yempty], ycmssmartedit, yatddtests, yscala, ygroovy, ycockpit, yoccaddon, yaddon,
֒→ ycommercewebservices, ycommercewebservicestest, ycommercewebserviceshmc,
֒→ ychinaacceleratorstorefront, yacceleratorordermanagement, yacceleratorstorefront,
֒→ yacceleratorfractusfulfilmentprocess, yacceleratorfulfilmentprocess, ybackoffice)
yaddon
[input]
[input] Please choose the name of your extension. It has to start with a letter followed
֒→ by letters and/or numbers.
[input] Press [Enter] to use the default value [training]
hybhubaddon
[input]
[input] Please choose the package name of your extension. It has to fulfill java package
֒→ name convention.
[input] Press [Enter] to use the default value [org.training]
com.hybhub.hybhubaddon
.......
[echo] Next steps:
[echo]
[echo] 1) Add your extension to your
֒→ /Workspace/hybris/hybris-6.0.0/hybris/config/localextensions.xml
[echo]
[echo] <extension
֒→ dir="/Workspace/hybris/hybris-6.0.0/hybris/bin/custom/hybhubaddon"/>
[echo]
[echo] 2) Please remove all template extensions (again) before you proceed.
[echo]
[echo] 3) Make sure the applicationserver is stopped before you build the extension the
֒→ first time.
[echo]
[echo] 4) Perform ’ant’ in your hybris/platform directory.
[echo]
[echo] 5) Restart the applicationserver
[echo]
[echo]
BUILD SUCCESSFUL
Total time: 29 seconds
50 CHAPTER 5. COMMERCE AND ACCELERATOR
After adding your addon to your eclipse environment and to your localextensions.xml file, you will
notice that it looks like any other extension except for the acceleratoraddon folder. This folder
structure is a copy of the usual structure of a frontend extension.
Next step is to install your addon into the designated store front extension. For this, we use ant:
In my case my addon’s name is hybhubaddon and the storefront extension I’m using is yaccelera-
torstorefront so I need to execute :
BUILD SUCCESSFUL
Total time: 2 seconds
• Generate a new project.properties file from the project.properties.template inside your addon.
• Configure the hybhubaddon web spring configuration hybhubaddonweb-spring.xml into yaccel-
eratorstorefront.additionalWebSpringConfigs
• Add hybhubaddon into extensioninfo.xml for yacceleratorstorefront
BUILD SUCCESSFUL
Total time: 2 seconds
52 CHAPTER 5. COMMERCE AND ACCELERATOR
Your new Addon extension has few files under its acceleratoraddon folder:
• acceleratoraddon/web/webroot/_ui/responsive/common/css/hybhubaddon.css
• acceleratoraddon/web/webroot/WEB-INF/_ui-src/responsive/less/hybhubaddon.less
Create a new JSP file under the folder
acceleratoraddon/web/webroot/WEB-INF/views/responsive/pages/layout, hybhubAddonLayout.jsp:
<template:page pageTitle="${pageTitle}">
<h1>From Hybhub Addon</h1>
</template:page>
package com.hybhub.hybhubaddon.controllers.pages;
import de.hybris.platform.addonsupport.controllers.page.AbstractAddOnPageController;
import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
import de.hybris.platform.cms2.model.pages.ContentPageModel;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value = "/hybhub")
public class HybHubAddonPageController extends AbstractAddOnPageController
{
@RequestMapping(method = RequestMethod.GET)
public String hybhub(final Model model) throws CMSItemNotFoundException
{
final ContentPageModel page = getContentPageForLabelOrId(null);
storeCmsPageInModel(model, page);
setUpMetaDataForContentPage(model, page);
return "addon:/hybhubaddon/pages/layout/hybhubAddonLayout";
}
}
5.2. OCC WEBSERVICES 53
<context:annotation-config/>
<context:component-scan base-package="com.hybhub.hybhubaddon.controllers"/>
Build your platform and start your server, now when you access https://localhost:9002/yacceleratorstorefront/
electronics/en/hybhub?site=electronics you should see :
What have we done? We have customized the store front extension without changing its
sources. We could easily inject our changes on any other project or future Hybris releases.
OCC Webservices
The Omni Commerce Connect module is a set of API that expose services and data from Hybris.
All webservices are Restful web services and support both JSON and XML format. Web services
are build with the Spring MVC framework, using controllers, facades and converters.
54 CHAPTER 5. COMMERCE AND ACCELERATOR
• commercewebservicescommons
• ycommercewebservices Authentication uses the OAuth2 framework. Object can be cached
using the Ehcache, cache is configured for each controller and method with the @Cacheable
annotation
• ycommercewebserviceshmc
• ycommercewebservicestest
Remember that all extensions starting with a y are templates. For example to add new
webservices or to customize existing one, you need to generate a new commerce web service
extensions from the ycommercewebservices template.
• Stateful
• Response format (XML or JSON).
2. V2 (/v2/) which is the current version of the web services released with Hybris 5.4. The key
features of version 2 are:
• Stateless;
• Restful
• Data creation.
Type of requests:
Remember that OCC doesn’t use normal users. It has its own data type to manage cre-
dentials. Have a look at OAuthClientDetails.
5.2. OCC WEBSERVICES 55
<attributes>
<attribute qualifier="clientId" type="java.lang.String">
<description>Client Id</description>
<modifiers unique="true" optional="false" initial="true"
֒→ write="false" />
<persistence type="property" />
</attribute>
<indexes>
<index name="clientIdIdx" unique="true">
<key attribute="clientId" />
</index>
</indexes>
</itemtype>
56 CHAPTER 5. COMMERCE AND ACCELERATOR
Install OCC
To activate and use the Omni Channel Connect module, you need to have these extensions acti-
vated:
• ycommercewebservices;
• ycommercewebserviceshmc;
• ycommercewebservicestest;
• commercewebservicescommons;
• webservicescommonsbackoffice;
• cmswebservices.
Warning!
If you have created your own web services extensions from the y templates (using modulegen
with commercewebservices), then delete the reference to the web services templates from
your localextensions.xml file.
Once you have updated your Hybris installation with the required extensions, you will be able to
manage the OAuthClientDetails and see the current OAuthAccessToken from the backoffice.
OAUTH 2
Hybris web services authorization mechanism is based on (https://oauth.net/2/) which is the
industry standard protocol. Each call to the OCC web services have to go through a complex
authorization mechanism. First the user will be authenticated (verifying credentials); then the
user is authorized (decide whether or not the user can perform a given action).
Authorization happens within the HTTP layer and the Service layer. Each of them applies its own
set of verification.
5.2. OCC WEBSERVICES 57
First you need to have OAuth clients configured. You can check this from the backoffice (System
-> OAuth -> OAuth Clients). If you don’t have any, you can import the one provided with the
cmswebservices extension inside the impex file sampledata-oauthclients.impex.
INSERT_UPDATE OAuthClientDetails;clientId[unique=true];resourceIds;scope;authorizedGrantType ⌋
֒→ s;authorities;clientSecret;registeredRedirectUri
;client-side;hybris;basic;implicit,client_credentials;ROLE_CLIENT;secret;http://localhost:90 ⌋
֒→ 01/authorizationserver/oauth2_implicit_callback;
;mobile_android;hybris;basic;authorization_code,refresh_token,password,client_credentials;RO ⌋
֒→ LE_CLIENT;secret;http://localhost:9001/authorizationserver/oauth2_callback;
;trusted_client;hybris;extended;authorization_code,refresh_token,password,client_credentials ⌋
֒→ ;ROLE_TRUSTED_CLIENT;secret;;
58 CHAPTER 5. COMMERCE AND ACCELERATOR
Curl
Postman
Post Request: https://localhost:9002/authorizationserver/oauth/token?client_id=trusted_client&
client_secret=secret&grant_type=client_credentials
The alternative is to create a new addon to extend existing API or add new one, this could
be a valid solution in some cases.
60 CHAPTER 5. COMMERCE AND ACCELERATOR
The first step is to generate a new extension from the ycommercewebservices extension:
extgen:
[input]
[input] Please choose a template for generation.
[input] Press [Enter] to use the default value (ywebservices, ysmarteditmodule, yhacext,
֒→ [yempty], ycmssmartedit, yatddtests, yscala, ygroovy, ycockpit, yoccaddon, yaddon,
֒→ ycommercewebservices, ycommercewebservicestest, ycommercewebserviceshmc,
֒→ ychinaacceleratorstorefront, yacceleratorordermanagement, yacceleratorstorefront,
֒→ yacceleratorfractusfulfilmentprocess, yacceleratorfulfilmentprocess, ybackoffice)
ycommercewebservices
[input]
[input] Please choose the name of your extension. It has to start with a letter followed
֒→ by letters and/or numbers.
[input] Press [Enter] to use the default value [training]
mywebservices
[input]
[input] Please choose the package name of your extension. It has to fulfill java package
֒→ name convention.
[input] Press [Enter] to use the default value [org.training]
com.hybhub.webservices
[echo] Using extension template source:
֒→ /Workspace/hybris/hybris-6.0.0/hybris/bin/ext-template/ycommercewebservices
[mkdir] Created dir: /Workspace/hybris/hybris-6.0.0/hybris/temp/hybris/extgen
[echo] Next steps:
[echo] 1) Add your extension to your
֒→ /Users/workspace-perso/hybris/hybris-6.0.0/hybris/config/localextensions.xml
[echo] <extension
֒→ dir="/Workspace/hybris/hybris-6.0.0/hybris/bin/custom/mywebservices"/>
[echo] 2) Please remove all template extensions (again) before you proceed.
[echo] 3) Make sure the applicationserver is stopped before you build the extension the
֒→ first time.
[echo] 4) Perform ’ant’ in your hybris/platform directory.
[echo] 5) Restart the applicationserver
BUILD SUCCESSFUL
Total time: 27 seconds
: platform
5.2. OCC WEBSERVICES 61
Once you have generated the new extension, you need to remove the ycommercewebservices from
the localextensions.xml file and add your new mywebservices into it.
<hybrisconfig xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’
֒→ xsi:noNamespaceSchemaLocation=’../bin/platform/resources/schemas/extensions.xsd’>
<extensions>
<path dir=’\${HYBRIS_BIN_DIR}’ autoload=’false’ />
...
<extension name="mywebservices"/>
...
</extensions>
</hybrisconfig>
Run ant clean all to check that the build is not broken before you start developing anything.
We are going to add a new web service under the version 2 structure. Our web service will simply
give a list of String of all running cronjob codes. To do so, we need to create a new class Cron-
JobsController under web/src source folder and inside the com.hybhub.webservices.v2.controller
package:
62 CHAPTER 5. COMMERCE AND ACCELERATOR
package com.hybhub.webservices.v2.controller;
import de.hybris.platform.servicelayer.cronjob.CronJobService;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hybhub.webservices.dto.cronjob.CronJobListWsDTO;
@Controller
@RequestMapping(value = "/{baseSiteId}/cronjobs")
public class CronJobsController extends BaseController
{
@Resource
CronJobService cronJobService;
@Secured("ROLE_TRUSTED_CLIENT")
@RequestMapping(value = "/running", method = RequestMethod.GET)
@ResponseBody
public CronJobListWsDTO getRunningCronJobCode()
{
final CronJobListWsDTO cronJobList = new CronJobListWsDTO();
cronJobList.setCronJobsCode(
cronJobService.getRunningOrRestartedCronJobs().
parallelStream().map(c ->
֒→ c.getCode()).collect(Collectors.toList()));
return cronJobList;
}
}
<bean class="com.hybhub.webservices.dto.cronjob.CronJobListWsDTO">
<property name="cronJobsCode" type="java.util.List<java.lang.String>"/>
</bean>
Run ant clean all then start your server. Check that you have at least one running cronjob otherwise
your list will be empty, then you can call our newly created webservice:
Warning!
Don’t forget that you first to generate a token as ROLE_TRUSTED_CLIENT
in order to call the new webservice since we have declared it with @Se-
cured("ROLE_TRUSTED_CLIENT")
Why do we use CronJobListWsDTO and not simply a List of String ? HTTP message convert-
ers operate only on the dedicated DTO objects. Marshalers operate mainly on properties and,
5.2. OCC WEBSERVICES 63
because of this, marshaling performed with commonly used classes such as java.util.ArrayList or
java.lang.String is not possible. The simplest solution is to wrap them using a dedicated DTO
object.
How to cache a webservice ? First we need to create a new cache configuration for our cronjob
controller, open the file mywebservices/web/webroot/WEB-INF/cache/ehcache.xml and add :
<cache name="cronjobCache"
maxElementsInMemory="1"
eternal="false"
overflowToDisk="true"
timeToLiveSeconds="30"
diskPersistent="false"
maxElementsOnDisk="100"
memoryStoreEvictionPolicy="LRU"/>
Then update our controller to be Cachable. This example is really basic we only cache the answer
for one key and for 30 seconds, You can find more complex examples in other controllers:
@Controller
@CacheControl(directive = CacheControlDirective.PUBLIC, maxAge = 30)
@RequestMapping(value = "/{baseSiteId}/cronjobs")
public class CronJobsController extends BaseController
...
@Secured("ROLE_TRUSTED_CLIENT")
@RequestMapping(value = "/running", method = RequestMethod.GET)
@Cacheable(value = "cronjobCache", key = "T(de.hybris.platform.commercewebservicescommons.ca ⌋
֒→ che.CommerceCacheKeyGenerator).generateKey(false,false,’getRunningCronJobCode’)")
@ResponseBody
public CronJobListWsDTO getRunningCronJobCode()
Now it should take 30 seconds before any changes to cronjobs status appear when you call our
cronjob.
64 CHAPTER 5. COMMERCE AND ACCELERATOR
• NavigationBarComponents, main item type, this represents a section of the top navigation
menu, can hold a CMSNavigationNodes (to display sub link) and a CMSLinkComponents
• CMSNavigationNodes, represents the architecture of the navigation menu, each node can
have parent nodes and children nodes
$contentCatalog=electronicsContentCatalog
$contentCatalogName=Electronics Content Catalog
$contentCV=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),Catalo ⌋
֒→ gVersion.version[default=Online])[default=$contentCatalog:Online]
$productCatalog=electronicsProductCatalog
$productCatalogName=Electronics Product Catalog
$productCV=catalogVersion(catalog(id[default=$productCatalog]),version[default=’Staged’])[un ⌋
֒→ ique=true,default=$productCatalog:Staged]
$category=category(code, $productCV)
Run this Impex query on the electronic store to update the top navigation menu.
Order splitting
Order splitting is part of the Order Management Module and is responsible of splitting orders into
different consignments based on the implemented splitting strategy.
The service responsible for splitting orders into different consignments is de.hybris.platform.ordersplitting.orderSplittingServ
66 CHAPTER 5. COMMERCE AND ACCELERATOR
This service contains a list of splitting strategies to apply on a given order. A strategy needs to im-
plement de.hybris.platform.ordersplitting.strategy.SplittingStrategy. The out of the box strategies
are:
• splitByAvailableCount;
• splitByDeliveryMode;
• splitByPoS;
• splitByNamedDeliveryDate;
• splitByEntryDeliveryAddress;
• splitByWarehouse.
Promotion
SAP Hybris V6 introduced a major change with the new Promotion Engine (Running with the
new rule engine). Unlike the now legacy and deprecated Promotion Module which was still using
the deprecated Jalo Layer, the new Promotion Engine uses the services layer and is highly flexible.
Warning!
For backward compatibility reasons under SAP Hybris V6.2 both legacy Promotion Module
and new Promotion Engine are available, but all new promotion implementation should be
done using the Promotion Engine.
Promotion Module
Remember this module is deprecated under SAP Hybris V6.2
Promotions can apply at two different levels:
• product promotion
• order promotion
Promotion are implemeted using the Jalo layer. It means that each promotion template would have
its own Jalo implementation. Your implemetation will need to implement either ProductPromotion
or OrderPromotion, both promotion type extends AbstractPromotion. For example, have a look
at the promotions-items.xml file. Here is an extract of the ProductFixedPricePromotion:
5.5. PROMOTION 67
<itemtype code="ProductFixedPricePromotion"
extends="ProductPromotion"
jaloclass="de.hybris.platform.promotions.jalo.ProductFixedPricePromotion"
autocreate="true"
generate="true">
<attributes>
<attribute
qualifier="productFixedUnitPrice"
autocreate="true"
type="PromotionPriceRowCollectionType">
<description>Fixed price to sell the product at in specific
֒→ currencies.</description>
<persistence type="property" />
<modifiers read="true" write="true" search="false" initial="false"
֒→ optional="true" partof="true"/>
</attribute>
</attributes>
</itemtype>
68 CHAPTER 5. COMMERCE AND ACCELERATOR
public ProductFixedPricePromotion() {
}
The major flaw of this approach and it’s why it is now deprecated, is that you can’t access the
service layer in a trivial manner.
Promotion Engine
Rule Engine
The rule engine is based on [Drools](http://www.drools.org), a Business Rules Management System
(BRMS). It provides a mechanism to define business rules with conditions and actions (for example
if you buy 2 products of the same type you will get a discount of 10
The rule engine is only used by the promotion engine out of the box but it could be useful for
other features that could benefit from a rules/actions engine like the business process framework
used by Hybris or order sourcing or btg.
It is made from two independent components:
• rule builder (accessible from the backoffice, Rule Engine -> Source Rule -> +
Promotion Rule)
• rule processor
Actions and conditions are used to create rules. They are the building blocks of the rule engine.
Rules are compiled using the IR (Intermediate Representation) into executables.
• OrderRAO
• CartRAO
• UserRAO
• RuleEngineResultRAO
• DeliveryModeRAO
70 CHAPTER 5. COMMERCE AND ACCELERATOR
RAO objects are defined using beans.xml files, and therefore are generated at compile time, you
can extend existing one or create new one.
Let’s extend de.hybris.platform.ruleengineservices.rao.AbstractOrderRAO with an additional value
dayOfWeek represented by an Integer (from 1 to 7). First we need to update the bean definition:
<bean class="de.hybris.platform.ruleengineservices.rao.AbstractOrderRAO"
֒→ template="resources/coderao-template.vm"
extends="de.hybris.platform.ruleengineservices.rao.AbstractActionedRAO">
<property name="dayOfWeek" type="Integer" />
</bean>
package de.hybris.ruleenginetrail.converters.populator;
import de.hybris.platform.core.model.order.AbstractOrderModel;
import de.hybris.platform.ruleengineservices.converters.populator.CartRaoPopulator;
import de.hybris.platform.ruleengineservices.rao.CartRAO;
import de.hybris.platform.servicelayer.dto.converter.ConversionException;
import java.time.LocalDate;
@Override
public void populate(AbstractOrderModel source, CartRAO target) throws
֒→ ConversionException {
super.populate(source, target);
target.setDayOfWeek(LocalDate.now().getDayOfWeek().getValue());
}
Warning!
This requires you to have extended the cart rao.
Let’s create a new condition to be fulfilled only on week end days (Saturday and Sunday). First you
need an implementation of de.hybris.platform.ruleengineservices.compiler.RuleConditionTranslator.
package de.hybris.ruleenginetrail.rule.evaluation.conditions.impl;
import de.hybris.platform.ruleengineservices.compiler.};
import de.hybris.platform.ruleengineservices.rao.CartRAO;
import de.hybris.platform.ruleengineservices.rule.data.RuleConditionData;
import de.hybris.platform.ruleengineservices.rule.data.RuleConditionDefinitionData;
@Override
public RuleIrCondition translate(RuleCompilerContext context, RuleConditionData
֒→ ruleConditionData, RuleConditionDefinitionData ruleConditionDefinitionData) throws
֒→ RuleCompilerException {
return weekEndDayCondition;
}
}
Then you need to create a new Spring bean for your condition:
<alias alias="ruleCartWeekEndConditionTranslator"
֒→ name="defaultRuleCartWeekEndConditionTranslator" />
<bean name="defaultRuleCartWeekEndConditionTranslator" class="de.hybris.ruleenginetrail.rule ⌋
֒→ .evaluation.conditions.impl.RuleCartWeekEndConditionTranslator"
֒→ />
72 CHAPTER 5. COMMERCE AND ACCELERATOR
Finally creating the new condition and mapping within SAP Hybris :
$lang=en
INSERT_UPDATE RuleConditionDefinition;id[unique=true];name[lang=$lang];priority;breadcrumb[l ⌋
֒→ ang=$lang];allowsChildren;translatorId;translatorParameters;categories(id)
;cart_weekend;Cart week end;301;Cart week end;false;ruleCartWeekEndConditionTranslator;;cart
INSERT_UPDATE RuleConditionDefinitionParameter;definition(id)[unique=true];id[unique=true];p ⌋
֒→ riority;name[lang=$lang];description[lang=$lang];type;value;required[default=true]
#We don’t insert anything here, not need for extra parameters
INSERT_UPDATE RuleConditionDefinitionRuleTypeMapping;definition(id)[unique=true];ruleType(co ⌋
֒→ de)[unique=true]
;cart_weekend;PromotionSourceRule
Warning!
RuleConditionDefinition translatorId must be the Spring bean name.
Update your system, and you should be able to select Cart Week End from the rule builder.
Available conditions
Your translator will return a condition for the rule engine. So the rule engine can compile and
optimize your rules for runtime. Out of the box, you have the following available conditions:
true de.hybris.platform.ruleengineservices.compiler.RuleIrTrueCondition
false de.hybris.platform.ruleengineservices.compiler.RuleIrFalseCondition
condition de.hybris.platform.ruleengineservices.compiler.RuleIrGroupCondition
Let’s create a new type of action. This will add a discount on the order based on how many
previous orders the customer fullfiled, for example:
A customer A has 3 orders in his history; his new order will be discounted by 3 value factor B with
a maximum of discount of C. First, we need to create a new RAO action:
5.5. PROMOTION 75
package de.hybris.ruleenginetrail.rule.evaluation.actions.impl;
import com.google.common.base.Preconditions;
import de.hybris.platform.ruleengineservices.rao.};
import de.hybris.platform.ruleengineservices.rule.evaluation.RuleActionContext;
import de.hybris.platform.ruleengineservices.rule.evaluation.actions.AbstractRuleExecutableS ⌋
֒→ upport;
import de.hybris.platform.ruleengineservices.rule.evaluation.actions.RAOAction;
import org.apache.commons.collections.MapUtils;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Optional;
@Override
public void performAction(RuleActionContext context, Map<String, Object> parameters) {
Preconditions.checkArgument(MapUtils.isNotEmpty(parameters), "Properties passed as a
֒→ method argument must not be empty");
this.validateRule(context);
this.trackRuleGroupExecutions(context);
this.trackRuleExecution(context);
}
DiscountRAO discountRao =
֒→ this.getRuleEngineCalculationService().addOrderLevelDiscount(cartRao, false, discount);
RuleEngineResultRAO result = context.getRuleEngineResultRao();
result.getActions().add(discountRao);
this.setRAOMetaData(context, new AbstractRuleActionRAO[]{discountRao});
context.updateFacts(new Object[]{cartRao, result});
context.insertFacts(new Object[]{discount});
}
}
76 CHAPTER 5. COMMERCE AND ACCELERATOR
We now need to create create two Spring beans for our new action:
<alias alias="ruleOrderHistoryDiscountRAOAction"
֒→ name="defaultRuleOrderHistoryDiscountRAOAction" />
<bean id="defaultRuleOrderHistoryDiscountRAOAction" parent="abstractRuleExecutableSupport"
֒→ class="de.hybris.ruleenginetrail.rule.evaluation.actions.impl.RuleOrderHistoryDiscountR ⌋
֒→ AOAction"/>
Warning!
We use DefaultRuleExecutableAction for backward compatibility, see the following topic:
Promotion actions.
Last step is to define the rule action, its parameter and mapping:
$lang=en
INSERT_UPDATE RuleActionDefinition;id[unique=true];name[lang=$lang];priority;breadcrumb[lang ⌋
֒→ =$lang];translatorId;translatorParameters;categories(id)
;order_history_discount;Order percentage discount base on how many orders;1200;Apply
֒→ {value}% discount on the multiply by how many orders customer has, max of
֒→ {max_discount}%;ruleExecutableActionTranslator;actionId->ruleOrderHistoryDiscountAction ⌋
֒→ ;cart_discounts
INSERT_UPDATE RuleActionDefinitionParameter;definition(id)[unique=true];id[unique=true];prio ⌋
֒→ rity;name[lang=$lang];description[lang=$lang];type;value;required[default=true]
;order_history_discount;value;1000;Percentage discount value factor;Percentage discount that
֒→ multiplied by order numbers;java.math.BigDecimal;;
;order_history_discount;max_discount;1001;Maximum discount;Max
֒→ discount;java.math.BigDecimal;;
INSERT_UPDATE RuleActionDefinitionRuleTypeMapping;definition(id)[unique=true];ruleType(code) ⌋
֒→ [unique=true]
;order_history_discount;PromotionSourceRule
You can create as many RuleActionDefinitionParameter as you need they would be available from
the backoffice and inside you RAO action parameters map.
Payment
SAP Hybris provides a module to integrate external payment gateways such as CyberSource. The
module is designed to seamlessly integrate any PSP into your checkout flow.
5.6. PAYMENT 77
Since SAP Hybris V6, CyberSource payment integration is not part of the Commerce
Accelerator, you would need to add the CyberSource extension.
When you integrate a new payment provider, you need to integrate the following steps:
• Follow on refund, refund money to the customer’s bank account for an order
• Standalone refund, refund money to the customer’s bank account when not attached to any
transactions or orders
• Is applicable, command to check if the payment provider can execute a given command
When you have implemented all commands for your payment service provider, create a new bean
using de.hybris.platform.payment.commands.factory.impl.DefaultCommandFactoryImpl, and inject
all your commands in it.
Tip 18: Payment providers
SAP Hybris can have multiple PSP configured at the same time, it’s up to the checkout
flow to give the customer the option to choose the final PSP.
HOP
Out of the box, SAP Hybris provides an example of a hosted order page. A HOP is a page hosted by
the payment provider where the customer will enter all his payment information. In a production
environment the flow would be as follows:
• customer is redirected to the payment provider site where he will enter all required payment
information;
• customer is redirected to SAP Hybris with a uid of his transaction so SAP Hybris can check
that the transaction was successful.
During the entire transaction SAP Hybris didn’t handle any sensitive payment data
from the customer, all SAP Hybris knows is the uid of the transaction
78 CHAPTER 5. COMMERCE AND ACCELERATOR
SOP
Out of the box, SAP Hybris provides an example of a silent order page. A SOP is page hosted by
SAP Hybris with a from sent directly to the payment provider. A SOP can be entirely customized
unlike a HOP (hosted by the payment provider). In a production environment the flow would be
as follows:
• customer fill a form hosted by SAP Hybris but redirecting to the payment provider;
• the payment provider receive the submited form and process the payment;
• customer is redirected to SAP Hybris with a uid of his transaction so SAP Hybris can check
that the transaction was successful.
PCI compliance
The payment card industry security standard enforce strict rules for your platform in order for you
to accept payment by credit card ([What is PCI compliance](http://www.onlinetech.com/resources/references/what
is-pci-compliance)).
In both mocked implementation SAP Hybris will only know a transaction uid, this is great for PCI
compliance
Internationalization
SAP Hybris supports out of the box the following:
• Language fallbacks;
• Tenant-specific settings;
The following services to work with internationalization and localization are available:
5.8. REQUEST HANDLING 79
Request handling
SAP Hybris accelerators are built on top of Spring MVC. This will handle all HTTP requests you
make to SAP Hybris. Below a simplified representation of how Spring MVC handles requests:
![Spring MVC - Request Handling](images/spring-mvc-requesthandling.png)
The dispatcherServlet (org.springframework.web.servlet.DispatcherServlet )is responsible of han-
dling and dispatching requests for all incoming requests it receives.
A unique entry point is configured for each extension web module. By default it’s the name of the
extension. You can change from your configuration (they are intentionally empty):
hybhubstorefront.webroot=
storefrontContextRoot=
Request filters
request filters are handled by a DelegatingFilterProxy, a special servlet filter that, by itself, doesn’t
do much. Instead, it delegates to an implementation of javax.servlet.Filter that’s registered as a
bean in the Spring application context.
The accelerators are configured with different filters out-of-the-box:
• cmsSiteFilter
• storefrontFilter
• urlEncoderFilter
• springSecurityFilterChain
• anonymousCheckoutFilter
• cartRestorationFilter
80 CHAPTER 5. COMMERCE AND ACCELERATOR
• customerLocationRestorationFilter
• ....
The filter entry point is configured inside your web application web.xml file:
<filter>
<description>
Spring configured chain of spring filter beans in tenant scope
</description>
<filter-name>storefrontTenantFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
package com.hybhub.storefront.filters;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.GenericFilterBean;
@Override
public void doFilter(final ServletRequest paramServletRequest, final ServletResponse
֒→ paramServletResponse,
final FilterChain paramFilterChain) throws IOException,
֒→ ServletException
{
final HttpServletRequest httpRequest = (HttpServletRequest)
֒→ paramServletRequest;
paramFilterChain.doFilter(paramServletRequest, paramServletResponse);
}
<alias name="defaultStorefrontTenantDefaultFilterChainList"
֒→ alias="storefrontTenantDefaultFilterChainList" />
<util:list id="defaultStorefrontTenantDefaultFilterChainList">
<!-- other filters -->
<ref bean="hybhubFilter"/>
<!-- other filters -->
</util:list>
The order you place your filter matters as they are executed in the list order!
82 CHAPTER 5. COMMERCE AND ACCELERATOR
Hot folders
SAP Hybris provides different ways to import data; one of them is a hot folder. A hot folder means
that when you transfer a file into a specific folder with matching name it will automatically be
processed by SAP Hybris.
The hot folder functionality is located inside the acceleratorservices extension, it’s
based on the Spring Integration Framework
When you transfer a file into a hot folder, the following actions are executed:
4. resolve the mapping between the file name and the type to import
7. cleanup
Let’s assume the out of the box customer import flow is not enough for us. We need a new one
with a different header and more attributes.
5.9. HOT FOLDERS 83
<file:inbound-channel-adapter id="hybhubBatchFilesCustomer"
֒→ directory="#{baseDirectoryTenant}"
filename-regex="^customers_full\-(.*)-(\d+)\.csv" comparator="fileOrderComparator">
<int:poller fixed-rate="1000" />
</file:inbound-channel-adapter>
<file:outbound-gateway request-channel="hybhubBatchFilesCustomer"
֒→ reply-channel="hybhubBatchFilesCustomerProc"
directory="#{baseDirectoryTenant}/processing" delete-source-files="true" />
<bean id="hybhubCustomersHeaderSetupTask"
֒→ class="de.hybris.platform.acceleratorservices.dataimport.batch.task.HeaderSetupTask">
<property name="catalog" value="electronicsProductCatalog" />
<property name="net" value="false" />
<property name="storeBaseDirectory" ref="baseDirectoryTenant" />
</bean>
<int:service-activator input-channel="hybhubBatchFilesCustomerProc"
֒→ output-channel="batchFilesHeaderInit"
ref="hybhubCustomersHeaderSetupTask" method="execute" />
<bean id="hybhubBatchCustomerConverterMapping"
class="de.hybris.platform.acceleratorservices.dataimport.batch.converter.mapping.i ⌋
֒→ mpl.DefaultConverterMapping"
p:mapping="customers_full"
p:converter-ref="hybhubBatchCustomerConverter"/>
Here we are using headerInitTask as a batchFilesHeaderInit. This is expecting your file to match
the following pattern to extract the language code:
-(\w{2})-(\d+)\.csv
84 CHAPTER 5. COMMERCE AND ACCELERATOR
-(\d+)\.csv
serge.d@hybhub.com,Serge,Dupont,mr,en,USD,regulargroup
This file will be automatically executed by SAP Hybris, and a new customer will be created.
The mapping is made between the name of your file and the string property of the
ConverterMapping implementation
Impex row definition uses a strange syntax, try to remember that + means mandatory
and ’S’ means the current sequence ID
Data Modeling
<coremodule generated="true"
manager="de.hybris.platform.jalo.extension.GenericManager"
֒→ packageroot="com.hybhub.myextension"/>
<items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="items.xsd">
<itemtypes>
<!--
<itemtype generate="true"
code="MyProduct"
jaloclass="yemptypackage.jalo.MyProduct"
extends="Product"
autocreate="true"
>
<attributes>
<attribute qualifier="myExampleInitialStringField"
֒→ type="java.lang.String">
<description>My Example Initial String
֒→ Value</description>
<modifiers initial="true"/>
<persistence type="property"/>
</attribute>
<attribute qualifier="myExampleBooleanField"
֒→ type="java.lang.Boolean">
<description>Example Initial Boolean
֒→ Field</description>
<persistence type="property"/>
</attribute>
</attributes>
</itemtype>
-->
</itemtypes>
</items>
• Atomic types, the most basic types available on the SAP Hybris platform, they most likely
5.10. DATA MODELING 87
represent Numbers, Strings, Dates.... they have a direct correspondence with a database
type. You probably won’t need to define your own Atomic type, following is an example
extracted from core-items.xml :
• Collection types, contains a typed number of instances. This can be a Collection (Unordered),
a List (Ordered) or a Set (Unique) of elements. The collection is kept in the database by
saving a csv list of instance pks.
<collectiontypes>
<collectiontype code="ProductSet" elementtype="Product" type="set" autocreate="true"
֒→ generate="true" />
</collectiontypes>
<itemtypes>
<itemtype code="Customer" autocreate="false" generate="false">
<attributes>
<attribute qualifier="wishList" type="ProductSet">
<persistence type="property"/>
</attribute>
</attributes>
</itemtype>
</itemtypes>
After updating my system the User table would look like this:
|p_wishlist|text|YES||NULL||
You can see the size of the Set (3) and the 3 Products PKs.
Use relation types whenever possible, collection types have severe limitation (max-
imum length as for example in Mysql maximum text size is 65,535 characters, not
cached by Hybris).
• Enumeration types, they are like java Enumerations, they declare a collection of constants,
within SAP Hybris Enumeration is a composed type and their value represents their instance.
Within SAP Hybris enumerations can be dynamic, meaning you can add new values during
runtime (unlike enumerations in Java), following is an example extracted from core-items.xml
:
• Map types, they are type collections of key/value pairs, they are intensively used under SAP
Hybris for localized elements, for example when you use localized:java.lang.String, following
is an example extracted from core-items.xml :
<maptype code="localized:java.lang.String"
argumenttype="Language"
returntype="java.lang.String"
autocreate="true"
generate="false"/>
• Relation types, they are the way to go to represent n:m relations, internally SAP Hybris
links both element via an instance of an helper type called LinkedItem. LinkedItem holds 2
attributes, SourceItem and TargetItem. When SAP Hybris runs a search query on either side
of the relation it returns a java Collection that contain all values, following is an example
extracted from core-items.xml :
• Item types, also called composed types are the main type used to build SAP Hybris platform,
all types are derived of a ComposedType. It holds metadata about the types like the item’s
type code, the JNDI deployment location, the database table deployment and the type’s java
class. The following is an example extracted from core-items.xml:
<itemtype code="Title"
extends="GenericItem"
jaloclass="de.hybris.platform.jalo.user.Title"
autocreate="true"
generate="true">
<!-- deployment="de.hybris.platform.persistence.user.Title" -->
<deployment table="Titles" typecode="24"/>
<attributes>
<attribute autocreate="true" qualifier="code" type="java.lang.String">
<persistence type="property"/>
<modifiers read="true" write="true" search="true" initial="true"
֒→ optional="false" unique="true"/>
<custom-properties>
<property name="hmcIndexField">
<value>"thefield"</value>
</property>
</custom-properties>
</attribute>
<attribute autocreate="true" qualifier="name" type="localized:java.lang.String">
<modifiers read="true" write="true" search="true" optional="true"/>
<persistence type="property"/>
<custom-properties>
<property name="hmcIndexField">
<value>"thefield"</value>
</property>
</custom-properties>
</attribute>
</attributes>
<indexes>
<index name="codeIdx">
<key attribute="code"/>
</index>
</indexes>
</itemtype>
<enumtypes>
<enumtype code="PostStatus">
<value code="DRAFT"/>
<value code="PUBLISHED"/>
<value code="DELETED"/>
</enumtype>
<enumtype code="CommentStatus">
<value code="PENDING"/>
<value code="APPROVED"/>
<value code="BLOCKED"/>
</enumtype>
</enumtypes>
• Post
• Blog
• PostComment
When you create new item types it is mandatory to specify a deployment table, or the
build would fail (you can deactivate this check with build.development.mode=false)
<itemtypes>
<itemtype code="Blog" extends="GenericItem" autocreate="true" generate="true">
<deployment table="blog" typecode="11001" />
<attributes>
<attribute qualifier="code" type="java.lang.String">
<modifiers initial="true" read="true" write="false"
֒→ optional="false" unique="true" />
<persistence type="property" />
</attribute>
<attribute qualifier="active" type="boolean">
<persistence type="property" />
</attribute>
</attributes>
</itemtype>
When you run ant all the SAP Hybris platform, the build framework will:
• Generate Model classes for the service layer (for example BlogModel)
• Abstract Jalo layer classes, starting with Generated (for example GeneratedBlog)
• Non abstract Jalo layer classes, with the same name as the item type (for example Blog)
Jalo is deprecated since Hybris V4.3, however not all logic have been moved to the
service layer. If you don’t plan to use the Jalo layer with your item types you can use
generate="false"
Once you have build the platform successfully, you will need to update your system so SAP Hybris
can update the database with the new item types definition (using the HAC or ant initialize).
Check that all new types, relations and enumtypes are available from the backoffice (filter types
per extension, in my case they are under hybhubaddon extension):
![Backoffice types](images/backoffice-types.png)
We can see that all newly defined items are available in our current system.
INSERT_UPDATE Blog;code[unique=true];active[default=true]
;myBlog;
INSERT_UPDATE Post;date[unique=true][dateformat=dd-MM-yyyy];Blog(code);author(uid)
;01-01-2016;myBlog;admin
INSERT_UPDATE PostComment;content[unique=true];author(uid);status(code);
;This is the content;admin;PENDING
• Products will have a boolean to activate (or not) an export to Google Shopping
Update your system and check from the backoffice that new attributes have been added to your
types:
![Product new attribute](images/backoffice-product-newAttr.png)
![Customer new attribute](images/backoffice-customer-newAttr.png)
New attributes are also available from the model service.
Localized Attributes
Localized attribute type is an essential type under SAP Hybris platform, it gives you the ability
to dynamically server different content (text, image, link...) based on the user language.
An example would be the product name:
When an item type has a localized attribute, SAP Hybris will automatically create an extra
database table ending with lp, for example Product type has the table productslp :
94 CHAPTER 5. COMMERCE AND ACCELERATOR
Each localized attribute of an item is grouped in this table and linked to a language through
LANGPK.
The model service will create getters and setters like this :
/**
* <i>Generated method</i> - Getter of the <code>Product.description</code> attribute
֒→ defined at extension <code>core</code>.
* @return the description
*/
@Accessor(qualifier = "description", type = Accessor.Type.GETTER)
public String getDescription()
{
return getDescription(null);
}
/**
* <i>Generated method</i> - Getter of the <code>Product.description</code> attribute
֒→ defined at extension <code>core</code>.
* @param loc the value localization key
* @return the description
* @throws IllegalArgumentException if localization key cannot be mapped to data language
*/
@Accessor(qualifier = "description", type = Accessor.Type.GETTER)
public String getDescription(final Locale loc)
{
return getPersistenceContext().getLocalizedValue(DESCRIPTION, loc);
}
You can get the product description using a Locale object or not, if you don’t provide any SAP
Hybris will load the default one (see de.hybris.platform.servicelayer.model.ItemModelContextImpl).
5.10. DATA MODELING 95
<maptype code="localized:java.lang.String"
argumenttype="Language"
returntype="java.lang.String"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Integer"
argumenttype="Language"
returntype="java.lang.Integer"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Boolean"
argumenttype="Language"
returntype="java.lang.Boolean"
autocreate="true"
generate="false"/>
....
Therefore to declare an attribute as localized, first check if the type has a declared localized
equivalent (SAP Hybris 6 has all atomic types, bigInteger, bigDecimal, date range and media).
If not you could create your own localized type, for example lets say you need to localize groups :
<maptype code="localized:Group"
argumenttype="Language"
returntype="UserGroup"
autocreate="true"
generate="false"/>
Enumerations
SAP Hybris gives you the possibility to use attributes with a predefined list of possible values.
This works exactly like Java enumeration but at a database level.
Enumeration types within SAP Hybris could be dynamic, it means you could add new
values during runtime. If you configure your enumeration not to be dynamic SAP
Hybris will use standard Java enumeration instead of SAP Hybris enumerations
How to create a new enumeration ? Add it under the targeted items.xml file:
96 CHAPTER 5. COMMERCE AND ACCELERATOR
You can add new values from a different extension if needed, for example the OrderStatus enumer-
ation is defined within the core extension, from my extension hybhubaddon I’m adding a new value
:
Enumeration Service
SAP Hybris provides a service to deal with enumeration, de.hybris.platform.enumeration.EnumerationService,
here is an example (Groovy compatible) to get the new OrderStatus we just created (you need to
build and update your SAP Hybris platform) :
import de.hybris.platform.enumeration.EnumerationService;
import de.hybris.platform.core.enums.OrderStatus;
EnumerationService es = spring.getBean("enumerationService");
OrderStatus os = es.getEnumerationValue("ORDERSTATUS", "MYSTATUS");
println os.getCode();
Dynamic attributes
In some cases, you will need dynamic attributes, for example under the address model you have
one field for each address characteristics, it would be nice to have directly under your model object
a getter for a formatted address string, right? That’s when you use a dynamic attribute when you
need attributes on your data model objects which aren’t persisted to the database.
Use dynamic attributes to:
Let’s add a dynamic attribute to our PostComment item type, we want to have a summary of each
comment with something like "PENDING - Luke T - Hi, I recently bought a new camera to start
doing prof..." :
Attribute Handler value is the name of the Spring bean that is responsible for the
dynamic attribute.
98 CHAPTER 5. COMMERCE AND ACCELERATOR
Next step is to create the class to handle the dynamic attribute, we will call it ‘DynamicAttribute-
sPostCommentSummaryHandler’:
package com.hybhub.hybhubaddon.servicelayer.dynamicattributes;
import de.hybris.platform.servicelayer.model.attribute.DynamicAttributeHandler;
import com.hybhub.hybhubaddon.model.PostCommentModel;
@Override
public String get(final PostCommentModel postComment)
{
final StringBuilder sb = new
֒→ StringBuilder(postComment.getStatus().getCode());
sb.append(SEP);
sb.append(postComment.getAuthor().getDisplayName());
sb.append(SEP);
sb.append(postComment.getContent().length() > MAX_CONTENT ?
֒→ postComment.getContent().substring(0, MAX_CONTENT)
: postComment.getContent());
return sb.toString();
}
@Override
public void set(final PostCommentModel postComment, final String str)
{
throw new IllegalAccessError("Cannot set that attribute [Summary]");
}
This class needs to implement ‘DynamicAttributeHandler’ interface, it will provide two methods,
a getter and a setter, here we will just use the getter and throw an exception if the setter is used.
Next step is to register this newly created class in a bean context:
And then build and run an update on your system, to try it we will use a groovy script, go to
http://localhost:9001/console/scripting/ :
5.10. DATA MODELING 99
import com.hybhub.hybhubaddon.model.PostCommentModel
import de.hybris.platform.servicelayer.model.ModelService
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import java.util.List
import de.hybris.platform.servicelayer.user.UserService
UserService us = spring.getBean("userService")
ModelService ms = spring.getBean("modelService")
FlexibleSearchService fss = spring.getBean("flexibleSearchService")
If you open the output tab you should see : PENDING - Administrator - This is the content of
the PostComment
Deployment
SAP Hybris item types are stored inside database’s tables, each instance is stored as one row within
the database.
The database table where instances of a type are stored is called the type deployment and is
specified within items.xml files. Every type must have a deployment table to store its instances.
Types inherits deployment tables from their super types. The deployment that is active for a
given type is the deployment specified closest to the type in the type’s hierarchy. The topmost
deployment is GenericItem, which is therefore the default deployment. This means if a type has
no explicit specification of deployment, that type’s instances are deployed in the same table as
GenericItem.
This means that the default deployment of any subtype, which you extend from GenericItem, is the
deployment of GenericItem. In other words: if you do not specify a deployment for a subtype of
GenericItem, the instances of that subtype are stored in the same table as instances of GenericItem.
For example, the User and Product types in SAP Hybris Commerce are subtypes of GenericItem.
If there were no deployment specified for User and Product, all Users and Products instances would
be written into one single database table. Firstly, this is not intuitive. Secondly, storing instances
of many different types in one single database table causes that database table to have quite a
lot of columns to store all attributes from all these types (a User has different attributes than a
Product, and both types needs to store attribute values).
Not declaring a deployment table for a new item type (extending GenericItem) would lead the build
to fail : [ycheckdeployments] No deployment defined for relation <RELATIONNAME> in file:
<FILENAME> If you want to force this behavior besides the performance and schema complexity
bottlenecks you could use : build.development.mode=true
To specify your own deployment table:
100 CHAPTER 5. COMMERCE AND ACCELERATOR
The deployment attribute also has a propertytable attribute, this is to configure different advanced
database features (database attribute types).
Indices
SAP Hybris gives you the ability to add database indices on item types, indices have a name and
one or more keys (composite indices), here is an example of an index on the blog type:
<indexes>
<index name="blogIDX" unique="true">
<key attribute="code" lower="true"/>
<key attribute="active"/>
</index>
</indexes>
SAP Hybris will run the following SQL command (may vary upon the targeted database, here we
use HSQL):
Types in DB
When SAP Hybris generates the SQL commands to initialize the system, it will select the right
destination types based on the current database, there is a out of the box mapping for this, have
a look at the file core-advanced-deployment.xml, for example for Mysql :
5.10. DATA MODELING 101
To see what commands SAP Hybris uses to create your item types you can use the dry-run
functionality ([Dry Run](http://localhost:9001/platform/dryrun)), for example for our Post type
on HSQL SAP Hybris will execute :
102 CHAPTER 5. COMMERCE AND ACCELERATOR
Warning!
Flexible Search Queries are executed on the database trough a SQL query, therefore it is
not possible to execute flexible search queries on Jalo or dynamic attributes.
5.11. FLEXIBLE SEARCH QUERY 103
Cache
SAP Hybris is caching flexible search query results, that is the reason why you should always
deactivate the query cache on your database when you go on production. On Mysql it’s deactivated
by default, but if you are not sure simply add this line to your my.cnf configuration:
query_cache_size=0
Flexible search queries are executed in a session context, different factors can influence the number
of search results:
• The session user, by default the session is assigned the anonymous user, you could assign the
session to any available user (including admin user)
• Restrictions, they are fragments of the SQL where clause that are applied for a given item
type. No restrictions are applied when you run a flexible search query with an admin session.
Restrictions
Do not get flexible search query restrictions mixed up with CMS restrictions ! On is
only adding filters in the SQL where clause while the other has its own java imple-
mentation.
Restrictions are manageable from the SearchRestrictionService:
104 CHAPTER 5. COMMERCE AND ACCELERATOR
package de.hybris.platform.search.restriction;
import de.hybris.platform.core.model.security.PrincipalModel;
import de.hybris.platform.core.model.type.ComposedTypeModel;
import de.hybris.platform.core.model.type.SearchRestrictionModel;
import de.hybris.platform.search.restriction.session.SessionSearchRestriction;
import java.util.Collection;
You could activate or deactivate the search restriction from the restriction service, or create/update/delete
existing restrictions.
Another way to create restrictions is Impex:
INSERT_UPDATE SearchRestriction;code[unique=true];name[lang=en];query;principal(UID);restric ⌋
֒→ tedType(code);active;generate
;Restriction_Code;Restriction Name;{Active} = true;anonymous;Language;true;true
Here we create a restriction for anonymous users, they would see only the active languages. For
example when you run this flexible search query (anonymous user):
5.11. FLEXIBLE SEARCH QUERY 105
SAP Hybris will execute this SQL query (pay attention to the WHERE clause where our restriction
is added:
You could also create restriction from the hmc or the backoffice, they are called Personalization
Rule
Syntax
Flexible search queries are very similar to SQL queries, although it is dedicated only for search.
It abstracts all the database details (columns and tables name), it is translated into native SQL
query on execution. The basic syntax of a flexible search query looks like this:
• Select is mandatory
• types is mandatory
• conditions is optional
• order is optional
All standard select SQL keywords are available (ORDER BY,AS,IS NULL,...) and you also need
to remember this:
• By default SAP Hybris will search for the given type and any subtype, if you want the query
only to search for the given item type you need to use an exclamation mark, select {code}
from {Product!}
• JOIN can be made inside the curly braces, {Product as prd join PriceRow as price on
{prd:code} = {price:productId}}
• WHERE clauses can execute sub queries using double curly braces
• To work with localized attributes you need to specify the language {Name[en]} to select an
attribute. If you want to match a localized attribute inside a WHERE clause you can use
{Desc[de]} to match exactly one language or {Desc[ANY} to match any language
106 CHAPTER 5. COMMERCE AND ACCELERATOR
• Parameters are passed using the question mark, where {date} > ?startDate
• Outer join parameter, it is used to include matches with missing rows inside the localized
table (xxxxxLP), for example :
SELECT {p:PK}
FROM {Product AS p}
WHERE {p:description[en]:o} LIKE ’%text%’
OR {p:description[de]:o} LIKE ’%text%’
If you use ! after a type SAP Hybris won’t load any sub types, for example from {product!} will
load only Product type items.
Examples
All users
select {name[en]}, {OnlineDate} from {Product} where {code} in ( {{ select {code} from
֒→ {Product} where {OnlineDate} > ’2016-01-01 00:00:00.0’ }} )
You can test all flexible search queries directly from the HAC.
package de.hybris.platform.servicelayer.search;
import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.RelationQuery;
import de.hybris.platform.servicelayer.search.SearchResult;
import de.hybris.platform.servicelayer.search.TranslationResult;
import java.util.List;
import java.util.Map;
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery
import de.hybris.platform.servicelayer.search.SearchResult
import de.hybris.platform.core.model.product.ProductModel
println result.getTotalCount()
Product Variants
When you work with products you often need to model variants, a variant represent a variation of
a base product. It has attributes from the base product, and defines its own variation attributes.
For example let’s define laptops, they are Products with specific attributes like the screen size and
variants with specific attributes like the disk capacity.
5.12. PRODUCT VARIANTS & CATEGORY VARIANTS 109
<enumtypes>
<enumtype code="ScreenSize">
<value code="THIRTEEN" />
<value code="FOURTEEN" />
<value code="FIFTEEN" />
</enumtype>
</enumtypes>
<itemtypes>
<itemtype code="Laptop" extends="Product" autocreate="true" generate="true">
<attributes>
<attribute qualifier="ScreenSize" type="ScreenSize">
<persistence type="property" />
</attribute>
</attributes>
</itemtype>
This is a bad idea, since it is described on the variant level, you need to define a screen size for all
110 CHAPTER 5. COMMERCE AND ACCELERATOR
Category Variants
A different approach is to build category variants with specific attributes. For example our laptop
category has a screen size attribute:
How to create a new product : You cannot create your first VariantCategory from an im-
pex unless you skip the service layer VariantValueCategoryValidateInterceptor. You
could also manually create one from the HMC and then use it as the super category
5.13. CLASSIFICATION ATTRIBUTES 111
$productCatalog=electronicsProductCatalog
$productCatalogName=Electronics Product Catalog
$catalogVersion=catalogversion(catalog(id[default=$productCatalog]),version[default=’Staged’ ⌋
֒→ ])[unique=true,default=$productCatalog:Staged]
$supercategories=supercategories(code, $catalogVersion)
$baseProduct=baseProduct(code,$catalogVersion)
$approved=approvalstatus(code)[default=’check’]
# Insert Categories
INSERT_UPDATE LaptopCategory;code[unique=true];name[lang=en];ScreenSize(code);$supercategori ⌋
֒→ es;$catalogVersion
;000100;Laptop;THIRTEEN;1
;000101;Laptop;FIFTEEN;1
INSERT_UPDATE Product;code[unique=true];$supercategories;manufacturerName;manufacturerAID;un ⌋
֒→ it(code);variantType(code);$catalogVersion;$approved
;000010;000100;Apple;MBP-13;pieces;LaptopVariant
;000011;000100;Apple;MBP-15;pieces;LaptopVariant
INSERT_UPDATE LaptopVariant;code[unique=true];$baseProduct;unit(code);diskCapacity;approvals ⌋
֒→ tatus(code)[default=’approved’];$catalogVersion
;000100_256;000010;pieces;256;
;000100_512;000010;pieces;512;
;000101_256;000011;pieces;256;
;000101_512;000011;pieces;512;
We now have a base laptop which holds the screen size through the category variant, and a variant
attribute disk capacity. We did all this without changing the product model !
The downside of this is that the value of the screen size is held by the category and
not the product.
Classification attributes
SAP Hybris gives you the possibility to classify your product, what is the difference between
classification and categorization ?
• You can categorize your laptop with : Electronic -> Computer -> Laptop.
• You can classify your laptop with its color, its screen size, its disk capacity...
$productCatalog=electronicsProductCatalog
$productCatalogName=Electronics Product Catalog
$catalogVersion=catalogversion(catalog(id[default=$productCatalog]),version[default=’Staged’ ⌋
֒→ ])[unique=true,default=$productCatalog:Staged]
$classCatalogVersion=catalogversion(catalog(id[default=’ElectronicsClassification’]),version ⌋
֒→ [default=’1.0’])[unique=true,default=’ElectronicsClassification:1.0’]
$classSystemVersion=systemVersion(catalog(id[default=’ElectronicsClassification’]),version[d ⌋
֒→ efault=’1.0’])[unique=true]
$class=classificationClass(ClassificationClass.code,\$classCatalogVersion)[unique=true]
$supercategories=supercategories(code, $catalogVersion)
$supercategoriesRel=source(code, $classCatalogVersion)[unique=true]
$categories=target(code, $catalogVersion)[unique=true]
$attribute=classificationAttribute(code,$classSystemVersion)[unique=true]
$unit=unit(code,$classSystemVersion)
$approved=approvalstatus(code)[default=’check’]
$baseProduct=baseProduct(code,$catalogVersion)
$clAttrModifiers=system=’ElectronicsClassification’,version=’1.0’,translator=de.hybris.platf ⌋
֒→ orm.catalog.jalo.classification.impex.ClassificationAttributeTranslator,lang=en
# Insert Classifications
INSERT_UPDATE ClassificationClass;$classCatalogVersion;code[unique=true];name[lang=en];allow ⌋
֒→ edPrincipals(uid)[default=’customergroup’]
;;2002;Laptop
INSERT_UPDATE ClassAttributeAssignment;$class;$attribute;position;$unit;attributeType(code[d ⌋
֒→ efault=string]);multiValued[default=false];range[default=false];localized[default=false]
;2002;screen size;1;16;number;false;false
INSERT_UPDATE CategoryCategoryRelation;$categories;$supercategoriesRel
;1;2002
$feature1=@screen size[$clAttrModifiers];
INSERT_UPDATE Product;code[unique=true];$supercategories;manufacturerName;manufacturerAID;un ⌋
֒→ it(code);variantType(code);$feature1;$catalogVersion;$approved
;000010;1;Apple;MBP-13;pieces;LaptopVariant;13
;000011;1;Apple;MBP-15;pieces;LaptopVariant;15
INSERT_UPDATE LaptopVariant;code[unique=true];$baseProduct;unit(code);diskCapacity;approvals ⌋
֒→ tatus(code)[default=’approved’];$catalogVersion
;000100_256;000010;pieces;256;
;000100_512;000010;pieces;512;
;000101_256;000011;pieces;256;
;000101_512;000011;pieces;512;
The same product could be classified from two different classification trees ! It offers a lot of
flexibility and it can be modified without changing the SAP Hybris model type!
Chapter 6
Order management
113
114 CHAPTER 6. ORDER MANAGEMENT
Through this chapter, you will learn how to work with orders within a SAP Hybris e-commerce
system.
Business process
You now need to define your process, create a new file named myprocess-process.xml under /re-
sources/hybhubaddon/process/, my extension is hybhubaddon :
6.1. BUSINESS PROCESS 115
</process>
• Notify nodes - inform a user or user group about the state of a process;
• Action nodes - carry out process logic and permit alternative actions to be carried out;
• End nodes - end the process and store state in a process item.
package com.hybhub.hybhubaddon.actions.myprocess;
import de.hybris.platform.processengine.action.AbstractSimpleDecisionAction;
import de.hybris.platform.task.RetryLaterException;
import com.hybhub.hybhubaddon.model.MyProcessModel;
return Transition.OK;
}
}
Second step, will return success or error based on the error flag
package com.hybhub.hybhubaddon.actions.myprocess;
import de.hybris.platform.processengine.action.AbstractSimpleDecisionAction;
import de.hybris.platform.task.RetryLaterException;
import com.hybhub.hybhubaddon.model.MyProcessModel;
package com.hybhub.hybhubaddon.actions.myprocess;
import de.hybris.platform.processengine.action.AbstractSimpleDecisionAction;
import de.hybris.platform.task.RetryLaterException;
import org.apache.log4j.Logger;
import com.hybhub.hybhubaddon.model.MyProcessModel;
@Override
public Transition executeAction(final MyProcessModel myProcess) throws
֒→ RetryLaterException, Exception
{
LOG.error("The process " + myProcess.getCode() + " failed !");
return Transition.OK;
}
}
<bean id="myProcess"
֒→ class="de.hybris.platform.processengine.definition.ProcessDefinitionResource" >
<property name="resource"
֒→ value="classpath:/hybhubaddon/process/myprocess-process.xml"/>
</bean>
import com.hybhub.hybhubaddon.model.MyProcessModel
import de.hybris.platform.servicelayer.model.ModelService
import de.hybris.platform.processengine.BusinessProcessService
modelService.save(myprocess)
bpService.startProcess(myprocess)
modelService.refresh(myprocess)
println myprocess.state
You can play around with the two flags and check the result in the HMC. You can see the process
state, and the log for each step.
Fulfillment process
In this chapter, we study the order fulfillment process. This process is triggered when the customer
triggers the place order action, then SAP Hybris will execute a set of actions to fulfill the order.
Here is the list of all possible transitions for the order fulfillment process :
2. Check authorize payment, check that the current order has a payment info attached.
4. Send payment failed notification, publish an event for the failed authorization.
5. Check transaction review status, check that the transaction has been authorized.
6. Fraud check, check couple of criteria to detect potential fraud (excessive amount, black listed
customer,....).
7. Notify customer about fraud, contact the customer about the fraudulent order.
8. Manual order check CSA, prepare the order to be manually checked by a customer agent.
9. Order manual checked, take the decision to follow the fulfillment process after the manual
check or not.
12. Send order placed notification, send a notification to the customer after his order has been
successfully placed.
13. Take payment action, capture the payment.
14. Send payment failed notification, send a message to the customer after a failed capture
attempt.
15. Split order, try to split the order in multiple consignment.
16. Is process completed, watch for the waitForWarehouseSubprocessEnd to end before moving
on with the fulfillment.
17. Send order completed notification, order has been shipped and is a success.
1. A customer access the store front, Hybris will create a new session, at that point no carts
have been created yet.
2. The customer adds a product.
(a) The cart service (cartService) will try to load the cart from the session. In our case
the customer has no cart yet, so the cart factory (cartFactory) will handle the cart
creation (generate a code, add user, add currency, set the date). It could be a stan-
dard persisted cart or a in memory cart (not persisted), for this you need to configure
default.session.cart.type (Cart, InMemoryCart or your own implementation).
(b) The commerce add to cart strategy (CommerceAddToCartStrategy) will add a new entry
into the cart entry collection, then it will mark the cart as not calculated.
(c) The calculation service (CalculationService) will calculate the total price of the cart.
(a) Before the checkout process, the customer will log-in or create a new account (guest
account for example). During this log-in phase the cart will be attached to the customer
account.
(b) During the checkout process the customer will add or select a delivery address, attach
payment info...
(c) When the Customer places the order, the order is created by making a copy of the cart
(order entries as well).
120 CHAPTER 6. ORDER MANAGEMENT
Checkout flow
SAP Hybris gives you the possibility to configure the entire checkout flow independently for each
store (since V5.2). All configuration is done using Spring beans and interface implementation.
SAP Hybris checkout is configured with:
1. Checkout steps, they hold information about the next, previous and current link, about the
validator to use (oftenly the controller is marked with a PreValidateStep annotation).
2. A validate result map, based on the different validation success or fail the checkout flow
will often need to redirect the process to a given step, to hold the different redirection the
checkout group has a string map with entry like REDIRECT_TO_DELIVERY_ADDRESS
that would point to a spring MVC redirection redirect:/checkout/multi/delivery-address/add
3. The checkout flow progress bar, it is a map with each step ordered by the number in which
they are populated under the progress bar
To create a new checkout flow you need to create a new bean from the class de.hybris.platform.acceleratorstorefrontcom
this is an example of the out of the box checkout flow configured with an extra step. Since multiple
checkout flows can live under the same system instead of updating the existing flow we declare a
new one named defaultHybhubCheckoutGroup with a alias hybhubCheckoutGroup:
6.4. CHECKOUT FLOW 121
<alias name="defaultHybhubDeliveryAddressCheckoutStep"
֒→ alias="hybhubDeliveryAddressCheckoutStep" />
<bean id="defaultHybhubDeliveryAddressCheckoutStep" parent="checkoutStep">
<property name="checkoutGroup" ref="hybhubCheckoutGroup"/>
<property name="checkoutStepValidator"
֒→ ref="defaultResponsiveDeliveryAddressCheckoutValidator"/>
<property name="transitions">
<map merge="true">
<entry key="previous" value-ref="REDIRECT_TO_HYBHUB"/>
<entry key="current" value-ref="REDIRECT_TO_DELIVERY_ADDRESS"/>
<entry key="next" value-ref="REDIRECT_TO_DELIVERY_METHOD"/>
</map>
</property>
<property name="progressBarId" value="deliveryAddress"/>
</bean>
You may have noticed that our Hybhub step is validated by hybhubValidator; it’s an implementation
of de.hybris.platform.acceleratorstorefrontcommons. checkout.steps.validation.AbstractCheckoutStepValidator
which lets you validate the step controller on enter and on exit. Here is our implementation for
the hybhub step:
6.4. CHECKOUT FLOW 123
package com.hybhub.storefront.checkout.steps.validation.impl;
import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps.validation.AbstractChe ⌋
֒→ ckoutStepValidator;
import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps.validation.ValidationR ⌋
֒→ esults;
import de.hybris.platform.commercefacades.order.data.CartData;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Override
public ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes)
{
final CartData cartData = getCheckoutFacade().getCheckoutCart();
LOG.info("Validating on enter with Hybhub Validator cart : " +
֒→ cartData.getCode());
return ValidationResults.SUCCESS;
}
@Override
public ValidationResults validateOnExit()
{
final CartData cartData = getCheckoutFacade().getCheckoutCart();
LOG.info("Validating on exit with Hybhub Validator cart : " +
֒→ cartData.getCode());
return ValidationResults.SUCCESS;
}
}
package com.hybhub.storefront.controllers.pages.checkout.steps;
import de.hybris.platform.acceleratorstorefrontcommons.annotations.PreValidateCheckoutStep;
import de.hybris.platform.acceleratorstorefrontcommons.annotations.RequireHardLogIn;
import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps.CheckoutStep;
import de.hybris.platform.acceleratorstorefrontcommons.constants.WebConstants;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.pages.checkout.steps.Abst ⌋
֒→ ractCheckoutStepController;
import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
@RequestMapping(value = "/checkout/multi/hybhub")
public class HybhubStepController extends AbstractCheckoutStepController
{
private static final String HYBHUB = "hybhub";
@RequestMapping(method = RequestMethod.GET)
@RequireHardLogIn
@Override
@PreValidateCheckoutStep(checkoutStep = HYBHUB)
public String enterStep(final Model model, final RedirectAttributes
֒→ redirectAttributes) throws CMSItemNotFoundException
{
this.prepareDataForPage(model);
storeCmsPageInModel(model, getContentPageForLabelOrId(HYBHUB));
setUpMetaDataForContentPage(model, getContentPageForLabelOrId(HYBHUB));
model.addAttribute(WebConstants.BREADCRUMBS_KEY,
getResourceBreadcrumbBuilder().getBreadcrumbs("checkout.mult ⌋
֒→ i.deliveryMethod.breadcrumb"));
model.addAttribute("metaRobots", "noindex,nofollow");
setCheckoutStepLinksForModel(model, getCheckoutStep());
return "pages/checkout/multi/hybhubPage";
}
<div class="row">
<div class="col-sm-6">
<div class="checkout-headline">
<span class="glyphicon glyphicon-lock"></span>
<spring:theme code="checkout.multi.secure.checkout" text="Secure
֒→ Checkout"></spring:theme>
</div>
<multi-checkout:checkoutSteps checkoutSteps="\${checkoutSteps}"
֒→ progressBarId="hybhubStep">
<jsp:body>
<ycommerce:testId code="hybhub">
<a href=’<spring:url value="\${nextStepUrl}"/>’
֒→ type="button" class="btn btn-primary btn-block checkout-next"><spring:theme
֒→ code="checkout.multi.hybhub.continue" text="Next"/></a>
</ycommerce:testId>
</jsp:body>
</multi-checkout:checkoutSteps>
</div>
<div class="col-sm-6 hidden-xs">
<h1>This is the Hybhub step</h1>
</div>
</div>
</template:page>
$contentCatalog=electronicsContentCatalog
$contentCV=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),Catalo ⌋
֒→ gVersion.version[default=Staged])[default=$contentCatalog:Staged]
INSERT_UPDATE ContentPage;$contentCV[unique=true];uid[unique=true];name;masterTemplate(uid,$ ⌋
֒→ contentCV);label;defaultPage[default=’true’];approvalStatus(code)[default=’approved’];h ⌋
֒→ omepage[default=’false’];
;;hybhub;Hybhub Page;MultiStepCheckoutSummaryPageTemplate;hybhub
Don’t forget to run a synchronization or to change the catalog to the Online one,
126 CHAPTER 6. ORDER MANAGEMENT
INSERT_UPDATE BaseStore;uid[unique=true];checkoutFlowGroup;
;electronics;hybhubCheckoutGroup;
Go to the store front, and checkout your cart. You should now see your new step!
ASM
SAP Hybris provides an Assister Service Module. It gives the customer service employees the
ability to assist customers in real time using the same interface as the end customer - the store
front. The ASM module is compatible with all SAP Hybris accelerator store front (B2C, B2B and
Telco).
In order to install the ASM module you need to add the asm extensions into your localexten-
sions.xml file:
<extension name="assistedservicefacades"/>
<extension name="assistedservicestorefront"/>
You also need to install the assistedservicestorefront addon into your store front extension. Here
my store front is named hybhubstorefront; remember to use your store front name. From SAP
Hybris platform/bin folder run :
Now start your server and run a system update (with assistedservicefacades and assistedser-
vicestorefront selected), when it’s finished, access your store front with this URL parameter
asm=true, for example to access my electronic store front on my localhost for development I
use : <a>http://localhost:9001/hybhubstorefront/?site=electronics&asm=true</a>.
The default user login / password is asagent / 123456.
You should see this :
You need to remember that from the ASM perspective you can:
• Find a customer’s account and session or an anonymous cart;
• Map an anonymous cart to an existing customer;
• Help a customer to create a new account;
6.6. CS COCPKIT 127
CS Cocpkit
SAP Hybris provides a Customer Service Cockpit. It uses the cockpit framework (and not the next
generation cockpit framework). This cockpit is loaded from the cscockpit cockpit extension and
available from : <a>http://localhost:9001/cscockpit/</a>. It is meant to be used by operators in
a call center environment for customers, pre-sales and post sales operations.
We recall that from the customer service cockpit, operators can do the following :
• Take payment;
• Manage order’s delivery mode and address;
• Manage subscription products.
The current customer cockpit will probably be reimplemented by SAP Hybris using
the NG Cockpit framework
128 CHAPTER 6. ORDER MANAGEMENT
131
132 CHAPTER 7. SEARCH AND NAVIGATION
SAP Hybris provides fast and customizable search and navigation with the help of an Apache
SOLR server ([More information](http://lucene.apache.org/solr/)).
Solr index
A SOLR index is a fast text search database for products (or any other kind of data). In order to
use a SOLR index you need:
• A SolrServerConfig, which defines the connections between SAP Hybris and the Apache
SOLR node(s).
– Standalone or Embedded (standalone is now the default and it’s the preferred way of
running SOLR as it’s how most systems in production run)
– Embedded Master, to decide if only one SOLR server should take care of all index
operations
– Alive check interval, interval between check for a running system
– Connection timeout, timeout before SAP Hybris considers a connection attempt a failure
– Socket timeout, timeout before SAP Hybris considers a socket access a failure
– Total connections, total open connections to SOLR
– Total connections per host, total connections per SOLR host
– List of endpoints, representing all the SOLR server
– Use Master node exclusively for indexing, will force SAP Hybris to access only non
master nodes and to reserve master nodes for indexing operations only
– Error handling, you can configure the behavior of the indexing process when an error is
raised
• A SolrSearchConfig.
– Result page size
– Restrict field in response
– Include all facets in response
• A SolrIndexedType, defines the type of item to index and what attributes.
We will create 2 new properties for our product index: one facet property from the exportTo-
GoogleShopping and the other free text search property from lastCustomerReview:
exportToGoogleShopping facet :
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true] ⌋
֒→ ;type(code);sortableType(code);currency[default=false];localized[default=false];multiVa ⌋
֒→ lue[default=false];facet[default=true];facetType(code);facetSort(code);priority;visible ⌋
֒→ ;useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvide ⌋
֒→ r;valueProviderParameter;facetDisplayNameProvider;customFacetSortProvider;topValuesProv ⌋
֒→ ider;rangeSets(name)
;electronicsProductType;exportToGoogleShopping;boolean;;;;false;;MultiSelectAnd;;100;true;;; ⌋
֒→ springELValueProvider;getExportToGoogleShopping();;
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true] ⌋
֒→ ;type(code);sortableType(code);currency[default=false];localized[default=false];multiVa ⌋
֒→ lue[default=false];facet[default=false];facetType(code);facetSort(code);priority;visibl ⌋
֒→ e;useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvid ⌋
֒→ er;valueProviderParameter;ftsQuery;ftsQueryBoost;ftsQueryMinTermLength;ftsWildcardQuery ⌋
֒→ ;ftsWildcardQueryBoost;ftsWildcardQueryMinTermLength;includeInResponse
;electronicsProductType;lastCustomerReview;string;;;;;;;;100;true;;;springELValueProvider;ge ⌋
֒→ tLastCustomerReview();true;500;5;true;100;10;false
In order to add a new free text attribute you need to configure the solr search configuration with
legacy mode to false, or to update the commerceSearchTextPopulator bean and add your new field,
in our case lastCustomerReview :
7.2. SOLR INDEXED PROPERTY 135
INSERT_UPDATE SolrSearchConfig;description[unique=true];pageSize;legacyMode
;electronicsPageSize;20;false
After running a full index job, and adding data both for exportToGoogleShopping and
lastCustomerReview look for products from your store front, you should see the new
facets and results from the two attribute providers. Combinations are limitless
The recommended way to create a new value provider is to create a new implementation of the ab-
stract class de.hybris.platform.solrfacetsearch.provider.impl.AbstractValueResolver<T extends Item-
Model, MDATA, QDATA>, the only abstract method that you have to implement is addField-
Values, here is an example of a simple value provider for our exportToGoogleShop-
ping attribute :
package com.hybhub.hybhubaddon.search.solrfacetsearch.provider.impl;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.solrfacetsearch.config.IndexedProperty;
import de.hybris.platform.solrfacetsearch.config.exceptions.FieldValueProviderException;
import de.hybris.platform.solrfacetsearch.indexer.IndexerBatchContext;
import de.hybris.platform.solrfacetsearch.indexer.spi.InputDocument;
import de.hybris.platform.solrfacetsearch.provider.impl.AbstractValueResolver;
@Override
protected void addFieldValues(final InputDocument inputDocument, final
֒→ IndexerBatchContext IndexerBatchContext,
final IndexedProperty indexedProperty, final ProductModel
֒→ productModel,
final ValueResolverContext<Object, Object> valueResolverContext)
֒→ throws FieldValueProviderException
{
inputDocument.addField(indexedProperty,
productModel.getExportToGoogleShopping() == null ?
֒→ Boolean.FALSE : productModel.getExportToGoogleShopping(),
valueResolverContext.getFieldQualifier());
}
We need to create a Spring bean for our value provider; it must have abstractValueResolver as
a parent bean definition:
136 CHAPTER 7. SEARCH AND NAVIGATION
<bean id="productExportToGS"
֒→ class="com.hybhub.hybhubaddon.search.solrfacetsearch.provider.impl.ProductExportToGS"
parent="abstractValueResolver"/>
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true] ⌋
֒→ ;type(code);sortableType(code);currency[default=false];localized[default=false];multiVa ⌋
֒→ lue[default=false];facet[default=true];facetType(code);facetSort(code);priority;visible ⌋
֒→ ;useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvide ⌋
֒→ r;valueProviderParameter;facetDisplayNameProvider;customFacetSortProvider;topValuesProv ⌋
֒→ ider;rangeSets(name)
;electronicsProductType;exportToGoogleShopping;boolean;;;;false;;MultiSelectAnd;;100;true;;; ⌋
֒→ productExportToGS;;;
Run a full indexation, you should now see that all products have a exportToGoogleShopping facet,
since we set it to Boolean.FALSE by default.
• Full query, it runs a full indexation, SAP Hybris will get all products pks from this query,
by default it runs :
Don’t forget that the query is executed by the anonymous user, therefore the
Frontend_ProductApprovalStatus search restriction applies ({approvalStatus} =
approved)
• Update query, runs an update indexation on the existing SOLR index. SAP Hybris will
load the products that have been modified since the last index time, therefore only products
that have been modified (modifiedtime attribute) since the last update (date is injected as
an argument by the indexing service) would be indexed.
7.3. INDEXING LISTENERS 137
Don’t forget that the query is executed by the anonymous user, therefore the
Frontend_ProductApprovalStatus search restriction applies ({approvalStatus} =
approved)
• Partial update, this operation is similar to the update process but you can select the field
you want to update. This kind of operation, unlike the others, can’t be launched from a
wizard. You would need to create a different job for this. Here is an example of how to
create one job.
INSERT_UPDATE SolrExtIndexerCronJob;code[unique=true];job(code)[unique=true];sessionLa ⌋
֒→ nguage(isocode);sessionCurrency(isoCode);indexedType(identifier)[unique=true];que ⌋
֒→ ry;facetSearchConfig(name);indexerOperation(code);sessionUser(uid);queryParameter ⌋
֒→ Provider;indexedProperties
;partialUpdate-fromImpex-cronJob;solrExtIndexerJob;en;USD;Product_Product;set in
֒→ solrIndexerQuery;electronicsIndex;partial_update;anonymous;ParameterProvider;name
The indexedProperties attribute is a collection of String. Here you can list the
attribute you want to update. This is where you configure the partial behavior,
if you don’t configure any properties all attributes are updated
• Delete query this deletes documents from the index. For example you can select all products
that are not authorized or have been discontinued.
Indexing listeners
During the indexing process you can use listeners to intercept and customize a piece of the indexing
operation. Each listeners can implement three kind of actions, before, after and afterError. SAP
Hybris provides three kind of listeners :
package com.hybhub.hybhubaddon.search.solrfacetsearch.indexer.impl;
import org.springframework.beans.factory.annotation.Required;
@Required
public void setName(final String name)
{
this.name = name;
}
}
package com.hybhub.hybhubaddon.search.solrfacetsearch.indexer.impl;
import de.hybris.platform.solrfacetsearch.indexer.IndexerContext;
import de.hybris.platform.solrfacetsearch.indexer.IndexerListener;
import de.hybris.platform.solrfacetsearch.indexer.exceptions.IndexerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Override
public void beforeIndex(final IndexerContext arg0) throws IndexerException
{
LOG.info("Before Index : " + getName());
}
@Override
public void afterIndex(final IndexerContext arg0) throws IndexerException
{
LOG.info("After Index : " + getName());
}
@Override
public void afterIndexError(final IndexerContext arg0) throws IndexerException
{
LOG.info("After Index Error : " + getName());
}
Example how to declare a bean for the listener and configure it as global :
Listeners are called based on their priority, from the highest to the lowest (reversed order for the
after method):
Solr Facet
The difference between normal search and facet search is that when you do a normal search you
follow a determined path, like a category path. It is fixed and you need to know all the details
about your product. Quite the opposite with a facet search when you don’t need to know anything
about the product, you narrow down the results by applying filters to the list of products. SAP
Hybris faceted search gives the customer the ability to navigate through a collection of products
using facets. A facet can be anything from colors, prices, weigh, internal components, classified
as, warranty time, available in store...
To see this with a real world example, you can go to any of the big online retailers. Here, you will
notice that when searching for a product by entering its name, you see a list of facets (usually) on
the left.
In order to create a new facet, you only need to declare a new SolrIndexedProperty and flag it as
a facet. We will update the existing pickupAvailableFlag and make a facet from it:
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true] ⌋
֒→ ;type(code);fieldValueProvider;facet;facetType(code);priority;
;electronicsProductType;pickupAvailableFlag;boolean;productPickupAvailabilityValueProvider;t ⌋
֒→ rue;MultiSelectAnd;50;
• Refine, meaning that this would be the only facet used if selected;
After running a full SOLR indexation you should see the new facet under your product search
page.
Auto suggestion
If a SOLR indexed property is configured to be auto complete, its content becomes available for a
search from the Search Box Component.
To activate it from an indexed property, execute the following impex query :
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true] ⌋
֒→ ;useForAutocomplete
;electronicsProductType;code;true
• display images.
Keywords
Keywords are configured within the solr facet search configuration. They provide you with the
ability to redirect the customer to a page for a given query. For example, if a customer enters the
word cart under the search component, you can redirect him or her to the cart page.
First you need a SolrFacetSearchKeywordRedirect. This holds the following:
142 CHAPTER 7. SEARCH AND NAVIGATION
• the language;
• the keyword;
• match type (EXACT, START_WITH, ENDS_WITH, CONTAINS, REGEX);
• ignore case flag;
• a link to a facet search configuration;
• a link to a redirect object (Abstract redirect). It can be one of the following:
– a category redirect;
– a direct url;
– a page redirect;
– a product redirect.
$productCatalog=electronicsProductCatalog
$productCatalogVersion=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$productCata ⌋
֒→ log]),CatalogVersion.version[default=Staged])[default=$productCatalog:Staged]
INSERT_UPDATE SolrProductRedirect;redirectItem(code,$productCatalogVersion)[unique=true];\&r ⌋
֒→ edirectRefID
;726510;contentCatalogName-redirectRefID-726510
INSERT_UPDATE SolrFacetSearchKeywordRedirect;facetSearchConfig(name)[unique=true];language(i ⌋
֒→ socode)[unique=true];keyword[unique=true];matchType(code)[unique=true];redirect(&redire ⌋
֒→ ctRefID);ignoreCase
;electronicsIndex;en;"the best camera";EXACT;contentCatalogName-redirectRefID-726510;true
Stopwords
Stopwords are words that SAP Hybris is ignoring during a search. Because you don’t want to search
words like the or a, a list needs to be created and maintained for each language. Happily SAP Hybris
and SOLR provide a standard stopword list for most languages. You can find it under your configu-
ration folder config/solr/instances/default/ configsets/default/conf/lang/stopwords_en.txt
(the example illustrates stopwords for English, but other languages are available).
To manage stopwords from SAP Hybris, one first creates them from Impex queries:
INSERT_UPDATE SolrStopWord;facetSearchConfig(name)[unique=true];language(isocode)[unique=tru ⌋
֒→ e];stopword[unique=true]
;electronicsIndex;en;the
7.9. SYNONYMS 143
Synonyms
Synonyms help you to deal with customers typo, abbreviations or requests. They simply translate
a word into something you know your SOLR index would easily understand. Let us say, a customer
is looking for a disk capacity and he enters ’256 gigabytes’; you need to translate ’gigabytes’ into
’GB’ because that’s how you have indexed your products.
In order to create a new synonym:
INSERT_UPDATE SolrSynonymConfig;facetSearchConfig(name)[unique=true];language(isocode)[uniqu ⌋
֒→ e=true];synonymFrom[unique=true];synonymTo
;electronicsIndex;en;"gigabytes";"GB"
$productCatalog=electronicsProductCatalog
$productCatalogVersion=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$productCata ⌋
֒→ log]),CatalogVersion.version[default=Online])[default=$productCatalog:Online]
INSERT_UPDATE SolrHeroProductDefinition;$productCatalogVersion[unique=true];category(code,
֒→ $productCatalogVersion);code[unique=true];indexedType(identifier);products(code,
֒→ $productCatalogVersion)
;;575;575_electronicsProductType;electronicsProductType;478828
INSERT_UPDATE Product;code[unique=true];$productCatalogVersion[unique=true];solrHeroProductD ⌋
֒→ efinitions(code)
;478828;;575_electronicsProductType
Now navigate to home -> open catalog -> cameras -> digital cameras. You should see your product
on top of the search result.
Boost rules
Boost rules help you adjust the SOLR server answers in the way that for example product in stock
shows up before out of stock products. Based on different factors, you will artificially boost the
144 CHAPTER 7. SEARCH AND NAVIGATION
results.
SAP Hybris implemented boosting at query time, meaning that you do not need to
re-index to see the changes!
For example, for the product 1312564 to always be on top, you can execute this Impex query
below:
$solrIndexedType=electronicsProductType
INSERT_UPDATE GlobalSolrSearchProfile;code[unique=true];indexedType(identifier)
;globalcatalog-srch-profile0000000001;$solrIndexedType
INSERT_UPDATE SolrBoostRule;propertyValue[unique=true];solrIndexedProperty(name);operator(co ⌋
֒→ de)[unique=true];boostFactor;solrSearchProfiles(code)
;1312564;code;EQUAL_TO;100;globalcatalog-srch-profile0000000001
Now when you navigate to the Power Supplies category (one of the default top navigation link),
you see that our product 1312564 is listed on top.
Solr boost rule operators are:
• EQUAL_TO;
• CONTAIN;
• GREATER_THAN;
• GREATER_THAN_OR_EQUAL_TO;
• LESS_THAN;
• LESS_THAN_OR_EQUAL_TO.
Now if you type battery into your search box component you’d expect to see your product 1312564
on top of the list, but it’s not! The reason is that the boost factor we entered 100 is not enough
to push it to the top. A lot of other factors are adding their boost rules. Below the SOLR query
executed when you search for battery :
Now if you type "battery"" into your search box component, you may expect to see your product
1312564 on top of the list; but it’s not! The reason is that the boost factor we entered (100 ) is
not enough to push it to the top. A lot of other factors are adding to their boost rules. Below
SOLR query is executed when you search for battery:
7.10. HERO PRODUCTS & BOOST RULES 145
localhost:8983/solr/master_electronics_Product/select?
q=....’((code_string:battery^90.0)+
OR+(keywords_text_en:battery^20.0)+
OR+(manufacturerName_text:battery^40.0)+
OR+(categoryName_text_en_mv:battery^20.0)+
OR+(lastCustomerReview_string:battery^100.0)+
OR+(ean_string:battery^100.0)+
OR+(name_text_en:battery^50.0))+
OR+((keywords_text_en:battery~^10.0)+
OR+(manufacturerName_text:battery~^20.0)+
OR+(categoryName_text_en_mv:battery~^10.0)+
OR+(lastCustomerReview_string:battery~^50.0)+
OR+(name_text_en:battery~^25.0))+
OR+((code_string:battery*^45.0)+
OR+(ean_string:battery*^50.0))+
OR+((keywords_text_en:"battery"^40.0)+
OR+(manufacturerName_text:"battery"^80.0)+
OR+(categoryName_text_en_mv:"battery"^40.0)+
OR+(name_text_en:"battery"^100.0))’})+
//
// This is our custom boost query !
//
AND+({!func+v="sum(map(query({!v=code_string:1312564}),0,0,0,1000.0))"})
//
&sort=score+desc,inStockFlag_boolean+desc,score+desc
&start=0&rows=20
&facet.field=Resolution,+80_string
&facet.field=Mounting,+1867_en_string
&facet.field=categoryPath_string_mv
&facet.field=Megapixel,+63_string
&facet.field=exportToGoogleShopping_boolean
&facet.field=availableInStores_string_mv
&facet.field=pickupAvailableFlag_boolean
&facet.field=Colour+of+product,+1766_en_string
&facet.field=price_usd_string
&facet.field=allPromotions_string_mv
&facet.field=allCategories_string_mv
&facet.field=Lens+type,+472_en_string_mv
&facet.field=category_string_mv
&facet.field=brand_string_mv
&facet=true
&facet.sort=count
&facet.mincount=1
&facet.limit=50
&spellcheck=true
&spellcheck.q=battery
&spellcheck.dictionary=en
&spellcheck.collate=true
&fq=(catalogId:"electronicsProductCatalog"+AND+catalogVersion:"Online")
If you want to see the SOLR query you need to activate the debug for de.hybris.platform.solrfacetsearch
package :
146 CHAPTER 7. SEARCH AND NAVIGATION
log4j2.logger.search.name=de.hybris.platform.solrfacetsearch
log4j2.logger.search.level = debug
log4j2.logger.search.appenderRef.stdout.ref = STDOUT
Having a boost of 100 is not enough. So why not putting more to be sure that our product is always
showing on top? By default, SAP Hybris limits the maximum boost factor to 100. If you want
to increase it, you need to change the out-of-the-box BoostRuleValidator behavior. Unfortunately
SAP Hybris does not "think"" that this needs to be easily updated and made all beans around it
without aliases. So in order to change the maxBoostFactorValue attribute, you have 3 options:
• import boost factor rules in legacy mode (without service layer interceptors);
• using Spring AOP to update the existing bean, the preferred solution by far.
How to change boostRuleValidator bean using AOP, first you need to create a class to handle the
change. This is called around the validate method call from the interceptor:
package com.hybhub.hybhubaddon.commercesearch.searchandizing.boost.interceptors;
import
֒→ de.hybris.platform.commercesearch.searchandizing.boost.interceptors.BoostRuleValidator;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Required;
@Required
public void setMaxBoostFactorValue(final int maxBoostFactorValue)
{
this.maxBoostFactorValue = maxBoostFactorValue;
}
}
Now you need to configure your aspect with Spring. We use an around aspect to be able to inject
our customized max boost factor into the existing bean:
7.10. HERO PRODUCTS & BOOST RULES 147
<bean id="hybhubBoostRuleValidatorMethodInterceptor"
class="com.hybhub.hybhubaddon.commercesearch.searchandizing.boost.interceptors.Hybhu ⌋
֒→ bBoostRuleValidatorAspect">
<property name="maxBoostFactorValue" value="500" />
</bean>
<aop:config>
<aop:aspect id="boostValidatorAspect"
֒→ ref="hybhubBoostRuleValidatorMethodInterceptor">
<aop:pointcut id="boostValidatorPoincut"
expression="execution(* de.hybris.platform.commercesearch.searchandi ⌋
֒→ zing.boost.interceptors.BoostRuleValidator.onValidate(..))"
֒→ />
<aop:around method="around" pointcut-ref="boostValidatorPoincut"/>
</aop:aspect>
</aop:config>
You can now have boost factor value up to 500. If you run this Impex query your product 1312564
will always be on top of search:
INSERT_UPDATE SolrBoostRule;propertyValue[unique=true];solrIndexedProperty(name);operator(co ⌋
֒→ de)[unique=true];boostFactor;solrSearchProfiles(code)
;1312564;code;EQUAL_TO;500;globalcatalog-srch-profile0000000001
148 CHAPTER 7. SEARCH AND NAVIGATION
Chapter 8
Platform basics
149
150 CHAPTER 8. PLATFORM BASICS
Initialization
Initialization creates the database and inject the data from scratch following these steps:
• Put together all items.xml files to create the type system definition.
• Aborts all running cronjobs.
• Remove all tables existing under the type system definition, orphaned data stay intact.
• Hybris goes through all extension manager and call: initialize Remove Objects, initialize
Create Types, initialize Modify Types and initialize Create Objects.
• Prepare the DDL (Data Definition Language) and the DML (Data Modification Language).
• Clears cache.
• Creates media folders.
• Sets license.
• Always creates essential data and if enabled project data.
Hybris no longer removes all tables, it removes only those that are declared in its cur-
rent items.xml files, to reactivate the legacy behavior use initialization.legacy.mode=true
in local.properties
To run the initialization, you have 2 options:
• from the SAP Hybris HAC (Hybris Administration Console);
• from the build framework, executing ant initialize, one option is to select the tenant
with -Dtenant=master.
On a production system it is a good idea to lock the initialization from the HAC,
configure system.unlocking.disabled=true
8.2. UPDATE 151
Update
During the update process SAP Hybris updates the item types to match the new items.xml defini-
tion. Unlike the initialization process, there are no loss of data during an update because update
process:
During the update process SAP Hybris will (in order of execution):
• put together all items.xml files to create the type system definition;
• update existing type system according to the new items.xml definition (if possible, see rules
above);
On a production system it is a good idea to lock the initialization from the HAC,
configure system.unlocking.disabled=true
You can control what an extension is doing during the initialization and update process. SAP
Hybris provides annotation hooks for you to control the execution. To create your own hook, you
need to create a class that uses the annotation SystemSetup. Here is an example using Abstract-
SystemSetup from commerceservices as a starting point:
8.4. UPDATE AND INITIALIZATION HOOKS 153
package com.hybhub.setup;
import de.hybris.platform.commerceservices.setup.AbstractSystemSetup;
import de.hybris.platform.core.initialization.SystemSetup;
import de.hybris.platform.core.initialization.SystemSetup.Process;
import de.hybris.platform.core.initialization.SystemSetup.Type;
import de.hybris.platform.core.initialization.SystemSetupContext;
import de.hybris.platform.core.initialization.SystemSetupParameter;
import de.hybris.platform.core.initialization.SystemSetupParameterMethod;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hybhub.constants.HybhubhookConstants;
@SystemSetup(extension = HybhubhookConstants.EXTENSIONNAME)
public class HybhubHookSystemSetup extends AbstractSystemSetup
{
@SystemSetupParameterMethod
@Override
public List<SystemSetupParameter> getInitializationOptions()
{
final List<SystemSetupParameter> params = new ArrayList<>();
params.add(createBooleanSystemSetupParameter("key", "Import ?", false));
return params;
}
• For essential data: The platform scans the <extension_name>/resources/impex folders for
files with names that match the regular expressionessentialdata.impex and imports the files
during the essential data creation.
• For project data: The platform scans the <extension_name>/resources/impex folders for
files with names that match the regular expressionprojectdata.impex and imports the files
during the project data creation.
The ImpEx directory does not exist by default. You must create it and copy files to it.
Import by configuration
If you have special folder structures or want to use another folder in the resources, you must
override the configuration in your local.properties file:
For example, assume that you have the following folder structure:
• resources/test1.impex
• resources/subfolder/test2.impex
• resources/impex/subfolder/subfolder/test3.impex
In this structure, only the test1.impex file has the pattern <extension_name>.essentialdata-impex-
pattern=impex.
In contrast to the example above, the pattern <extension_name>.essentialdata-impex-pattern=/.impex
includes test1.impex, test2.impex and test3.impex. If you want your configuration to work as the
default does, you must set the pattern to <extension_name>.essentialdata-impex-pattern=impex/essentialdataimpex
8.6. SESSIONS HANDLING 155
"#% impex.includeExternalData(SampleDataManager.class.getResourceAsStream(""/firstFileToBeIm ⌋
֒→ ported.csv""), ""utf-8"", 0, 0
֒→ );";
"#% impex.includeExternalData(SampleDataManager.class.getResourceAsStream(""/secondFileToBeI ⌋
֒→ mported.csv""), ""utf-8"", 0, 0
֒→ );";
Sessions handling
All browser requests made to SAP Hybris are bind to a session. There are 2 kind of sessions:
• the HTTP session which is by default held by Tomcat;
• the JaloSession held by SAP Hybris.
The layer Jalo is deprecated, but JaloSessions are not going to be replaced by the
service layer, they just use a legacy name.
The JaloSession is a wrapper around the HTTP session to hold information about the current
SAP Hybris user:
• user (anonymous by default);
• language;
• currency;
• price factory;
• locale;
• timezone.
Jalo Sessions are also used for cronjobs, they exist only within SAP Hybris memory and are
by default never persisted.
Example how to get your current Jalo Session from the SessionService (Groovy script):
println jaloSession.getHttpSessionId()
println sessionContext.getLanguage()
println sessionContext.getLocale()
156 CHAPTER 8. PLATFORM BASICS
Extensions structures
SAP Hybris is made of different extensions, like the set of extensions that constitute the so called
platform. Extensions are made to be independent from each other, so you could migrate SAP
Hybris platform without changing your customized extensions.
Each extensions are represented by a Java project, even the out of the box extensions can be
opened as Java projects. Below the folder’s structure of all extensions:
extensioninfo.xml
Within the extensioninfo.xml file, you can configure:
• list of dependencies, this will be used by the build framework to know what extensions need
to be included within the build and in what order they should be compiled.
• activated modules.
– core module, if defined the extension will be used to define and localize item types
trough the }items.xml file.
– web module, if activated the extension will be used as a web application.
– hmc, if activated the extension will have hmc configuration.
meta, there are also different meta keys that can be used to configure extensions, for
backoffice or templates for example.
localextensions.xml
SAP Hybris consists of a number of extensions. You can configure which extensions are used by
modifying the localextensions.xml file located under your configuration folder.
Extensions located under ${HYBRIS_BIN_DIR}/platform/ext are automatically
loaded
Extensions are loaded when:
For examples :
<extension dir="${HYBRIS_BIN_DIR}/custom/hybhubaddon"/>
It’s also possible to load external web application (war files for example), using the
webapp tag :
During the build phase you can read what extensions are being loaded directly, and what extensions
are being lazy loaded (through dependencies and configured path):
...
[echo] -----
[echo] --- Extensions in dependency order ( options:
[echo] --- @deprecated: is deprecated, p: platform extension,*: auto-required
[echo] --- ?: lazy-loaded, i: got items.xml, b: got beans.xml, c: got core module
[echo] --- w: got web module, h: got HMC module )
[echo] -----
[echo] core 6.0.0.0-SNAPSHOT [p*cib]
[echo] testweb 6.0.0.0-SNAPSHOT [p*w]
[echo] scripting 6.0.0.0-SNAPSHOT [p*ci]
....
158 CHAPTER 8. PLATFORM BASICS
You can create new extensions based on an existing template. The example below creates a new
extension based on the yempty template:
There are different available templates to create new extensions, the convention is that all exten-
sions starting with a y are templates, the most basic one is the yempty template which is an empty
shell with the SAP Hybris folder structure.
Maven
SAP Hybris is currently in between Ant and Maven. The whole platform build is tightly coupled
with Ant but dependency management can be used for any extension. Also for some modules (CIS
and Datahub for example) the full lifecycle is done with Maven.
If you want to activate dependency management for one of your extension, open the extension-
info.xml file and configure it with usemaven=”true”:
8.8. CONFIGURATION 159
<project xmlns="http://maven.apache.org/POM/4.0.0"
֒→ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
֒→ http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.hybris.platform</groupId>
<artifactId>hybhubhook</artifactId>
<version>5.0.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
</dependencies>
</project>
When you build your project, Hybris will automatically download all libraries and update your
project. If you want to update your project classpath you can use ant classpathgen within your
extension.
You need to have Maven installed!
Configuration
SAP Hybris uses simple property files for its configuration. All variables would be either injected
into Tomcat when you execute ant server, or injected into the running system as configuration
variables (you can configure them lively directly from the HAC).
There are different files where you can configure SAP Hybris behavior, in order of priority from
high to low:
160 CHAPTER 8. PLATFORM BASICS
• config/local.properties
• your extensions project.properties files
• platform directory project.properties file
Configuration properties are defined using a key and a value; for example:
#A comment
the.key=myValue
Configuration Service
An example of how to get a configuration key from your code is below:
You can read or edit the current configuration. Have a look at the interface org.apache.commons.configuration.Config
Environment variables
When configuration files may contain sensible data such as logins, passwords, urls, hash..., it’s a
good idea not to store them within a file. SAP Hybris gives you the possibility to configure special
properties value that need to be overridden by environment variables using <CHANGE_ME>
keyword. For example within my configuration, I have :
hybhub.config=<CHANGE_ME>
Then from my environment I execute (note that it needs to start with y_ and you replace dots by
underscore, double underscore to replace single underscores):
8.9. BUILD 161
export y_hybhub_config=fromConsole
In this folder files would be loaded in they match [1-9][0-9]-local.properties (example : 10-local.properties),
the number specifies the order in which they are loaded and merged.
Build
SAP Hybris build framework is based on:
• Eclipse IDE.
When you execute the command ant, the build framework would call the default ant target (all
-> build + server):
• check directories (data, temp and log), it creates the folders if they don’t exist;
• check the config directory, and prompt for the configuration template selection if none exist;
• extensions that depends on another are built only after all their dependencies are built;
• generates and compiles source files (according to the definitions in the items.xml files);
Callbacks
In each extensions you will find a file named buildcallbacks.xml, within this file you can extend
the behavior of the build framework for a given extension adding custom actions around each ant
targets. For example, before my extension is built:
<macrodef name="hybhubhook_before_build">
<sequential>
<echo message="Hybhub is being build !!" level="info"/>
</sequential>
</macrodef>
Tenant
SAP Hybris can run in a multi tenant mode, which means each tenant is using a different set of
data.
Each tenant has:
• isolated data;
installed.tenants=junit,foo,t1,t2,hybhub
allowed.extensions=core;promotions
forbidden.extensions=b2bapprovalprocess;hybhubaddon
Cache
SAP Hybris cache helps reduce the number of database queries. It caches three type of objects:
• Item instances;
• Item attributes.
The cache is used within the Service Layer. It is completely transparent to be used. When you call
a getter on an item attribute, if it hasn’t been loaded yet, it will be then loaded from the database
and cached for the next time. The cache is independent for each node meaning that each nodes
have their local cache.
Data are removed from the cache when:
– item is deleted;
– item is modified.
When a node invalidates a cache entry, the invalidation is shared with other nodes by sending a
UDP request to all cluster nodes.
Region cache
SAP Hybris cache is divided into regions. Each region has its own configuration, caches different
kind of objects, and has a maximum size. Regions can have different kinds of eviction strategy:
164 CHAPTER 8. PLATFORM BASICS
• Least Recently Used (LRU), objects are evicted based on their last used timestamp;
• Least Frequently Used (LFU), every time an object is read the cache increment a hit counter,
object are evicted based on this counter;
• First In First Out (FIFO), objects are evicted based on their age.
By default, SAP Hybris has a region for type systems. The region is called ehCacheEntityCacheRe-
gion and uses LRU eviction strategy.
To create new cache region, you need to create a new Spring Beans within the global Spring
context. First we configure for our extension named hybhubhook a new global spring context file:
hybhubhook.global-context=hybhubhook-cache-spring.xml
handledTypes is the type code of the item type, one is for products. It could also be
ALL_TYPES, QUERY_CACHE or NO_QUERY. For more examples have a look at
the SAP Hybris default regions cache within core-cache.xml.
Now if you go into the HAC, under /monitoring/cache, you should see your new cache region
productCacheRegion.
8.12. INTERCEPTORS 165
Interceptors
The service layer gives the ability to activate interceptor when life cycle of a model reaches certain
steps:
package com.hybhub.hybhubaddon.servicelayer.interceptor;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.servicelayer.interceptor.InterceptorContext;
import de.hybris.platform.servicelayer.interceptor.InterceptorException;
import de.hybris.platform.servicelayer.interceptor.RemoveInterceptor;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Override
public void onRemove(final ProductModel prd, final InterceptorContext ctx) throws
֒→ InterceptorException
{
LOG.info("Removing product : " + prd.getCode());
if (PROTECTED_PRODUCTS.matcher(prd.getCode()).find())
{
throw new InterceptorException("Product is protected, cannot remove
֒→ it !");
}
LOG.info("Product : " + prd.getCode() + " removed");
}
}
You need to declare the interceptor as a Spring bean and to configure the type mapping :
Now try to delete a product with a numeric code. The interceptor should block you from removing
it.
The InterceptorMapping can be also configured with :
You can choose to disable interceptors from an Impex query, by types [disable.interceptor.types=validate]
or by bean names [disable.interceptor.beans=’productRemoveInterceptor’]
You can choose to call the service layer in a local view with interceptor deactivated :
Transactions
Transactions are used to keep the data consistent at any time. SAP Hybris provides a wrapper to
easily work with transactions.
A simple groovy example follows below.
transaction.begin()
A single thread can only have one transaction, therefore it doesn’t matter how many
times you get the current transaction, if it’s from the same thread you will always get
the same transaction !
Remember to execute commit and rollback within a finally block ! Errors are not
caught by Exception blocks.
SAP Hybris also has a more advanced wrapper to include all steps of a transactions. The advantage
of TransactionBody is that you don’t need to manually handle the transactions over and over:
168 CHAPTER 8. PLATFORM BASICS
SAP Hybris offers a delayed store mechanism, if activated statements will be executed
only when the transaction is committed, the pro is that performance would be better
in big transactions but data won’t be updated and available until the transaction is
committed. To activate it Transaction.current().enableDelayedStore(true);
Tasks
SAP Hybris provides a task service. Tasks are scheduled actions like cronjob a simplified version;
they have the following features:
Each task can be executed on any cluster node. The first cluster to fetch and lock the task
would run it. If you need to deactivate the task engine on a given node, you can do it from the
configuration file:
task.engine.loadonstartup=false
Platform core
169
170 CHAPTER 9. PLATFORM CORE
Events
The Event System is a framework provided by the service layer allowing you to send and receive
events within the SAP Hybris.
• One software component acts as a source and publishes an event that is received by registered
listeners.
• Event listeners are objects that are notified of events and perform business logic corresponding
to the event that occurred.
To create your own event, you need to extend the class de.hybris.platform.servicelayer.event.events.AbstractEvent:
package com.hybhub.event;
import de.hybris.platform.servicelayer.event.events.AbstractEvent;
@Override
public String toString()
{
return "Hybhub Event : " + this.name;
}
}
package com.hybhub.event;
import de.hybris.platform.servicelayer.event.impl.AbstractEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Override
protected void onEvent(final HybhubEvent hybhubEvent)
{
LOG.info("Received event(Hybhub Event) : " + hybhubEvent);
}
import com.hybhub.event.HybhubEvent
def eventService = spring.getBean("eventService")
You should be able to read the following message on SAP Hybris console: INFO [hybrisHTTP8]
[HybhubListener] Received event(Hybhub Event) : Hybhub Event : Event published from Groovy
console !
The only flaw here is that everything is executed synchronously by the same thread! To process
them in an asynchronous way, you can:
package com.hybhub.event;
import de.hybris.platform.servicelayer.event.ClusterAwareEvent;
import de.hybris.platform.servicelayer.event.events.AbstractEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Override
public String toString()
{
LOG.info(Thread.currentThread().getName());
return "Hybhub Event : " + this.name;
}
@Override
public boolean publish(final int sourceClusterId, final int targetClusterId)
{
return true; //Returning true means your event will be broadcast on all nodes
}
}
<bean id="platformClusterEventSender"
֒→ class="de.hybris.platform.servicelayer.event.impl.PlatformClusterEventSender">
<property name="serializationService" ref="serializationService"/>
<property name="tenant" ref="tenantFactory"/>
<property name="executor">
<bean class="java.util.concurrent.Executors"
֒→ factory-method="newCachedThreadPool"/>
</property>
</bean>
9.2. IMPEX 173
Impex
SAP Hybris needs to exchange a lot of data with external systems and it needs to be easily
configurable without having to create complex SQL query. Impex offers a way to easily store
and exchange. That means *import and export*, which is an out-of-the-box CSV-based import
framework. From an impex file you can do the following:
• import data;
• update data;
• import / update data;
• remove data;
• export data.
• initial data injection (stores definitions, initial catalogs, cms components creation, catalogs
creation...);
• update data during runtime;
• test datas / configurations during development;
• migrate data between systems;
• backups.
• a header defining the mapping between an item type and the value lines;
• line value(s) defining the date;
• comments;
• macro definition;
• BeanShells directive;
• user rights definition.
Eclipse Neon (impexeditor Feature, with live Impex validation if your server is started)
and IntelliJ (Hybris integration) have a special editors available for Impex files.
Header
Header is a single line preceding the value lines. A header has:
• a mode which defines what kind of operations you are executing, it can be:
– INSERT, creates a new item.
– UPDATE, update an existing item based on unique identifiers.
174 CHAPTER 9. PLATFORM CORE
– INSERT_UPDATE, update an existing item if it can find the unique identifier oth-
erwise create a new entry.
– REMOVE, try to remove an item based on unique attributes, log a warning if it can’t
find any elements.
• header modifiers, are configured with the item type, for example : INSERT MyType[headerModifier=something
INSERT Title;code;name[lang=en]
UPDATE Title;code[unique=true];name[lang=en]
INSERT_UPDATE Title;code[unique=true];name[lang=en]
REMOVE Title;code[unique=true];name[lang=en]
You can also specify a subtype of the Header item type on the value line, for example :
INSERT User;uid[unique=true]
Customer;aCustomer
Employee;anEmployee
The header item type could be abstract, but the value line item type obviously can’t
Setting an attribute value for atomic types is straightforward, a string attribute for example can
be directly entered within the value (see example with *User* item type above). For reference
attributes, Impex expects you to enter the primary key of the referenced item. This is not possible
to know items primary key before they are created; so this is not the right way to create relations.
To efficiently and without external dependencies insert relations between items, you need to look
them up based on their own attributes. Add a comment to this line
To localized attributes you need to use a modifier within the header attributes like [lang=en] to
localize an attribute in English:
INSERT Type;localizedAttribute[lang=en]
en is defined with the Language items and correspond to unique ISO code of the
language, have a look at the internationalization tab under the HMC or HAC
Comment
A commented line starts with a dash # and is completely ignored during import:
176 CHAPTER 9. PLATFORM CORE
INSERT_UPDATE Product;code
#Begin importing products
;product1;
#Finished importing products
Macro
Impex files can easily get large; it’s not occasional to see Impex import files of more than a thousand
lines! If you need to update one common attribute for each of the value lines, Macros come in
handy. A Macro definition starts with a $ sign:
#Macro definition
$unit=pieces
$variantType=LaptopVariant
$aid=MBP-
$manufacturer=Apple
$catalogVersion=catalogversion(catalog(id[default=$productCatalog]),version[default=’Staged’ ⌋
֒→ ])[unique=true,default=$productCatalog:Staged]
$supercategories=supercategories(code, $catalogVersion)
INSERT_UPDATE Product;code[unique=true];$supercategories;manufacturerName;manufacturerAID;un ⌋
֒→ it(code);variantType(code);$catalogVersion;$approved
;000010;000100;$manufacturer;$aid13;$unit;$variantType
;000011;000100;$manufacturer;$aid15;$unit;$variantType
Abbreviations
Another way to shorten Impex files is to use abbreviations. You may use system wide regex
replacement for you Impex headers. For example, out of the box there is an header replacement
for the classification header:
impex.header.replacement.1=C@(\\w+) ...
֒→ @$1[system=’$systemName’,version=$systemVersion’,translator=’de.hybris.platform.catalog ⌋
֒→ .jalo.classification.impex.ClassificationAttributeTranslator’]
That’s the reason why during classification import you might encounter:
9.2. IMPEX 177
Document ID
Sometimes item references lookup method trough attributes does not suffice and you need to be
able to have a reference to an object within an Impex file. That’s when you use the & operator to
create references:
INSERT Address;\&addrID;owner(Customer.uid);
;addr1;andrew@hybhub.com;
Translators
For some attributes, you need a special translator to import the object. The most obvious example
is for the media objects. In those cases you need to use a special translator:
INSERT_UPDATE Media;code[unique=true];realfilename;@media[translator=de.hybris.platform.impe ⌋
֒→ x.jalo.media.MediaDataTranslator];mime[default=’image/jpeg’];$catalogVersion
;/img/low_pic/574-4346.jpg;574-4346.jpg;$siteResource/images/img/low_pic/574-4346.jpg;
INSERT_UPDATE SavedQuery;code[unique=true];resulttype(code);query;params(key,value(code))
;savedQuery;Customer;SELECT {pk} FROM {Product} where {code} = ?code;code->java.lang.String
Alternative pattern
When an item type relation is set to a basic item type such as ItemType for example, you can
find the referenced item from multiple attributes. You can, in this case, give the Impex attribute
178 CHAPTER 9. PLATFORM CORE
different options. Below is an example with the address owner type which is set to ItemType:
Distributed Impex
SAP Hybris V6 introduced a new concept of distributed Impex to share the Impex import between
nodes. It speeds up the execution of queries by splitting them into batches that are executed in
different nodes. This doesn’t need to be configured since it’s the new default Impex engine.
Importing data using the new distributed mode consists of three steps:
• finishing.
/**
* Impex ImportProcessor that injects all config properties as impex definitions.
* All defined configuration properties are added as impex macro definitions with
* the prefix of "config-". For example the config key <tt>mail.smtp.server</tt>
* can be accessed via the macro <tt>$config-mail.smtp.server</tt>.
* In order to use this import processor and to load the configuration properties
* the following must be added to the top of the impex file:
*
* <tt>UPDATE GenericItem[processor=de.hybris.platform.commerceservices.impex.impl.ConfigPro ⌋
֒→ pertyImportProcessor];pk[unique=true]</tt>
*/
my.default.language=French
UPDATE GenericItem[processor=de.hybris.platform.commerceservices.impex.impl.ConfigPropertyIm ⌋
֒→ portProcessor];pk[unique=true]
$defaultLanguage=$config-my.default.language
INSERT_UPDATE Country;isocode[unique=true];name[lang=en];active[default=true]
;FR;$defaultLanguage
Spring context
SAP Hybris is heavily using Spring. It offers developers the flexibility to implement their work
on top of the out of the box extensions. Spring offers the ability to contain beans within different
contexts. SAP Hybris provides different application contexts:
– to configure it you need to configure an extra property within your extension configuratio
extname.global-context=spring.xml.
– configured inside the web.xml file of your extension (your extension needs to have
a web module defined within its extension.xml configuration file).
– the listener org.springframework.web.context.ContextLoaderListener configured within
the web.xml automatically configured the core application as parent of the web appli-
cation context.
– web application context can use core beans but cannot modify them.
The order of loading Spring configuration is the same as in the build process, so to
override a Spring bean defined in extension A from extension B, add a dependency
in extension B for extension A
You can configure more than one Spring configuration file, simply separate them with
a coma, for example : extname.application-context=spring1.xml,spring2.xml
To manually load a bean, it is recommended to use Registry.getApplicationContext() as this will
first try to load it from a web application context then from the core context and finally from the
global context.
180 CHAPTER 9. PLATFORM CORE
Cronjobs
A cronjob is an automated task performed at a certain time (every day at 2 am for example), or
in fixed intervals (every hour for example). It can be used for:
• data backups;
• Catalog synchronization;
• a job to do;
• a cronjob item which link the job and the trigger and configure the environment the job will
be performed in.
To create a new Cronjob first you need to create a new item which extend the Cronjob item type.
We will create a cronjob that deactivate products that haven’t been updated since a given time:
<typegroup name="hybhub">
<itemtype code="DeactivateOutdatedProductCronJob" extends="CronJob">
<description>Job to deactivate out-dated products</description>
<attributes>
<attribute type="java.util.Date" qualifier="minLastUpdate">
<persistence type="property" />
</attribute>
</attributes>
</itemtype>
</typegroup>
Then we need to create the actual job that deactivate products based on the minLastUpdate
attribute:
9.4. CRONJOBS 181
package com.hybhub.job;
import de.hybris.platform.catalog.CatalogVersionService;
import de.hybris.platform.catalog.enums.ArticleApprovalStatus;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.servicelayer.cronjob.AbstractJobPerformable;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import java.util.List;
import javax.annotation.Resource;
import com.hybhub.model.DeactivateOutdatedProductCronJobModel;
@Resource
private FlexibleSearchService flexibleSearchService;
@Resource
private CatalogVersionService catalogVersionService;
@Resource
private ModelService modelService;
@Override
public PerformResult perform(final DeactivateOutdatedProductCronJobModel cronjob)
{
final FlexibleSearchQuery fsq = new FlexibleSearchQuery("SELECT {pk} FROM
֒→ {Product} "
+ "WHERE {modifiedtime} <= ?minLastUpdate " + " AND
֒→ {catalogVersion} = ?catalogVersion");
fsq.addQueryParameter("minLastUpdate", cronjob.getMinLastUpdate());
fsq.addQueryParameter("catalogVersion",
֒→ catalogVersionService.getCatalogVersion("electronicsProductCatalog", "Staged"));
productsToUpdate.stream().forEach((prd) -> {
prd.setApprovalStatus(ArticleApprovalStatus.UNAPPROVED);
modelService.save(prd);
});
}
182 CHAPTER 9. PLATFORM CORE
You need to update your system for SAP Hybris to find the new Job
Let’s create a cronjob from a Groovy script (You could do this from the HMC or from an Impex
query), we create a trigger but also we start the cron manually:
Don’t forget to switch the commit mode to on, if you execute this more than once it
will fail since cronjob codes needs to be unique !
import com.hybhub.model.DeactivateOutdatedProductCronJobModel
import de.hybris.platform.cronjob.model.JobModel
import de.hybris.platform.cronjob.model.TriggerModel
DeactivateOutdatedProductCronJobModel cron =
modelService.create(DeactivateOutdatedProductCronJobModel.class)
cron.setMinLastUpdate(new Date())
cron.setCode("deleteOutdatedProductsss")
cron.setJob(job)
modelService.save(cron)
cronJobService.performCronJob(cron)
Be careful this will change the status of all your products under the staged electronic
product catalog !
Abortable Cronjob
Sometimes when the jobs you are performing are time consuming you need to be able to abort a
running cronjob. By default a cronjob will run until it’s done; but you can implement your own
9.5. CLUSTER 183
logic to give it a chance to abort itself. First you need to create a job to be aware of this new
functionality. To do so, there are two methods:
1. override isAbortable()
@Override
public boolean isAbortable()
{
return true;
}
Secondly you need to add within your perform method implementation an exit door like this:
if (clearAbortRequestedIfNeeded(theJob))
{
return new PerformResult(CronJobResult.ERROR, CronJobStatus.ABORTED);
}
Cluster
When you deploy SAP Hybris into production you would need to configure a cluster of SAP Hybris
nodes, a cluster offers:
• node specific configuration;
• cronjobs / events for specific nodes;
• session fail over;
• load balancing compatibility (load balancing needs to be done by a third party component);
• choice of UDP (unicast or multicast) or TCP (Jgroup) for nodes communication.
All nodes are using the same database
184 CHAPTER 9. PLATFORM CORE
Cache invalidation
Each SAP Hybris nodes have their own local cache. When one node update an item in the cache,
it needs to tell the other nodes to invalidate the entry in their local cache for consistency purpose.
To do so the node sends a request (TCP or UDP depends on your cluster configuration) so that
other nodes discards the item and reloads it from the database the next time it needs to access
that object.
Configuration
Node specific configuration can be done by using:
#cluster.<nodeid>.my.property=value
cluster.1.my.property=value
Nodes need to have a unique identifier. Prior to SAP Hybris V6, you had to manually configure
an id for each node:
clustermode=true
cluster.id=0
This could make deployment more complex as you needed to provision a unique identifier for each
node. Since SAP Hybris V6, you can activate auto discovery mode; this keeps track of each nodes
within the database:
clustermode=true
cluster.nodes.autodiscovery=true
Testing
SAP Hybris uses Junit to run unit tests and integration tests, which are located within the testsrc
and web/testsrc folders.
You can execute tests from your IDE or from ant.
9.6. TESTING 185
#All tests
ant alltests
#Integration tests
ant integrationtests
#Unit tests
ant unittests
There are other ant commands (manual tests, performance tests...) to see all available
tests execute "ant -p"
Unit tests
Unit tests are simple tests that do not need any access to SAP Hybris platform (database, ser-
vices...). They focus on testing the correct behavior of a single java class. When necessary, you
can isolate the class by using Mockito to mock anything you need (interfaces, pojo...).
An example of a Unit test class generated by SAP Hybris follows:
186 CHAPTER 9. PLATFORM CORE
/**
* JUnit Tests for the Ruleenginetrail extension.
*/
public class RuleenginetrailTest extends HybrisJUnit4TransactionalTest
{
/** Edit the local|project.properties to change logging behavior (properties
֒→ log4j2.logger.*). */
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(RuleenginetrailTest.class);
@Before
public void setUp()
{
// implement here code executed before each test
}
@After
public void tearDown()
{
// implement here code executed after each test
}
/**
* This is a sample test method.
*/
@Test
public void testRuleenginetrail()
{
final boolean testTrue = true;
assertThat(testTrue).isTrue();
}
}
@Test
public void testThrowAnExceptionWhenNotEmptyContentCatalogs() throws BusinessException
{
final ContentCatalogModel contentCatalogOne =
֒→ Mockito.mock(ContentCatalogModel.class);
final CatalogVersionModel catalogVersion = Mockito.mock(CatalogVersionModel.class);
BDDMockito.given(siteModel.getStores()).willReturn(Collections.EMPTY_LIST);
BDDMockito.given(siteModel.getContentCatalogs()).willReturn(Arrays.asList(contentCat ⌋
֒→ alogOne));
BDDMockito.given(contentCatalogOne.getActiveCatalogVersion()).willReturn(catalogVers ⌋
֒→ ion);
Integration tests
Integration tests let you interact with SAP Hybris (database, services...) using a dedicated tenant
junit.
The easiest way to create integration tests is to extend:
• ServicelayerTest, this way you can import any service using the @Resource annotation and
gain access to methods too create basic data (createDefaultUsers, createHardwareCatalog,
createDefaultCatalog...);
Other tests
• @DemoTest;
• @PerformanceTest;
• @ManualTest.
188 CHAPTER 9. PLATFORM CORE
Chapter 10
189
190 CHAPTER 10. PCM AND PRICE
Price calculation
SAP Hybris provides a flexible, scalable and configurable way to handle prices, all price informa-
tions are contained with the PriceRow item type, a price row has :
• a price
• a currency
• a unit factor
• a unit
• a minimum quantity
• a catalog version (not mandatory)
• a time frame (not mandatory)
• a customer or a groups of customers (not mandatory)
• a product or a group of products (not mandatory)
• a net flag (not mandatory)
Under SAP Hybris V6 the out of the box price factory implementation is called
Europe1PriceFactory this is a legacy name, when the SAP Hybris team implemented
their first price factory they thought they would implement different price factories
for each regions which in fact was not needed, but they kept this legacy name
The price factory is still using the deprecated jalo layer, therefore within the next
version Europe1PriceFactory might be migrated to something like DefaultPriceFacto-
ryService
To be selected by the price factory a price row needs (following the order of execution) :
Currency conversion is done automatically if no price are defined for the current
currency, all conversions are done based on the base currency and the conversion
attribute of the targeted currency, have a look at currencies from the HMC
After the price factory has loaded all matching prices it needs to select the final one, ordered by
highest priority :
When the price factory returns more than one price if they are more than one match the Price-
Service will select the lowest one.
Taxes
Taxes are represented by tax rows, they define :
• an absolute flag
• a currency
• a date range
• a product
• a tax object
• a user
• a value
Tax rows are very similar to price rows, but unlike price rows you accumulate them,
for one product you could apply multiple taxes unlike prices where you need to select
only one instance
To match tax rows the Europe1PriceFactory will look for :
• date range
192 CHAPTER 10. PCM AND PRICE
Discounts
Discounts are represented by discount rows, they define :
• an absolute flag
• a currency
• a date range
• a product
• a discount object
• a user
• a value
Discount rows are very similar to price rows, but unlike price rows you accumulate
them, for one product you could apply multiple discounts unlike prices where you
need to select only one instance
To match discount rows the Europe1PriceFactory will look for :
• date range
Media object
SAP Hybris supports media objects, a media item is a reference to any sort of physical files stored
on locally or remotely. It can be a picture, a text file, a flash file, a zip archive and so on. A media
is linked to only one file but a file could be linked to more than one media. A media item is defined
by :
• a unique identifier
• a catalog version
• a mime type
• a URL
10.4. MEDIA OBJECT 193
• a folder
• a format
• a media container
• a location hash
• metadatas
• security rules
Out of the box Media type has multiple sub types for specialized objects like Impex, Log and
Email.
Medias are not localized, therefore to have a localized reference to medias you need
to declare an attribute this way : localized:Media
SAP Hybris offers out the box two MediaStorageStrategy :
• de.hybris.platform.media.storage.impl.LocalFileMediaStorageStrategy, default out of the box
strategy, files are stored along with Hybris under the data directory
• de.hybris.platform.amazon.media.storage.S3MediaStorageStrategy, files are stored within Ama-
zon AWS S3 Buckets
Depending on the media storage strategy you are using you would need to select the appropriate
MediaURLStrategy, out of the box you have :
• de.hybris.platform.media.url.impl.LocalMediaWebURLStrategy
• de.hybris.platform.amazon.media.url.S3MediaURLStrategy
Media contexts
SAP Hybris is a multi channel platform therefore you could be loading medias in many different
contexts from a mobile storefront to a print cockpit, therefore you need to be able to adequate
images format for each context, a media context is a mapping container that would map a source
format to a target format so the proper image is loaded.
Secured media
by default media access is not secured.
media.default.secured=false
To secure all media turn configure it to true, if you need to secure only one folder you can use :
media.folderName.secured=true
Synchronization jobs
SAP Hybris has a concept of catalog and catalog versions, all item types which are catalog aware
(have an attribute of type CatalogVersion) can exist in multiple catalogs. This gives you the
flexibility to have a backstage where you prepare your changes before you push it into production.
Out of the box a SAP Hybris system is configured with three type of catalogs, a content catalog
for CMS items, (paragraph, menu, pages...) medias, a product catalog and a classification catalog.
Synchronizing catalogs means that you push the content of a catalog into another, usually the
Staged catalog into the Online catalog.
You can either run a synchronization as a cronjob or run manual synchronization from the catalog,
a CatalogVersionSyncJob is defined by :
• synchronization source and target (usually Staged to Online)
• create new elements flag
• remove missing elements flag
• synchronization languages
• root item types (item types to synchronize)
Warning!
A catalog can have multiple versions and a Synchronization could merge two Staged catalog
into one Online catalog.
10.6. WORKFLOW 195
$productCatalog=productCatalog
$defaultCurrency=EUR
$languages=en
$defaultLanguage=en
$prices=europe1prices[translator=de.hybris.platform.europe1.jalo.impex.Europe1PricesTranslat ⌋
֒→ or]
$stagedProduct=catalogVersion(catalog(id[default=$productCatalog]),version[default=’Staged’] ⌋
֒→ )[unique=true,default=’$productCatalog:Staged’]
$onlineProduct=catalogVersion(catalog(id[default=$productCatalog]),version[default=’Online’] ⌋
֒→ )[unique=true,default=’$productCatalog:Online’]
$sourceProductCV=sourceVersion(catalog(id[default=$productCatalog]),version[default=’Staged’ ⌋
֒→ ])[unique=true,default=’$productCatalog:Staged’]
$targetProductCV=targetVersion(catalog(id[default=$productCatalog]),version[default=’Online’ ⌋
֒→ ])[unique=true,default=’$productCatalog:Online’]
INSERT_UPDATE CatalogVersionSyncJob;code[unique=true];$sourceProductCV;$targetProductCV;
;sync productCatalog:Staged->Online;;;;
Dependent Synchronization
To avoid having references to a staged catalog in your online catalog version when two catalogs
depend on each other (for example a product catalog and category catalog) you can run a dependent
synchronization.
The CatalogVersionSyncJob item type has two attributes for this :
• dependentSyncJobs
• dependsOnSyncJobs
You can use one or the other, what’s important is to have dependency set between the two syn-
chronization jobs.
Workflow
SAP Hybris workflows help you modeling business processes like writing and validating a product
description in multiple languages, a workflow is defined by :
• completed
• disabled, deprecated
• ended through end of workflow
Start action are automatically marked as pending when the workflow is started
If no action are marked as start actions then all actions are set to pending
If a workflow is ended without reaching all actions, then the status of untouched
actions is set to ended through end of workflow
SAP Hybris V6 has a fully functional workflow example under productcockpitsampledata extension,
have a look at projectdata_workflow.impex.
Chapter 11
User Management
197
198 CHAPTER 11. USER MANAGEMENT
User rights
All groups and users within SAP Hybris are based on the principal item type, this is the foundation
of all users and groups (unique identifier). A user can be either a Customer or an Employee :
• Customers are users designed to visit your store front and place orders.
• Employees are users designed to access the back office
There are three special principals within SAP Hybris that can’t be modified or up-
dated, the admin and anonymous users and the admin group
Access rights
SAP Hybris has a permission framework that let you define your own access rules to item types
and attributes. An access right can be defined :
• globally for a user or user group
• for an item type
• for an instance of an an item type
• for an attribute
rights apply from the most general rules to most specific rules
Access right definitions could be either positive (granted) or negative (denied)
If two rules collide, the most restrictive one would be applied, so if one rule grants
read right and another denies read right, the user won’t have read right
To assign permissions you have two possibilities :
• Legacy Impex scripts that are only compatible with legacy permissions (READ, CHANGE,
CREATE, DELETE)
• PermissionManagementService is the new recommended way of managing permissions, it
allows you to create new permission types
Changing permissions takes effect immediately
Impex script
To define access rights using the legacy Impex script, you need to use $START_USERRIGHTS
and $END_USERRIGHTS to indicate that every line in between those two statements are not
Impex but user rights definition.
Example :
$START_USERRIGHTS
Type;UID;MemberOfGroups;Password;Target;read;change;create;delete;change_perm
UserGroup;employeegroup;;
;;;;Product;+;-;-;-;-
;;;;CMSItem.name;+;-;-;-;-
$END_USERRIGHTS
11.2. SEARCH RESTRICTIONS 199
Permission service
The out of the box de.hybris.platform.servicelayer.security.permissions.PermissionManagementService
lets you :
import de.hybris.platform.servicelayer.security.permissions.PermissionAssignment
PermissionAssignment permission =
new PermissionAssignment("read", productmanager, true)
pms.addTypePermission(typeService.getComposedTypeForCode("Product")
, permission)
Remember:
Search restrictions
Search restrictions are where clauses automatically added to flexible search queries for specific
users and item types. Restrictions do not apply for :
• SOLR search
Impex example
INSERT_UPDATE SearchRestriction;code[unique=true];name[lang=en];query;principal(UID);restric ⌋
֒→ tedType(code);active;generate
;OnlyPublicProduct;Only Public Product;"{code} like ’11%’";anonymous;Product;true;true
B2B hierarchy
SAP Hybris B2B accelerator gives you the ability to manage company organizations :
• Unit, basic block of an organization. A unit could represent a part (location, department)
or an entire organization
• Users, each user is attached to a unit and must have at least one of these roles :
• Cost center, assigned to units, orders are charged against a cost center
• Budget, assigned to units, if a unit exceed its budgets then orders are sent to an approver
• Credit limit, credit limit are assigned by the merchant to a unit, it exceeds the limit a manual
approval is needed
When you run SAP Hybris with the B2B accelerator you have access to a new panel under your
account to manage your company organization directly from the store front under My Company,
to see this your user need to be B2B administrator.
202 CHAPTER 11. USER MANAGEMENT
Chapter 12
Study tips
203
204 CHAPTER 12. STUDY TIPS
This covers suggestions and recommendations for SAP Hybris developers who have been working
on few implementations, have completed all trails from the wiki and are starting to look at the
certification proposed by SAP. If you have never attempted any certification exams this will be
stressful, all people at work keep asking you when you finally pass that certification!
Study plan
Before you even sign up for the test you first need to plan how you envision it :
2. I learn how to use the Groovy console to quickly debug and understand SAP Hybris
3. I configure my IDE with SAP Hybris and learn how to be comfortable with the console
5. I study each chapter and play with SAP Hybris and all code fragments provided
6. I pass the first mocked exam in real condition and list all unclear concepts and wrong answers
8. I pass the second mocked exam in real condition and list all unclear concepts and wrong
answers
10. The days before the exam I randomly pick questions and check if I know the answer
Mock exam 1
207
208 CHAPTER 13. MOCK EXAM 1
Questions
Mock 1 - Question 1
What assessments are correct about modules and extensions ?
1. A module is a synonym of template
2. An extension is never used alone
3. A module includes a set of functionalities fulfilled by one or more extensions
4. An extension holds source code and configuration files
−→ Go to the solution.
Mock 1 - Question 2
What is a saved query ?
1. A query that has been cached by the service layer
2. A way of reusing a query from the flexible search service
3. A flexible search query saved inside the SavedQuery item type and reusable from the HMC
4. There is no such query
−→ Go to the solution.
Mock 1 - Question 3
Why do you need to execute setantenv.sh** or **setantenv.bat before calling the build platform
?
1. To preload ant classes
2. To configure your PLATFORM_HOME environment variable
3. If you already have ant installed you do need to call this script
4. TO configure ant home and opts environment variable
−→ Go to the solution.
Mock 1 - Question 4
Choose the correct definition for the bean scope singleton
1. One shared instance, which will be returned by all calls to getBean with the given id
2. One shared instance per thread, which will be returned by all calls to getBean with the given
id
3. Independent instance resulting from each call to getBean
4. One shared instance per tenant, which will be returned by all calls to getBean with the given
id
−→ Go to the solution.
13.1. QUESTIONS 209
Mock 1 - Question 5
What is the "batch=true" Impex header modifier ?
1. creates an individual import context for each value line
2. Allows modifying more than one item for a combination of all unique attributes
−→ Go to the solution.
Mock 1 - Question 6
What are the steps in order to create a backoffice widget ?
1. create a widget view
−→ Go to the solution.
Mock 1 - Question 7
What is correct definition of the LTU eviction strategy ?
1. The oldest element would be deleted first
−→ Go to the solution.
Mock 1 - Question 8
Which of the following statements are not true regarding the use of inheritance in SAP Hybris
Item type definitions ?
1. All new item types must extend Object
2. All new item types must be declared within the Core extension
3. You can extend another item type only if it has been defined within the same extension
−→ Go to the solution.
210 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 9
Which one of the following design patterns has this as its primary goal ; Provides a single,
simplified interface to a complex system of mutually dependent interacting objects ?
1. Strategy
3. Service Layer
4. Facade
−→ Go to the solution.
Mock 1 - Question 10
If you are performing a flexible search query as the user admin which of the following is true ?
1. all restrictions on the search are ignored
3. you will only see in the result for the admin catalog
−→ Go to the solution.
Mock 1 - Question 11
When executing an Impex import, which of the following is true ?
1. you can only import one item type per Impex file
3. you need to specify the location of the CSV value lines file
4. if you don’t specify a header the Impex framework will find a matching item type
−→ Go to the solution.
Mock 1 - Question 12
OAUTH2 is
1. a library built by SAP Hybris to handle authentication
4. an authorization protocol
−→ Go to the solution.
13.1. QUESTIONS 211
Mock 1 - Question 13
To load a localized resource bundle, what service should you use ?
1. L10NService
2. I18NService
3. CommonI18NService
4. CommerceCommonI18NService
−→ Go to the solution.
Mock 1 - Question 14
How can you activate the cluster mode ?
1. cluster mode is on by default
3. configure clustermode=true
4. configure clustering=true
−→ Go to the solution.
Mock 1 - Question 15
What are the logging framework shipped with Hybris ?
1. LOG4J
2. LOG4J2
3. LOG4J3
4. SLF4J
−→ Go to the solution.
Mock 1 - Question 16
What happen when you run the following Impex script when the currency doesn’t exist yet ?
UPDATE Currency;isocode[unique=true];conversion;digits;symbol
;GBP;1;2;£
1. the import fails, log an error and move on to the next file
2. the import logs a warning and continue to resolve the remaining value lines
3. the import logs a warning, creates a temporary file, and try to import it later on
4. the import ignores non matching value lines when doing only UPDATE
−→ Go to the solution.
212 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 17
Why is it considered bad practice to call directly CartService.getSessionCart().getEntries().isEmpty()
to test if a customer already has a cart ?
1. this will create a cart if none is yet existing and the cart creation is expensive
−→ Go to the solution.
Mock 1 - Question 18
What is the correct definition of the Spring MVC dispatcher servlet ?
1. receives incoming API requests and dispatch them to the right extension
4. servlet responsible to load data from the database, load the JSP view and delegate the request
handling to a matching controller
−→ Go to the solution.
Mock 1 - Question 19
What template do you use do create a new cockpit ?
1. ycockpit
2. cockpit
3. ybackoffice
4. backoffice
−→ Go to the solution.
Mock 1 - Question 20
Which of the following cockpit import by convention files have a correct path and name ?
1. cockpitextension/resources/cockpitextension-admin/cscockpit/all/listViewContentBrowser_CatalogVersion.xm
2. cockpitextension/resources/cockpitextension/cscockpit/cockpitgroup/listViewContentBrowser_CatalogVersion
3. cockpitextension/resources/cockpitextension-admin/cscockpit/cockpitgroup/listViewContentBrowser.xml
4. cockpitextension/resources/cockpitextension-config/cscockpit/cockpitgroup/listViewContentBrowser_CatalogV
−→ Go to the solution.
13.1. QUESTIONS 213
Mock 1 - Question 21
Which methods are valid to create and save a new product item from the service layer ?
1.
ModelService modelService = spring.getBean("modelService");
ProductModel prd = new ProductModel();
//Fill the product object with valid data
modelService.save(prd);
2.
3.
−→ Go to the solution.
Mock 1 - Question 22
What is the correct definition of the ant target updatesystem ?
1.type system definitions are modified to match the new type system definition in the items.xml
files, the update mechanism makes sure that all data that existed in the system before the update
is still accessible after the update
2.type system definitions are recreated to match the new type system definition in the items.xml
files, the update mechanism makes sure that all data that existed in the system before the update
is still accessible after the update
3.type system definitions are modified to match the new type system definition in the items.xml
files, the update mechanism makes sure that all data that existed in the system are replaced by
new data
4.type system definitions are modified to match the new type system definition in the spring-
items.xml files, the update mechanism makes sure that all data that existed in the system before
the update is still accessible after the update
−→ Go to the solution.
Mock 1 - Question 23
How many currency items would be inserted from the following impex query, assuming they don’t
exist in SAP Hybris yet ?
INSERT_UPDATE Currency;isocode[unique=true];conversion;digits;symbol
;DKK;1;2;DKK
214 CHAPTER 13. MOCK EXAM 1
INSERT Currency;isocode[unique=true];conversion;digits;symbol
;DKK;7;2;DKK
INSERT_UPDATE Currency;isocode[unique=true];conversion;digits
;VND;7;2;VND
1. none
2. one
3. two
4. three
−→ Go to the solution.
Mock 1 - Question 24
Which of the following application contexts are valid ?
1. tenant service application context
−→ Go to the solution.
Mock 1 - Question 25
Is this a valid item type definition ?
<itemtype code="DeactivateOutdatedProductCronJob">
<description>Job to deactivate out-dated products</description>
<attributes>
<attribute type="java.util.Date" qualifier="minLastUpdate">
<persistence type="memory" />
</attribute>
</attributes>
</itemtype>
4. yes
−→ Go to the solution.
13.1. QUESTIONS 215
Mock 1 - Question 26
What does the ant target customize do ?
1. inject all properties into tomcat configuration
−→ Go to the solution.
Mock 1 - Question 27
What SQL query could be generated from the following flexible search query ?
select {pk} from {Product as prd}
−→ Go to the solution.
Mock 1 - Question 28
Which of the following item type attribute default value definition valid ?
1. <defaultvalue>java.lang.Boolean.FALSE</defaultvalue>
2. enumerationService().getEnumerationValue("validEnumeration", "validValue")
3. <defaultvalue>Boolean.FALSE</defaultvalue>
4. <defaultvalue>com.hybhub.core.ExistingClass.EXISTING_STATIC_STRING</defaultvalue>
−→ Go to the solution.
Mock 1 - Question 29
The SAP Hybris out of the box model service is used to ?
1. refresh the status of a data object
−→ Go to the solution.
216 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 30
What statements about the backoffice application orchestrator are wrong ?
1. it’s already visible when you are logged as an admin
−→ Go to the solution.
Mock 1 - Question 31
What is cached by SAP Hybris ?
1. result of flexible search queries
2. media images
3. item attributes
4. user sessions
−→ Go to the solution.
Mock 1 - Question 32
Choose the correct definition of an interface based architecture ?
1. defines an application as a collection of components, in which API calls between components
are made through abstract interfaces, not concrete classes
3. defines an application as a collection of static components, in which API calls between com-
ponents are made static references
4. defines an application as a collection of RESTFUL API entry points, calls between compo-
nents are made through HTTP requests
−→ Go to the solution.
Mock 1 - Question 33
What steps are required in order to create a new SAP Hybris cron job ?
1. create a new trigger for the job
−→ Go to the solution.
13.1. QUESTIONS 217
Mock 1 - Question 34
How do you declare an attribute dynamic ?
1.
<attribute type="dynamic" attributeHandler="myAttributeHandlerBean" />
1.
<persistence type="dynamic" attributeHandler="myAttributeHandlerBean" />
1.
<dynamic attributeHandler="myAtttibuteHandlerBean" />
1.
<persistence dynamic="myAtttibuteHandlerBean" />
−→ Go to the solution.
Mock 1 - Question 35
How is Spring configured in SAP Hybris ?
1. Explicit configuration in XML
2. Explicit configuration in Java
3. Implicit bean discovery and automatic wiring
4. Explicit configuration in XML, implicit bean discovery and automatic wiring
−→ Go to the solution.
Mock 1 - Question 36
How could you enable single product catalog synchronization from the PCM ?
1. catalog synchronization cannot be done from the PCM, it’s meant to be done by adminis-
trators only
2. configure expressUpdateCatalogVersions=catalog:version
3. each product can be synchronized individually out of the box
4. PCM is not for products
−→ Go to the solution.
Mock 1 - Question 37
What is the default authorization framework for the OCC web services ?
1. spring-security
2. oauth 2.0
3. java-security
4. sso
−→ Go to the solution.
218 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 38
In order to test a dao implementation what test should you write ?
1. @UnitTest
2. @DatabaseTest
3. @SqlTest
4. @IntegrationTest
−→ Go to the solution.
Mock 1 - Question 39
How can you use environment variables in your Hybris configuration ?
1. from a call back scripts
2. using hybhub.config=$NAME assuming the env variable exists and is named NAME
3. using hybhub.config=<CHANGE_ME> assuming the env variable exists and is name y_hybhub_config
4. using hybhub.config=
? assuming the env variable exists and is name hybhub_config
−→ Go to the solution.
Mock 1 - Question 40
What statements are correct about he following impex ?
INSERT_UPDATE MediaFolder;qualifier[unique=true];path[unique=true]
;images;images
;email-body;email-body
;email-attachments;email-attachments
1. only creates new MediaFolder
2. generates a unique database index from the qualifier and the path
3. contains 3 value lines
4. doesn’t use any macro
−→ Go to the solution.
Mock 1 - Question 41
Which one of the following flexible correct is valid ?
1. select name[de] from product
2. select name.de from product
3. select name[de] from product
4. select name from product,lang where lang = ’de’
−→ Go to the solution.
13.1. QUESTIONS 219
Mock 1 - Question 42
Choose the right definition for a payment capture ?
1. authorize an amount of money after it has been reserved
−→ Go to the solution.
Mock 1 - Question 43
Using the out of the box impex import convention, what files would be imported during the update
process (only create essential data checked) ?
1. extension/resources/impex/0_essentialdata.impex
2. extension/resources/impex/essentialdata_0.impex
3. extension/resources/impex/core/essentialdata_0.impex
4. extension/resources/impex/projectdata_users.impex
−→ Go to the solution.
Mock 1 - Question 44
"A navigation technique for accessing a collection of available information by narrowing down long
lists of objects to a manageable size. The reduction is achieved through attribute filters that can by
applied in flexible combinations of any order." best describes ?
1. facet search
2. solr
3. category search
4. flexible search
−→ Go to the solution.
Mock 1 - Question 45
How many catalog versions can be attached to a catalog ?
1. zero, a catalog defines its own version
2. one, the version can be shared across different catalogs, for example Online
3. two, catalogs have their own Staged and Online catalog versions
4. as many as needed, there are no limits at how many versions a catalog can have
−→ Go to the solution.
220 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 46
How many transactions would be created by the following Groovy script ?
def transaction = de.hybris.platform.tx.Transaction.current()
transaction.begin()
transaction.begin()
//Do something
transaction.commit()
transaction.begin()
//Do something
transaction.commit()
transaction.commit()
−→ Go to the solution.
Mock 1 - Question 47
What is the main entry servlet of Spring MVC application ?
1. SpringMvcServlet
2. DispatcherServlet
3. JaloServlet
4. RequestContextServlet
−→ Go to the solution.
Mock 1 - Question 48
What statements are true about CMSItem and CMSRelation item types ?
1. their sub items are catalog version aware
−→ Go to the solution.
13.1. QUESTIONS 221
Mock 1 - Question 49
How can you configure a new checkout flow ?
1. from an impex query
−→ Go to the solution.
Mock 1 - Question 50
What application context is valid to create a new region cache for an item type ?
1. core tenant
2. master tenant
3. core static
4. global static
−→ Go to the solution.
Mock 1 - Question 51
Choose the best definition for the following exception : de.hybris.platform.servicelayer.exceptions.AmbiguousIdentifierExcep
?
1. the service layer can’t find any matching identifier
2. the service layer found more than one matching item and expected only one
3. the service layer doesn’t know what attribute is used as the unique identifier
−→ Go to the solution.
Mock 1 - Question 52
What informations can you extract from a PK ?
1. type code
3. created time
−→ Go to the solution.
222 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 53
The Spring Integration Framework is used for ?
1. OCC webservices
2. Datahub
3. Hot Folder
4. Service Layer
−→ Go to the solution.
Mock 1 - Question 54
Where can you specify an index for an item type ?
1. resources/extensionName-indexes.xml
2. resources/extensionName-items.xml
3. resources/extensionName-indices.xml
4. resources/database/index.sql
−→ Go to the solution.
Mock 1 - Question 55
Choose the right definition for the order splitting service ?
1. split an order into sets of order entries, for each set a consignment is then created
2. split an order into multiple orders, for each orders a consignment is then created
3. split order entries into sets of order entries, for each set a consignment is then created
4. split a consignment into sets of consignments, for each set a new consignment is then created
−→ Go to the solution.
Mock 1 - Question 56
When designing a new web service what HTTP header should you choose to implement a create
object endpoint ?
1. GET
2. PUT
3. CREATE
4. POST
−→ Go to the solution.
13.1. QUESTIONS 223
Mock 1 - Question 57
What is the downside of product variants ?
1. none
2. you cannot have common attributes between variant objects without changing the base prod-
uct definition
4. all variant objects and the base product share the same unique code which makes any search
not trivial
−→ Go to the solution.
Mock 1 - Question 58
How could you group solr attribute values in a single set to avoid excessive number of values ?
1. use a group by statement
−→ Go to the solution.
Mock 1 - Question 59
Which of the following interceptors are valid ?
1. load
2. init
3. prepare
4. remove
−→ Go to the solution.
Mock 1 - Question 60
What statements are wrong about the build framework ?
1. it compiles extension in a pre-defined order
−→ Go to the solution.
224 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 61
A Media can be ?
1. a image
2. a zip file
3. a flat file
4. a string
−→ Go to the solution.
Mock 1 - Question 62
Which one of the following service is best suited to load a resource bundle for a specific language ?
1. I18NService
2. CommonI18NService
3. CommerceCommonI18NService
4. L10NService
−→ Go to the solution.
Mock 1 - Question 63
If I add the following search restriction for product and for user anonymous, what will happen
when anonymous users execute a product search ?
{name} is not null
2. this will replace any where clause for anonymous and product
3. this will be added to the where clause for anonymous and product
4. this will be added to the where clause for anonymous and product during solr indexing
−→ Go to the solution.
Mock 1 - Question 64
What happened when you execute the following Groovy script ?
import java.util.HashSet
import de.hybris.platform.core.model.user.UserGroupModel
groups.add(group)
modelService.save(customer)
1. a service layer exception is thrown
2. only the customer is created
3. only the user group is created
4. both the customer and the user group are created
−→ Go to the solution.
Mock 1 - Question 65
What statements are true about the promotion engine ?
1. runs on the rule engine
2. runs on the jalo layer
3. uses rule aware object (RAO) actions
4. runs when the promotion strategy is called during cart calculation
−→ Go to the solution.
Mock 1 - Question 66
How can you create a new socket for a custom backoffice widget ?
1. open your widget definition.xml file
2. use the HMC
3. run the widget wizard from OCC
4. create a new socket.zul file
−→ Go to the solution.
Mock 1 - Question 67
What statements are true about Apache SOLR ?
1. SAP Hybris uses an embedded SOLR server
2. SOLR uses the same database as SAP Hybris
3. all products are cached inside SOLR
4. SOLR can have multiple index
−→ Go to the solution.
226 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 68
Why would run the following flexible search query ?
select {pk} from {Product!}
−→ Go to the solution.
Mock 1 - Question 69
What is the right way to create a localized string attribute ?
1.
<attribute qualifier="name" type="java.lang.String">
<persistence type="property" localized="true"/>
</attribute>
2.
3.
4.
−→ Go to the solution.
Mock 1 - Question 70
What can you define permissions for (using the permission framework) ?
1. OCC access
2. item type
3. instance of an item type
4. attribute
−→ Go to the solution.
13.1. QUESTIONS 227
Mock 1 - Question 71
import ...
@SystemSetup(extension = HybhubhookConstants.EXTENSIONNAME)
public class HybhubHookSystemSetup extends AbstractSystemSetup
{
@SystemSetupParameterMethod
@Override
public List<SystemSetupParameter> getInitializationOptions()
{
final List<SystemSetupParameter> params = new ArrayList<>();
params.add(createBooleanSystemSetupParameter("key", "Choice",
֒→ false));
return params;
}
−→ Go to the solution.
Mock 1 - Question 72
Is this a valid impex import ?
INSERT_UPDATE Title;code
#% beforeEach: print(line[1]);
;Doctor
1. yes
2. yes only if bean shell execution is activated
3. yes only if the title Doctor doesn’t exist yet
4. no
−→ Go to the solution.
Mock 1 - Question 73
What is the recommended way of setting cluster ids ?
1. use cluster.node.autodiscovery=true
2. create a subnet and configure nodes to listen to the broadcast address
3. manually configure a unique id on each node
4. activate the Spring Cluster functionality
−→ Go to the solution.
Mock 1 - Question 74
Which are valid steps of the ant all target ?
1. Resolving extensions dependencies
2. Restart the application server
3. Delete all previously compiled classes
4. Generate sources for all extensions
−→ Go to the solution.
13.1. QUESTIONS 229
Mock 1 - Question 75
Which statements are correct about widget definitions ?
1. widget definition is as simple as creating a Spring bean under your core extension spring
configuration
2. A widget needs to extend another widget id in order to be available
3. Each widget ids must be unique otherwise they wouldn’t be available
4. Widgets definition are located under myextension/backoffice/resources/widgets/widgetName/definition.xml
−→ Go to the solution.
Mock 1 - Question 76
What is the best way to create a new addon for your store front ?
1. generate a new extension from yempty
2. generate a new extension from yoccaddon
3. generate a new extension from yaddon
4. generate a new extension from addon
−→ Go to the solution.
Mock 1 - Question 77
Is this a valid business process definition ?
<?xml version="1.0" encoding="utf-8"?>
<process>
</process>
1. yes
2. yes if you had a new action with start=true
3. yes if action1 implements StartProcess
4. no
−→ Go to the solution.
230 CHAPTER 13. MOCK EXAM 1
Mock 1 - Question 78
What are the required steps to create a new CMSComponent ?
1. create an item that extends AbstractCMSComponent or one of its subtype
−→ Go to the solution.
Mock 1 - Question 79
When should you run a full Apache SOLR indexation ?
1. when you restart the SOLR server
−→ Go to the solution.
Mock 1 - Question 80
How many websites could you have per tenant ?
1. only one because orders and customers are tenant dependent
Solutions
Mock 1 - Solution 1
3,4 are correct.
A module is made of one or more extensions to provide a set of related functionalities, like the
WCMS module made from different extensions : cms2lib, cmscockpit, cm2.
−→ Go back to the question.
Mock 1 - Solution 2
3 is correct.
A saved query can be used from the HMC to search a given item type from a customized and
possibly parameterized flexible search query.
13.2. SOLUTIONS 231
Mock 1 - Solution 4
1 is correct.
3 is the definition of prototype scope, 4 is correct only if you are inside different tenant application
context.
−→ Go back to the question.
Mock 1 - Solution 5
2 is correct.
When you need to update more than one item from the same value line use the batch mode.
−→ Go back to the question.
Mock 1 - Solution 6
1,3 are correct.
−→ Go back to the question.
Mock 1 - Solution 7
4 is correct.
The available eviction strategy are :
• LRU (Least Recently Used)
• LFU (Least Frequently Used)
• FIFO (First In First Out)
Mock 1 - Solution 8
*1,2,3,4 are correct.
1. All new item types extends GenericItem by default
2. Any extension with a core module defined could declare new item types
3. You can extend any item type from your extensions as long as you have a dependency to the
extension where the item type you inherit from is defined
4. All item types extend one item type (except AbstractItemModel)
Mock 1 - Solution 9
4 is correct.
−→ Go back to the question.
Mock 1 - Solution 10
1 is correct.
−→ Go back to the question.
Mock 1 - Solution 11
2 is correct.
After a header all lines would be imported (unless they are empty, contain comments or macro).
−→ Go back to the question.
Mock 1 - Solution 12
4 is correct.
SAP Hybris OCC uses OAUTH2, the Java implementation of the secured protocol is provided by
Spring under Spring-security-oauth2.
−→ Go back to the question.
Mock 1 - Solution 13
1 is correct.
• I18NService is to load Java Locale objects
Mock 1 - Solution 14
3 is correct.
−→ Go back to the question.
Mock 1 - Solution 15
2 is correct.
SLF4J is a simple logging facade for logging frameworks.
−→ Go back to the question.
Mock 1 - Solution 16
3 is correct.
If there is no item that matches the values of all key attributes, the value line cannot be resolved.
The value line is dumped into a temporary file and the ImpEx extension tries to resolve the value
line later on.
−→ Go back to the question.
Mock 1 - Solution 17
1 is correct.
Make sure your system does not create a new cart when the user does not need it. This has massive
impact to the system performance since for every session a new entry in the Carts table is created.
13.2. SOLUTIONS 233
In SAP Hybris, if using cartService.getSessionCart(), a new cart object is created implicitly if none
is yet existing for this session. You should always use cartService.hasSessionCart() before.
−→ Go back to the question.
Mock 1 - Solution 18
3 is correct.
A dispatcher servlet is the entry point of the Spring MVC framework, it loads the right controller
from its mapping, call the controller, use the view name answered by the controller to load a view,
and use the view and its model (loaded inside the controller) to generate a a response.
−→ Go back to the question.
Mock 1 - Solution 19
1 is correct.
−→ Go back to the question.
Mock 1 - Solution 20
4 is correct.
Remember extensionName/resources/extensionName-config/userGroup/context_itemType.xml
−→ Go back to the question.
Mock 1 - Solution 21
1,2,3 are correct
−→ Go back to the question.
Mock 1 - Solution 22
1 is correct.
−→ Go back to the question.
Mock 1 - Solution 23
2 is correct.
INSERT Currency;isocode[unique=true];conversion;digits
;DKK;7;2;DKK
would fail since because it’s conflicting with an existing item (de.hybris.platform.impex.jalo.imp.ItemConflictException)
−→ Go back to the question.
Mock 1 - Solution 24
2,4 are correct.
−→ Go back to the question.
Mock 1 - Solution 25
2 is correct.
To create a new SAP Hybris cronjob you need to extend the cronjob item type, but it doesn’t
make the item definition invalid.
−→ Go back to the question.
Mock 1 - Solution 26
3 is correct.
−→ Go back to the question.
Mock 1 - Solution 27
2 is correct.
234 CHAPTER 13. MOCK EXAM 1
Mock exam 2
239
240 CHAPTER 14. MOCK EXAM 2
Questions
Mock 2 - Question 1
What is/are the best definition(s) of the JALO Layer ?
−→ Go to the solution.
Mock 2 - Question 2
What changes need to be done in the following query to be imported successfully ?
\$productCatalog=apparelProductCatalog
\$productCatalogName=Apparel Product Catalog
INSERT_UPDATE
֒→ ApparelProduct;code;\$catalogVersion;unit(code);supercategories(code,\$catalogVersion)
;300441142;;pieces;Blue Tomato,caps
−→ Go to the solution.
Mock 2 - Question 3
Choose the correct file to localize HMC entries in English (extension’s name is hybhubcore)?
1. hybhubcore/resources/localization/hybhubcore-locales_en.properties
2. hybhubcore/resources/localization/hmc-locales_en.properties
3. hybhubcore/hmc/localization/hybhubcore-locales_en.properties
4. hybhubcore/resources/localization/english/hybhubcore.properties
−→ Go to the solution.
14.1. QUESTIONS 241
Mock 2 - Question 4
Select the right definition for the tenant concept ?
1. a single SAP Hybris installation with multiple localextensions.xml
2. a clustered SAP Hybris installation with one database
3. a single SAP Hybris installation with distinct sets of data
4. a single SAP Hybris installation with a specific database for each store
−→ Go to the solution.
Mock 2 - Question 5
When do you use cluster aware events ?
1. when you run a cluster all events need to be cluster aware
2. since SAP Hybris V6 all events are cluster aware
3. when you need to run an event from a specific node
4. when you need to broadcast an event to all nodes
−→ Go to the solution.
Mock 2 - Question 6
Why does the rule engine (used by the promotion engine) include a versioning and archiving mech-
anism ?
1. to keep an history of all promotions that ever existed on the system
2. to have a consistent representation of the applied rules when promotions were applied
3. to be able to work on different time zone
4. all item types in SAP Hybris are archived and versioned
−→ Go to the solution.
Mock 2 - Question 7
What is wrong with the following item type definition ?
<itemtype code="Subscription" extends="GenericItem">
<attributes>
<attribute type="java.lang.String" qualifier="code">
<persistence type="property" />
<modifiers unique="true"/>
</attribute>
</attributes>
<indexes>
<index name="codeIdx">
<key attribute="code"/>
</index>
</indexes>
</itemtype>
242 CHAPTER 14. MOCK EXAM 2
−→ Go to the solution.
Mock 2 - Question 8
Out of the box, what CMS items are used to build the top navigation menu ?
1. NavigationBarComponent
2. TopMenuNavigationComponent
3. CMSNavigationNode
4. CMSLinkComponent
−→ Go to the solution.
Mock 2 - Question 9
What steps do you need to fulfill in order to create a new cronjob ?
1. create a new cron job expression in your Spring XML
−→ Go to the solution.
Mock 2 - Question 10
What statements are wrong about catalog synchronization ?
1. only existing items can be updated
−→ Go to the solution.
14.1. QUESTIONS 243
Mock 2 - Question 11
Cached data are removed from the cache when ?
1. the cache is full
3. an item is created
4. an item is removed
−→ Go to the solution.
Mock 2 - Question 12
What statements are true about classification ?
1. classification is horizontal unlike categorization which is vertical
3. classification is not being used by SAP Hybris because its model type definition is flexible
−→ Go to the solution.
Mock 2 - Question 13
What can you do from an addon ?
1. add front end files (JSP, HTML, CSS and Javascript)
−→ Go to the solution.
Mock 2 - Question 14
What configuration file has the highest priority ?
1. project.properties from the platform extension
−→ Go to the solution.
244 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 15
When you create the following item type A what classes are being generated ?
<itemtype code="A" extends="ItemB" generate="false">
<attributes>
<attribute type="java.lang.String" qualifier="code">
<persistence type="property" />
<modifiers unique="true"/>
</attribute>
</attributes>
</itemtype>
1. A.java
2. GeneratedA.java
3. AJalo.java
4. AModel.java
−→ Go to the solution.
Mock 2 - Question 16
When configuring the Apache SOLR indexer mode what does DIRECT means ?
1. access the embedded Apache SOLR server
4. all index operations would be made on a temporary index before indexes are switch
−→ Go to the solution.
Mock 2 - Question 17
Is it possible for two tenants to use different extensions ?
1. yes using two different localextensions.xml, one for each tenant
−→ Go to the solution.
14.1. QUESTIONS 245
Mock 2 - Question 18
How do you install a new addon ?
1. add the addon inside your localextensions.xml
−→ Go to the solution.
Mock 2 - Question 19
Is this a valid Flexible Search Query ?
select {p.description[fr]:o} from {Product as p} where {p:pk} in
( {{ select {p:pk} from {product as p} where {p:code} like ’%0%’ }} )
1. no
2. yes if we delete :o
4. yes
−→ Go to the solution.
Mock 2 - Question 20
Out of the box how can you access the assisted service module functionalities ?
1. from the targeted storefront add a request parameter asm equal true
3. go to the /asmcockpit
4. go to the /cscockpit
−→ Go to the solution.
Mock 2 - Question 21
How can you initialize SAP Hybris ?
1. using ant initialize
−→ Go to the solution.
246 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 22
What is highest B2B organization block ?
1. company
2. unit
3. division
4. region
−→ Go to the solution.
Mock 2 - Question 23
In order to force a product to be listed on top of a given category, what out of the box feature(s)
should you use ?
1. boost rules
2. hero rules
3. hero products
4. top products
−→ Go to the solution.
Mock 2 - Question 24
What payment steps are described by the following definition ?
Transfer back money to a customer account, the transfer not being associated with
֒→ any order or previous transactions.
1. capture
3. capture
4. refund
−→ Go to the solution.
Mock 2 - Question 25
For what of the following things can the BTG module be used?
1. personalize a web applications based on customers
2. business to groups
−→ Go to the solution.
14.1. QUESTIONS 247
Mock 2 - Question 26
What ant target should you use to start working on a new B2C implementation ?
1. ant installer -r b2c_acc
2. ant extgen
3. ant modulegen
4. ant accelerator
−→ Go to the solution.
Mock 2 - Question 27
What Spring context has the largest scope ?
1. web context
2. core context
3. shared context
4. international context
−→ Go to the solution.
Mock 2 - Question 28
What will happen during an ImpEx Import when the import process can’t find a reference to an
item type ?
1. import process will fail and move onto the next file
3. the value line would be saved and a new attempt would be made
4. the value line would be saved and attached to an error log entry
−→ Go to the solution.
Mock 2 - Question 29
When loading available prices what is the price factory trying to match ?
1. customer / customer group
−→ Go to the solution.
248 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 30
What is the problem with the following business process action ?
package com.hybhub.core.process.action;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.orderprocessing.model.OrderProcessModel;
import de.hybris.platform.processengine.action.AbstractSimpleDecisionAction;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.task.RetryLaterException;
import javax.annotation.Resource;
@Resource
private ModelService modelService;
@Override
public Transition executeAction(final OrderProcessModel orderProcess)
֒→ throws RetryLaterException, Exception
{
OrderModel order = orderProcess.getOrder();
if(order!= null){
order.setNet(Boolean.TRUE);
modelService.save(order);
return Transition.OK;
}
return null;
}
}
1. it doesn’t always return a transition
2. it has not setter for the modelService attribute
3. it should implement Action<T>
4. the package is wrong
−→ Go to the solution.
Mock 2 - Question 31
What is true about the DefaultCMSComponentController controller ?
1. it will inject all attributes into the model
14.1. QUESTIONS 249
2. it will inject all front-end attributes (non system) into the model
4. it should be avoided
−→ Go to the solution.
Mock 2 - Question 32
What is true about the following log extracted from the build process ?
[echo] catalog->(validation,commons) 6.0.0.0-SNAPSHOT [p}cib]
−→ Go to the solution.
Mock 2 - Question 33
Choose the correct user rights definition to complete the following import query.
\$START_USERRIGHTS
Type;UID;MemberOfGroups;Password;Target;read;change;create;delete;change_perm
UserGroup;employeegroup;;
<Choose the right answer to complete this>
\$END_USERRIGHTS
1. ;;;;Media;true+;false;false;false;false
2. ;;;;Media;1;0;0;0;0
3. ;;;;Media;+;-;-;-;-
4. ;;;;Media;granted;denied;denied;denied;denied
−→ Go to the solution.
Mock 2 - Question 34
Which of the following components are deprecated ?
1. cockpit framework
2. Jalo layer
3. task engine
4. service layer
−→ Go to the solution.
250 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 35
What is the correct way of configuring a new logger for the package com.hybhub.hybhubaddon ?
1.
log4j.logger.com.hybhub.hybhubaddon = info
2.
log4j.logger.hybhub.name = com.hybhub.hybhubaddon
log4j.logger.hybhub.level = info
log4j.logger.hybhub.appenderRef.stdout.ref = STDOUT
3.
log4j2.logger.hybhub.name = com.hybhub.hybhubaddon
log4j2.logger.hybhub.level = info
log4j2.logger.hybhub.appenderRef.stdout.ref = STDOUT
4.
log4j2.logger.com.hybhub.hybhubaddon = info
log4j2.logger.com.hybhub.hybhubaddon = STDOUT
−→ Go to the solution.
Mock 2 - Question 36
The OCC webservices are ?
1. restful API
2. restless API
3. soap API
4. oAuth API
−→ Go to the solution.
Mock 2 - Question 37
What statements are wrong about converters ?
1. they all have the same bean parent abstractPopulatingConverter
−→ Go to the solution.
14.1. QUESTIONS 251
Mock 2 - Question 38
What is wrong with the following extensioninfo.xml file ?
<extensioninfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
֒→ xsi:noNamespaceSchemaLocation="extensioninfo.xsd">
<extension abstractclassprefix="Generated" classprefix="HybhubFacades"
֒→ name="hybhubfacades">
<requires-extension name="hybhubfacades"/>
<requires-extension name="hybhubcore"/>
<coremodule generated="true"
֒→ manager="de.hybris.platform.jalo.extension.GenericManager"
֒→ packageroot="com.hybhub.facades"/>
</extension>
</extensioninfo>
1. missing web module declaration
2. missing core module declaration
3. missing hmc module declaration
4. dependency issue
−→ Go to the solution.
Mock 2 - Question 39
Is the following dynamic attribute handler correct ?
package com.hybhub.core.model.dynamic;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.servicelayer.model.attribute.DynamicAttributeHandler;
@Override
public String get(ProductModel product)
{
return product.getCode() + " - " + product.getDescription();
}
}
1. no, it must extends ServiceLayerItems
2. no, it must also implement a setter
3. no, it must be in a different package
4. yes
−→ Go to the solution.
252 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 40
What statements are true about collections under item type definitions ?
1. a collection is comma-separated list of PKs
2. collections are preferred over relations
3. at runtime collections are loaded into a collection of objects
4. collections can store as many objects as needed
−→ Go to the solution.
Mock 2 - Question 41
Which of the following definition is the correct one for unit tests ?
1. requires access to the database and need a running SAP Hybris
2. requires access to the database and don’t need a running SAP Hybris
3. does not require access to the database and don’t need a running SAP Hybris
4. require access to the database and starts a transaction for each test
−→ Go to the solution.
Mock 2 - Question 42
What is the following Spring configuration doing ?
<context:annotation-config/>
<context:component-scan
base-package="...,..."
scope-resolver="..."/>
1. add a new XML Spring configuration
2. load all detected components from the given packages
3. create a new bean scope
4. configure a request filter
−→ Go to the solution.
Mock 2 - Question 43
When you synchronize a Media object from a Staged to an Online catalog what happens to the
media file ?
1. the Media file is referenced by the Online and Staged Media
2. the Media file is copied to the Online data folder and referenced by the Online Media
3. the Media file is moved to a shared folder and referenced by both Media
4. the Media file is embedded inside the file attribute and synchronize like all other attributes
−→ Go to the solution.
14.1. QUESTIONS 253
Mock 2 - Question 44
Select the right definition for the facade layer.
1. builds a complex object using simple objects and using a step by step approach
3. hides the complexities of the system and provides a simplified interface to the client
−→ Go to the solution.
Mock 2 - Question 45
Select the existing Impex header mode.
1. INSERTED
2. UPDATE_INSERT
3. REMOVE
4. DELETE
−→ Go to the solution.
Mock 2 - Question 46
How could you configure a new hot folder ?
1. from the HAC
−→ Go to the solution.
Mock 2 - Question 47
How do you create a new interceptor ?
1. declare it along with the item type definition
2. provide an implementation of one of the Interceptor interface and create a bean from it.
4. add a Spring bean mapping the item type and the Interceptor implementation
−→ Go to the solution.
254 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 48
A checkout step has ?
1. checkoutGroup reference
2. checkoutStepValidator reference
3. transitions map
4. progressBarId string
−→ Go to the solution.
Mock 2 - Question 49
What are are valid legacy cockpit areas ?
1. navigation
2. item
3. browser
4. editor
−→ Go to the solution.
Mock 2 - Question 50
When running an initialization on one tenant SAP Hybris will ?
1. delete all tables
3. delete all known tables starting with the tenant table prefix
−→ Go to the solution.
Mock 2 - Question 51
When creating a new item how do you generate a new primary key ?
1. using java.util.UUID.randomUUID()
−→ Go to the solution.
14.1. QUESTIONS 255
Mock 2 - Question 52
How could you declare configure an attribute to be encrypted ?
1.
<attribute qualifier="sensible" autocreate="true" type="java.lang.String">
<persistence type="property"/>
<modifiers encrypted="true"/>
</attribute>
2.
3.
4.
−→ Go to the solution.
Mock 2 - Question 53
Which item types exist ?
1. collectiontype
2. enumtype
3. atomictype
4. listtype
−→ Go to the solution.
Mock 2 - Question 54
A customer segment could be executed in ?
1. optimized processing
2. full processing
3. jalo processing
4. complete processing
−→ Go to the solution.
256 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 55
Why a Spring MCV controller needs to return a String ?
1. to return it as an HTML page
2. to load a view
3. to load a servlet
4. to load a model
−→ Go to the solution.
Mock 2 - Question 56
What features are available through the Order Management Module (formally OMS) ?
1. order splitting
2. payment
3. sourcing
4. promotion engine
−→ Go to the solution.
Mock 2 - Question 57
Why do you need to define stop words for for your search configuration ?
1. to ignore configured words while searching
−→ Go to the solution.
Mock 2 - Question 58
What are the two main components of the rule engine ?
1. rule processor
2. rule matcher
3. rule executor
4. rule builder
−→ Go to the solution.
14.1. QUESTIONS 257
Mock 2 - Question 59
How could you improve the following code (groovy) ?
import de.hybris.platform.processengine.enums.ProcessState
businessProcessService.startProcess(process)
modelService.refresh(process)
if(ProcessState.SUCCEEDED != process.getProcessState()){
businessProcessService.startProcess(process)
}
1. use the method <T extends BusinessProcessModel> T startProcess(String arg0, String arg1);
to create a process
−→ Go to the solution.
Mock 2 - Question 60
What statements are true about the following table (SQL DDL for HSQL) ?
CREATE CACHED TABLE b2bbudgetslp
(
ITEMPK BIGINT,
ITEMTYPEPK BIGINT,
LANGPK BIGINT,
p_name NVARCHAR(255),
PRIMARY KEY (ITEMPK, LANGPK)
);
−→ Go to the solution.
258 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 61
Why would you use classification ?
1. to optimize Apache SOLR requests
3. to speed up search
−→ Go to the solution.
Mock 2 - Question 62
Which facet search configuration attributes give you the ability to redirect a user for a specific
search request ?
1. stopwords
2. keywords
3. redirectwords
4. matchwords
−→ Go to the solution.
Mock 2 - Question 63
What statements are wrong about extensions ?
1. they have to be inside the bin folder
−→ Go to the solution.
Mock 2 - Question 64
What statements are true about the SAP Hybris server ?
1. based on Apache Tomcat
−→ Go to the solution.
14.1. QUESTIONS 259
Mock 2 - Question 65
When you run an impex import query from the HAC with the default configuration what statements
are true ?
1. you are running distributed impexes
−→ Go to the solution.
Mock 2 - Question 66
Which of the following would be good uses for a SAP Hybris CronJob ?
1. synchronizing the stock level with an external warehouse once per day
2. notify the System Administrator when the peak load on the server passes a critical point
4. any task that isn’t database related, cronjobs are designed to perform operating System
tasks, not database system tasks
−→ Go to the solution.
Mock 2 - Question 67
Content slots for page template are ?
1. place holder for CMS component
−→ Go to the solution.
Mock 2 - Question 68
Which bean would be loaded from getBean("bean") ?
<bean name="stringBean" class="java.lang.String" >
<constructor-arg><value>my String Name</value></constructor-arg>
</bean>
1. my String Name
2. my String ID
3. a new String
4. none
−→ Go to the solution.
Mock 2 - Question 69
Is it possible to add new enumeration values by runtime ?
1. no
−→ Go to the solution.
Mock 2 - Question 70
What a POS is ?
1. a warehouse
2. a physical store
3. a web store
4. a geolocalization service
−→ Go to the solution.
Mock 2 - Question 71
What statements are wrong about Backoffice widgets ?
1. widget can extend each other
−→ Go to the solution.
14.1. QUESTIONS 261
Mock 2 - Question 72
When writing unit tests how should you simulate pojo dependencies to external services, facades...
?
1. the test class should extend HybrisUnitTests
−→ Go to the solution.
Mock 2 - Question 73
What is the notification framework used for ?
1. notify cockpit users
2. notify customers
3. notify administrators
−→ Go to the solution.
Mock 2 - Question 74
What statements are true about stock levels ?
1. the stock service can check stock levels across multiple warehouses
2. a single warehouse can contain multiple stock levels for the same product
−→ Go to the solution.
Mock 2 - Question 75
The CS cockpit was designed for ?
1. customer segment management
−→ Go to the solution.
262 CHAPTER 14. MOCK EXAM 2
Mock 2 - Question 76
SAP Hybris semi-session failover mechanism allows to ?
1. automatically redirected users to the login page of a new node when on node goes down
2. to transfer all sessions of the failing node to other available nodes without loss of data
3. to always have all sessions replicated on every nodes
4. to automatically redirect users to a temporary page
−→ Go to the solution.
Mock 2 - Question 77
Choose the flexible query which has generated the following SQL query ?
SELECT item_t0.PK, item_t1.p_code
FROM products item_t0 LEFT JOIN medias item_t1
ON item_t1.PK = item_t0.p_logo
WHERE ((item_t0.TypePkString=? AND (item_t1.TypePkString IS NULL OR (
֒→ item_t1.TypePkString=? ) )))
1. select prd.pk, md.code from Product as prd left join Media as md on md.pk = prd.logo
2. select prd.pk, md.code from Product! as prd join Media! as md on md.pk = prd
3. select prd.pk, md.code from Product! as prd left join Media! as md on md.pk = prd.logo
4. select md.code from Product as prd left join Media! as md on md.pk = prd.logo
−→ Go to the solution.
Mock 2 - Question 78
What service should you use to save an model ?
1. persistenceService
2. jaloService
3. serviceLayerService
4. modelService
−→ Go to the solution.
Mock 2 - Question 79
If you are testing a Flexible Search Restriction, the user you are running the query as ?
1. should be admin
2. should be flexiblesearchquery
3. should be a member of the searchquery group
4. should not be a member of the admin group
−→ Go to the solution.
14.2. SOLUTIONS 263
Mock 2 - Question 80
With default configuration when you load a model item with the model service (for examples product
model).What is automatically loaded inside the object ?
1. nothing, all attributes are lazy loaded
4. all
−→ Go to the solution.
Solutions
Mock 2 - Solution 1
1 and 2 are correct.
−→ Go back to the question.
Mock 2 - Solution 2
1 and 3 are correct.
−→ Go back to the question.
Mock 2 - Solution 3
1 is correct.
−→ Go back to the question.
Mock 2 - Solution 4
3 is correct.
−→ Go back to the question.
Mock 2 - Solution 5
3 and 4 are correct.
When you implement the interface ClusterAwareEvent you need to implement the method pub-
lish(int sourceNodeId, int targetNodeId), but you are free to decide whether your code should run
on a very specific node (answer 3) or on all nodes (answer 4). In order to be able to broadcast and
process it to all nodes you need to return true in the publish method like so:
264 CHAPTER 14. MOCK EXAM 2
package com.hyhub.core;
import de.hybris.platform.servicelayer.event.ClusterAwareEvent;
import de.hybris.platform.servicelayer.event.impl.AbstractEventListener;
@Override
protected void onEvent(AnyEvent event) {
// your logic
}
/**
* Decide weather this event should be broadcasted/received. Examples are
* <ul>
* <li><code>return (sourceNodeId==targetNodeId );</code> => will only publish to
֒→ local cluster</li>
* <li><code>return true;</code> => will publish to all nodes</li>
* <li><code>return (targetNodeId==14);</code> => publish to dedicated node
֒→ regardless of source</li>
* </ul>
* @return <code>true</code> if event should be published from source cluster node
֒→ to target cluster node
*/
@Override
public boolean publish(int sourceNodeId, int targetNodeId) {
// publish event on all cluster nodes
return true;
}
}
Mock 2 - Solution 6
2 is correct.
−→ Go back to the question.
Mock 2 - Solution 7
4 is correct.
−→ Go back to the question.
Mock 2 - Solution 8
1,3,4 are correct.
−→ Go back to the question.
Mock 2 - Solution 9
2,3 are correct.
−→ Go back to the question.
Mock 2 - Solution 10
1,2,3 are correct.
14.2. SOLUTIONS 265
• literal
• all
• default (equal to none)
Mock exam 3
271
272 CHAPTER 15. MOCK EXAM 3
Questions
Mock 3 - Question 1
Dynamic forms are used to ?
−→ Go to the solution.
Mock 3 - Question 2
When you use advanced personalization what are the valid scopes for segment rule results?
1. Singleton
2. Session
3. Web
4. Permanent
−→ Go to the solution.
Mock 3 - Question 3
Choose the right definition for the modulegen ant task
1. Generate sets of dependent extensions to quickly start new projects or create new applications
2. Generate a single dependent extension to quickly start new projects or create new applications
3. Generate new extensions based on extension templates
4. Generate new empty extensions
−→ Go to the solution.
Mock 3 - Question 4
Which of the following are out of the box point of services ?
1. Factory
2. ServiceDesk
3. Store
4. Warehouse
−→ Go to the solution.
15.1. QUESTIONS 273
Mock 3 - Question 5
What attribute from the stock level item are mandatory?
1. A product model
2. A product code
3. A point of service
4. A warehouse
−→ Go to the solution.
Mock 3 - Question 6
What is the ant command used to generate a new backoffice extension ?
1. ant modulegen
2. ant ybackofficegen
3. ant extgen
4. ant extensiongen
−→ Go to the solution.
Mock 3 - Question 7
Which of the following language are available to write dynamic form scripts?
1. beanshell
2. groovy
3. spel
4. javascript
−→ Go to the solution.
Mock 3 - Question 8
What is the correct way to create a new cockpit ?
1. add a new line in the xml config file for cockpit (cockpits.xml)
2. create a new cockpit model from the hac (impex) or the hmc
−→ Go to the solution.
274 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 9
Inside the configuration folder you have a file called local_tenant_all.properties, what is it ?
1. a property file for all tenants
−→ Go to the solution.
Mock 3 - Question 10
Why would you use a widget virtual socket rather than a widget regular socket
1. to add a socket at runtime
−→ Go to the solution.
Mock 3 - Question 11
What statements are true about the widget application context ?
1. it belongs to the CS cockpit
−→ Go to the solution.
Mock 3 - Question 12
Dynamic forms can perform actions on which of the following elements ?
1. spring bean
2. enumeration
3. backoffice orchestrator
−→ Go to the solution.
15.1. QUESTIONS 275
Mock 3 - Question 13
What statements are true about a new extension created from the ycockpit template ?
1. it has only one perspective
2. it has no perspective
−→ Go to the solution.
Mock 3 - Question 14
A cockpit perspective is composed of which of the following elements ?
1. a navigation area
2. a browser area
3. an editor area
4. a product area
−→ Go to the solution.
Mock 3 - Question 15
What statement(s) are true about cockpit wizards ?
1. it guides users through complex item creation
4. wizards are part of the backoffice framework not the cockpit framework
−→ Go to the solution.
Mock 3 - Question 16
When implementing a new payment provider, what is the most important ?
1. requests should be done using SSL encryption
−→ Go to the solution.
276 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 17
What are the new features of Hybris V6 compared to V5?
1. backoffice
2. Yaas integration
3. rule engine
4. smart edit
−→ Go to the solution.
Mock 3 - Question 18
What makes a B2B implementation different than a B2C?
1. B2B needs to manage customer credit
3. B2B most likely will ask customer to login before they can access the catalog
−→ Go to the solution.
Mock 3 - Question 19
What is de the default password encryption?
1. none
2. md5
3. sha-512
4. pbkdf2
−→ Go to the solution.
Mock 3 - Question 20
How can you create a new promotion rule?
1. from the backoffice by using a template
−→ Go to the solution.
15.1. QUESTIONS 277
Mock 3 - Question 21
What are OCC v2 new features?
1. stateless
2. stateful
3. restful
−→ Go to the solution.
Mock 3 - Question 22
In SAP Hybris 6.2 what is the recommended to have promotions
1. the promotion engine
−→ Go to the solution.
Mock 3 - Question 23
When 2 promotions (promotion engine) have the same priority how does SAP Hybris order them
1. alphabetically
2. can’t be determined
3. date of creation
4. uuid
−→ Go to the solution.
Mock 3 - Question 24
What statements are true about the rule compiler ?
1. when compiling it uses the IR data structure
−→ Go to the solution.
278 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 25
How do you define a new RAO object ?
1. create new item type in a items.xml file
−→ Go to the solution.
Mock 3 - Question 26
When creating a new condition translator what are the available conditions ?
1. RuleIrTrueCondition
2. RuleIrFalseCondition
3. RuleIrGroupCondition
4. RuleIrAttributeCondition
−→ Go to the solution.
Mock 3 - Question 27
Where should you manage the visibility restrictions of an existing CMS page ?
1. hac
2. hmc
3. CMS cockpit
−→ Go to the solution.
Mock 3 - Question 28
What statements are true about flexible search restrictions ?
1. they only apply for anonymous users
−→ Go to the solution.
15.1. QUESTIONS 279
Mock 3 - Question 29
Tenants let you choose a specific ?
1. set of extensions
2. time zone
3. currency
4. database
−→ Go to the solution.
Mock 3 - Question 30
Can you use SOLR to index something else than products ?
1. yes, if you have at least 2 solr servers
2. yes, if you have at least 2 tenants
3. yes, if you create a new index
4. no, it’s not possible
−→ Go to the solution.
Mock 3 - Question 31
To create a new CMS restriction type (for example loyal customers with at least 3 past orders)
what do you need to do ?
1. create a new item type for your restriction extending AbstractRestriction
2. create an implementation of de.hybris.platform.cms2.servicelayer.services.evaluator.CMSRestrictionEvaluator
with the restriction logic
3. create a new spring bean for my restriction evaluator
4. create a new spring bean to map my evaluator with my item type
−→ Go to the solution.
Mock 3 - Question 32
What could be improved with the following DAO ?
package de.hybris.dao;
import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.servicelayer.internal.dao.DefaultGenericDao;
import java.util.List;
import java.util.Set;
3. extends CachedDao<ProductModel>
−→ Go to the solution.
Mock 3 - Question 33
How many item types can a single cache region handle ?
1. only one
−→ Go to the solution.
Mock 3 - Question 34
Choose the best definition for the FIFO eviction strategy ?
1. objects are evicted based on their age, newest first
−→ Go to the solution.
Mock 3 - Question 35
What can you do with the Assised Service Module (ASM) ?
1. create a cart in behalf of a customer
Mock 3 - Question 36
What is best approach to implement the following requirements ?
From my custom backoffice perspective, I want the product description to be
֒→ filled with the product name automatically if empty.
1. create a new prepare interceptor
2. create a new dynamic form for the backoffice
3. customize the ProductModel constructor
4. create a cron job to scan products
−→ Go to the solution.
Mock 3 - Question 37
How does SAP Hybris redirect a URL is redirect to the correct store front ?
1. using different port
2. stores have URL patterns
3. websites have URL patterns
4. using different ips
−→ Go to the solution.
Mock 3 - Question 38
Where can you define a new socket for a widget ?
1. myextension-widgets.xml
2. myextension-backoffice.xml
3. mywidget/definition.xml
4. mywidget/config.xml
−→ Go to the solution.
Mock 3 - Question 39
What functionality should you use to periodically check for product out of stock ?
1. task service
2. cronjob service
3. stockCheck service
4. productSentinel service
−→ Go to the solution.
282 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 40
Can you override a content slot defined in a page template when you are editing a page ?
1. yes, if the slot is empty
2. yes, if you are editing another page template extending the first one
3. yes
−→ Go to the solution.
Mock 3 - Question 41
What statements are true about macrodefs ?
1. they are part of the build framework
2. they can add build custom logic logic before or after each build step
−→ Go to the solution.
Mock 3 - Question 42
What version(s) of OCC is activated by default ?
1. V1
2. V2
3. V1 and V2
4. none
−→ Go to the solution.
Mock 3 - Question 43
When call OCC API, request filters are executed before or after the controllers ?
1. always before
2. always after
−→ Go to the solution.
15.1. QUESTIONS 283
Mock 3 - Question 44
What statements are true about the following relation definition ?
<relation code="Product2KeywordRelation" autocreate="true" generate="true"
֒→ localized="true">
<deployment table="Prod2KeywordRel" typecode="604"/>
<sourceElement qualifier="keywords" type="Keyword" cardinality="many"
֒→ ordered="true" collectiontype="list">
<description>Keywords</description>
<modifiers read="true" write="true" search="true"
֒→ optional="true"/>
</sourceElement>
<targetElement qualifier="products" type="Product" cardinality="many"
֒→ ordered="false">
<description>Products</description>
<modifiers read="true" write="true" search="true"
֒→ optional="true"/>
</targetElement>
</relation>
1. defines a new item type Product2KeywordRelation
2. will create a new database table Prod2KeywordRel
3. a relation can’t be localized
4. a new attribute products will be visible from the Keyword item type
−→ Go to the solution.
Mock 3 - Question 45
Choose the right definition for a converter ?
1. create new instance of model objects and call populators to populate them
2. create new instance of data objects and call populators to populate them
3. populate a data object attributes from a model object
4. populate a model object attributes from a data object
−→ Go to the solution.
Mock 3 - Question 46
Is this a correct flexible search query ?
delete from {Product} where {code} like ’prd123’
1. no, because it’s missing the semi colon
2. no, because you can’t use like in a where clause
3. no, because flexible search query can’t execute delete statements
4. no, because you need the primary key to delete an item
−→ Go to the solution.
284 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 47
If one item attribute contains sensitive data what should you do ?
1. use password encrypted attribute
−→ Go to the solution.
Mock 3 - Question 48
In a multi tenant system how could you be sure that a Spring bean is unique across different tenants
?
1. use the tenant scope
−→ Go to the solution.
Mock 3 - Question 49
facets could be of which type ?
1. MultiSelectAnd
2. MultiSelectOr
3. Refine
4. Define
−→ Go to the solution.
Mock 3 - Question 50
Which of the following item types are valid B2B item types ?
1. B2BUnit
2. B2BBudget
3. B2BCostCenter
4. B2BCustomer
−→ Go to the solution.
15.1. QUESTIONS 285
Mock 3 - Question 51
Give the correct definition of cross site scripting ?
1. malicious code is sent to and executed by end users’ web browsers
−→ Go to the solution.
Mock 3 - Question 52
How can you install an SAP license for SAP Hybris ?
1. ant -install /home/hybris/license.txt
4. ./licenseInstall.sh /home/hybris/license.txt
−→ Go to the solution.
Mock 3 - Question 53
Why would you run a dependent synchronization ?
1. your catalogs extend each other
−→ Go to the solution.
Mock 3 - Question 54
What happen when you update SAP Hybris ?
1. it updates items type code according to items.xml files
−→ Go to the solution.
286 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 55
After adding a new attribute into the product item type definition, what is needed to forward this
attribute into the SOLR index ?
1. nothing the build process would generate a value resolver based on the attribute type and
map it with SOLR
−→ Go to the solution.
Mock 3 - Question 56
Which of the following are available accelerators within SAP Hybris 6.2 ?
1. China accelerator
2. B2B accelerator
3. Telco accelerator
4. Travel accelerator
−→ Go to the solution.
Mock 3 - Question 57
What is the best way to start a new project from an accelerator ?
1. ant extgen nameOfTheAccelerator
3. ./install.sh -i nameOfTheAccelerator
4. ./install.sh -p nameOfTheAccelerator
−→ Go to the solution.
Mock 3 - Question 58
What steps are required to create a new wizard for a legacy cockpit ?
1. defines a new Spring bean for the wizard de.hybris.platform.cockpit.wizards.Wizard
−→ Go to the solution.
15.1. QUESTIONS 287
Mock 3 - Question 59
How should you implement the following requirement ?
We need all products within our SAP Hybris system to carry a new uid generated
֒→ from an external system integrated with our platform.
−→ Go to the solution.
Mock 3 - Question 60
How should you implement the following requirement ?
We need to have a different product catalog for each season. Most important we
֒→ need to be able to work on any catalog at any moment even if they are not
֒→ online.
−→ Go to the solution.
Mock 3 - Question 61
How should you install a the captcha addon into your store front extension ?
1. ant addoninstall -Daddonnames="captchaaddon" -DaddonStorefront.myStoreFront="myStoreFront"
2. ant addoninstall -Daddonnames="captchaaddon" myStoreFront
3. add <requires-extension name="captchaaddon"/> into your store front extensioninfo.xml
4. add myStoreFront.additionalWebSpringConfigs.captchaaddon=classpath
:/captchaaddon/web/spring/captchaaddon-web-spring.xml into your property file
−→ Go to the solution.
Mock 3 - Question 62
Choose the appropriate term defined by ?
User interface where you can create and maintain rules and rule templates
1. Rule Engine
2. Rule Cockpit
288 CHAPTER 15. MOCK EXAM 3
3. Rule Design
4. Rule Builder
−→ Go to the solution.
Mock 3 - Question 63
How could SAP Hybris decide to create multiple consignments for the same order ?
1. if you have implemented a custom business process for order fulfillment
−→ Go to the solution.
Mock 3 - Question 64
Is this a valid impex file ?
INSERT_UPDATE Employee;UID;name;groups(uid);description;password
;CustomerSupportAdministrator;Customer Support
֒→ Administrator;customersupportadministratorgroup;This generic Customer Support
֒→ Administrator.;1234
1. yes
2. no
−→ Go to the solution.
Mock 3 - Question 65
How can you be sure your property file are compatible with every existing characters (French,
Chinese, Vietnamese, Hindi...) ?
1. each language should have a different encoding (UTF-FR for French, ISO-HINDI for In-
dian,...)
−→ Go to the solution.
15.1. QUESTIONS 289
Mock 3 - Question 66
What is the correct definition of the service layer ?
1. interconnects data objects with the client (api, controllers...) and hold logic to perform
business processes
2. interconnects external service with SAP Hybris hold logic to perform business processes
3. interconnects model objects with the client (api, controllers...) hold logic to perform business
processes
−→ Go to the solution.
Mock 3 - Question 67
What media storage strategy does SAP Hybris 6.2 offers out of the box ?
1. nfs media storage strategy
−→ Go to the solution.
Mock 3 - Question 68
When creating a new cms component item type what item type should yours extend from ?
1. CMSItem
2. SimpleCMSComponent
3. AbstractCMSComponent
4. CMSComponentType
−→ Go to the solution.
Mock 3 - Question 69
How to you access the backoffice orchestrator ?
1. Login as an admin into the backoffice and open the orchestrator perspective
2. Login as an admin into the hmc and open the orchestrator perspective
3. Login as an admin into the hac and open the orchestrator tab
−→ Go to the solution.
290 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 70
In a widget zul file what slot(s) can you use to embed another widget ?
1. <widget .../>
2. <widgetslot .../>
3. <widgetchild .../>
4. <widgetchildren .../>
−→ Go to the solution.
Mock 3 - Question 71
How does SAP Hybris provides to secure the platform ?
1. attribute encryption
2. xss protection
3. access rights
4. password encoding
−→ Go to the solution.
Mock 3 - Question 72
How does SOLR handle localized attributes ?
1. it creates a copy of the each product document for each language
2. it creates a map for each localized attribute (the key being the language code)
3. it creates one attribute for each language (name ends with _en, _de...)
−→ Go to the solution.
Mock 3 - Question 73
When connecting two widgets through a socket, what statements are true ?
1. the data type must be serializable
−→ Go to the solution.
15.1. QUESTIONS 291
Mock 3 - Question 74
What do you need to provide to create a search restriction ?
1. targeted attribute(s)
2. targeted catalog(s)
4. targeted tenant
−→ Go to the solution.
Mock 3 - Question 75
Which of the following are price row attributes ?
1. currency
2. price group
4. minimum quantity
−→ Go to the solution.
Mock 3 - Question 76
Which of the following are valid workflow action statuses ?
1. new
2. pending
3. deleted
4. disabled
−→ Go to the solution.
Mock 3 - Question 77
What is the correct definition of a B2B approver ?
1. to provide customer approval for an order
−→ Go to the solution.
292 CHAPTER 15. MOCK EXAM 3
Mock 3 - Question 78
Is it possible to abort a cron job ?
1. yes, if your job performable extends AbortJobPerformable
2. yes, if isAbortable() returns true
3. yes, if you implement the abortable logic within the PerformResult method of your job
4. none of the above
−→ Go to the solution.
Mock 3 - Question 79
Which of the following user / user group can’t be deleted ?
1. anonymous
2. cockpitgroup
3. backofficegroup
4. anonymousgroup
−→ Go to the solution.
Mock 3 - Question 80
When writing a new integration test class, what already existing class should you extend to assure
isolation ?
1. ServiceLayerIsolatedTest
2. ServiceLayerTest
3. ServiceLayerRollbackTransactionalTest
4. ServiceLayerTransactionalTest
Solutions
Mock 3 - Solution 1
2 are correct.
Dynamic forms are used to add logic within a wizard or editor area.
−→ Go back to the question.
Mock 3 - Solution 2
2 and 4 are correct.
−→ Go back to the question.
Mock 3 - Solution 3
1 is correct.
15.2. SOLUTIONS 293
if (clearAbortRequestedIfNeeded(cronJob))
{
return new PerformResult(CronJobResult.ERROR, CronJobStatus.ABORTED);
}
Mock 3 - Solution 79
1 is correct.
−→ Go back to the question.
Mock 3 - Solution 80
4 is correct.
300 CHAPTER 15. MOCK EXAM 3
Alphabetical Index
OAuth 2, 56 OCC, 53
301