SAP Hybris V6 Certified Development Professional - Study Guide
SAP Hybris V6 Certified Development Professional - Study Guide
Development Professional
Study Guide
Benoit
Vanalderweireldt
SAP Hybris V6 Certified Development
Professional | Study Guide
Benoit Vanalderweireldt
2016-10-25
© 2017 Hybhub
© 2014 hybris AG or an SAP affiliate company. All rights reserved. Hybris and
other Hybris products and services mentioned herein as well as their respective
logos are trademarks or registered trademarks of hybris AG (or an SAP affiliate
company) in Switzerland, Germany and other countries. All other product and
service names mentioned are the trademarks of their respective companies. learn
more
Contents
1 Introduction 6
About the author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Groovy console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Example Groovy console . . . . . . . . . . . . . . . . . . . . . . . 8
Assessment test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2 WCMS 16
CMS Items hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
CMSItem CMSRelation . . . . . . . . . . . . . . . . . . . . . . . 17
CMSItem types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
CMS Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Example how to create a cms component . . . . . . . . . . . . . 18
Personalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Segmentation rules . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Segmentation actions . . . . . . . . . . . . . . . . . . . . . . . . . 22
Create a CMS restriction . . . . . . . . . . . . . . . . . . . . . . 22
WCMS cockpit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Warehouse & point of service . . . . . . . . . . . . . . . . . . . . . . . 23
Warehouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Point of services . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2
Create / customize webservices . . . . . . . . . . . . . . . . . . . 42
CMS navigation bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Order splitting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Promotion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Payment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Internationalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Request handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Request filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Hot folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Create a new import configuration . . . . . . . . . . . . . . . . . 55
Data Modeling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Create new types . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5 Order management 88
Business process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Fulfillment process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Shopping cart handling . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Checkout flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
ASM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
CS Cocpkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Introduction
Dear Reader,
Thank you for choosing SAP Hybris V6 Certified Development Professional |
Study Guide to prepare for your SAP certification.
I’d be very interested to hear your feedback on how you are doing after using
this e-book. Feel free to let me know what you think about this study guide by
sending an email to [email protected].
If you disagree or think there are technical errors, feel free to share it with me.
Requirements
In order to use this study guide you need :
1. SAP H[y]bris V6.x
2. access to http://help.hybris.com
3. access to http://experts.hybris.com
4. a working IDE compatible with SAP Hybris (Eclipse, IntelliJ, Netbeans…)
6
5. a JDK 8 installed
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
Example loading a product:
1 import de.hybris.platform.servicelayer.search.FlexibleSearchService
2 import de.hybris.platform.catalog.CatalogVersionService
3 import de.hybris.platform.catalog.model.CatalogVersionModel
4 import de.hybris.platform.core.model.product.ProductModel
5
14 pm = fss.getModelByExample(pm)
15
16 println pm.getName()
Example Groovy console
Assessment test
When you prepare the P_HYCD_60 exam to become a SAP Certified
Development Professional - SAP Hybris Commerce 6.0 Developer you have a
lot of questions like :
• How do I know I’m ready for the exam ?
• How hard are the questions ?
• How do I know what chapter I need to focus on ?
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_60 if you were
trying today. So let’s get started, try to answer all the questions in real
conditions.
Questions
Pretest - Question 1
When you initialize SAP Hybris from ant, what actions are executed ?
1. Aborts all running cronjobs
2. Delete and recreate the database
3. Delete all known tables
4. Import all project data
Solution
Pretest - Question 2
Changing SAP Hybris configuration from the project.properties file of your
platform project is considered bad because ?
1. This doesn’t follow SAP Hybris licence
2. It makes future updates harder
3. The file is already too big
4. This file is ignored after you create a new config folder from it
Solution
Pretest - Question 3
Is this a valid Flexible Search Query ?
1 SELECT {p.pk} FROM {Principal} AS p WHERE {p.uid} = 'admin'
Solution
Pretest - Question 4
According to the following extensioninfo.xml what statements are true ?
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <extensioninfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:noNamespaceSchemaLocation="extensioninfo.xsd">
4
5 <extension abstractclassprefix="Generated" classprefix="
HybhubStorefront"
6 name="hybhubstorefront">
7
8 <requires-extension name="assistedservicestorefront"/>
9 <requires-extension name="smarteditaddon"/>
10 <requires-extension name="captchaaddon"/>
11 <requires-extension name="acceleratorstorefrontcommons"/>
12 <requires-extension name="hybhubfacades"/>
13
14 <webmodule jspcompile="false" webroot="/hybhubstorefront"/>
15
16 <meta key="extgen-template-extension" value="true"/>
17
18 </extension>
19
20 </extensioninfo>
Solution
Pretest - Question 5
Which off the following Interfaces are valid SAP Hybris interceptors ?
1. de.hybris.platform.servicelayer.interceptor.ValidateInterceptor
2. de.hybris.platform.servicelayer.interceptor.PrepareInterceptor
3. de.hybris.platform.servicelayer.interceptor.CheckInterceptor
4. de.hybris.platform.servicelayer.interceptor.InitAllInterceptor
5. de.hybris.platform.servicelayer.interceptor.RemoveInterceptor
6. de.hybris.platform.servicelayer.interceptor.DeleteInterceptor
Solution
Pretest - Question 6
What is the recommended way to create a new extension within SAP Hybris V6
?
1. Use the installer script with the extgen recipe
2. Extensions are automatically created by the build framework based on
your dependencies
3. Use the build framework with the extgen ant target to create a new
extension from a template
4. Use the build framework with the extgen maven goal to create a new
extension from a template
Solution
Pretest - Question 7
What bean would I get when I execute spring.getBean(“alias”)* for the following
spring configuration?*
1 <alias name="bean1" alias="alias"/>
2 <bean name="bean1" class="spring.exos.MyBean" />
3
4 <alias name="bean2" alias="alias"/>
5 <bean name="bean2" class="spring.exos.MyBean" />
1. bean1
2. bean2
3. alias
4. The configuration is wrong
Solution
Pretest - Question 8
Using a standard SAP Hybris configuration, is this a valid item type definition ?
1 <itemtype code="MyItem" abstract="false" extends="GenericItem">
2 </itemtype>
Pretest - Question 9
All CMS item types extend ?
1. GenericItem
2. CMS Item
3. CMSItem or CMSRelation
4. CatalogAware
Solution
Pretest - Question 10
Next Generation Cockpit dynamic forms can be used to ?
1. Automatically generate forms for new item types
2. Automatically open the next tab when required data have been entered
3. Automatically disable a field when data are entered
4. Automatically create an event when data are validated
Solution
Solutions
Pretest - Solution 1
1,4 are correct.
2. The database is never deleted by SAP Hybris even if the configured
database user had ti right to do so.
3. SAP Hybris will delete only tables he knows from its type definition.
Question
Pretest - Solution 2
2 is correct.
Keeping your configuration isolated from SAP Hybris out of the box
configuration is recommenced.
Question
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.
Question
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.
Question
Pretest - Solution 5
1,2,5 are correct.
The available interceptors are :
• PrepareInterceptor
• LoadInterceptor
• RemoveInterceptor
• ValidateInterceptor
• InitDefaultsInterceptor
Question
Pretest - Solution 6
3 is correct.
Installer script and the build framework don’t create any extensions. SAP
Hybris V6 is using ant to generate new extensions, maven can be used to
configure libraries dependencies.
Question
Pretest - Solution 7
2 is correct.
The last configured alias will be used.
Question
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).
Question
Pretest - Solution 9
1,3 are correct.
All item types extend GenericItem type. All CMS item types extend either
CMSItem or CMSRelation.
Question
Pretest - Solution 10
2,3 are correct.
Dynamic forms are used to add logic within a wizard or editor area.
Question
Chapter 2
WCMS
The SAP Hybris Commerce 6.0 Developer expects you to know the Web
Content Management System (WCMS) cockpit, in this chapter readers
will learn the different CMS component hierarchy and items, learn how to
create new CMS component, explore the store and website data model, will
learn how to create a manage warehouse and point of sales, finally you will
learn how to create restriction using the BTG extension.
16
CMSItem CMSRelation
CMSItem types
CMSItem type and CMSRelation type unicity is guaranty with a key made of
catalogVersion and UID.
1 <itemtype code="CMSItem" extends="GenericItem" ...>
2 <attributes>
3 <attribute ... qualifier="catalogVersion">
4 <modifiers ... unique="true"/>
5 </attribute>
6 <attribute ... qualifier="name">
7 </attribute>
8 <attribute ... qualifier="uid">
9 <modifiers ... unique="true" .../>
10 </attribute>
11 </attributes>
12 </itemtype>
13 <itemtype code="CMSRelation" extends="GenericItem" ...>
14 <attributes>
15 <attribute ... qualifier="catalogVersion">
16 <modifiers ... unique="true"/>
17 </attribute>
18 <attribute ... qualifier="uid">
19 <modifiers ... unique="true"/>
20 </attribute>
21 </attributes>
22 </itemtype>
CMS Components
A CMS component is a 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 components are made of three
things :
• an item that extends AbstractCMSComponent or one of its subtypes
• a Spring MVC controller that extends AbstractCMSComponentController
• a JSP (or other front end technology) to render the component
To change how customized item types are rendered within the
WMCS cockpit, you need to create editorArea_myType.xml,
contentEditor_myType.xml and wizardConfig_myType.xml
3 import de.hybris.platform.servicelayer.time.TimeService;
4
5 import java.text.MessageFormat;
6 import java.util.Calendar;
7 import java.util.Date;
8
9 import javax.annotation.Resource;
10 import javax.servlet.http.HttpServletRequest;
11
12 import org.springframework.stereotype.Controller;
13 import org.springframework.ui.Model;
14 import org.springframework.web.bind.annotation.RequestMapping;
15
16 import com.hybhub.core.model.OrderDeliveryTimeLimitComponentModel;
17 import com.hybhub.storefront.controllers.ControllerConstants;
18
19
20 @Controller("OrderDeliveryTimeLimitComponentController")
21 @RequestMapping(value = ControllerConstants.Actions.Cms.
OrderDeliveryTimeLimitComponent)
22 public class OrderDeliveryTimeLimitComponentController
23 extends AbstractAcceleratorCMSComponentController
24 <OrderDeliveryTimeLimitComponentModel>
25 {
26
27 @Resource
28 private TimeService timeService;
29
34 static
35 {
36 DATE_LIMIT = new Calendar.Builder().set(Calendar.HOUR_OF_DAY,
MAX_HOUR_FOR_NEXT_DAY_DELIVERY).set(Calendar.SECOND, 0)
37 .build().getTime();
38 }
39
40 @Override
41 protected void fillModel(final HttpServletRequest request, final
Model model,
42 final OrderDeliveryTimeLimitComponentModel component)
43 {
44 final Calendar cal = new Calendar.Builder().setInstant(
timeService.getCurrentTime()).build();
45 model.addAttribute("nextDayDelivery", (Boolean.valueOf(cal.
get(Calendar.HOUR_OF_DAY) <
MAX_HOUR_FOR_NEXT_DAY_DELIVERY)));
46 model.addAttribute("nextDayDeliveryMessage", MessageFormat.
format(component.getMessage(), DATE_LIMIT));
47 }
48 }
Run ant all, start your server and update your system, then run this (example
based on the electronic store front) :
1 $contentCatalog=electronicsContentCatalog
2 $contentCatalogName=Electronics Content Catalog
3 $contentCV=catalogVersion(CatalogVersion.catalog(Catalog.id[default=
$contentCatalog]),CatalogVersion.version[default=Online])[default
=$contentCatalog:Online]
4
5 INSERT_UPDATE OrderDeliveryTimeLimitComponent;$contentCV[unique=true
];uid[unique=true];name;message[lang=en];&componentRef;
6 ;;orderDeliveryTimeLimitComponent;order Delivery Time Limit Component
;"Order before {0} to receive your order tomorrow.";
orderDeliveryTimeLimitComponent;
7
8 INSERT_UPDATE ContentSlot;$contentCV[unique=true];uid[unique=true];
name;active;cmsComponents(&componentRef)
9 ;;Section1Slot-Homepage;Section1 Slot for Homepage;true;
orderDeliveryTimeLimitComponent
You should now see your new CMS component under your home page.
Personalization
The BTG extension (Behavioral Targeting Group) provides the AP module
(Advanced Personalization), with this module activated you can customize per
customer the CMS items to display or to add. SAP Hybris customer
segmentation groups your customers into multiple subset and activate actions.
Segmentation rules
Segmentation actions
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 contents
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)
Warehouse
Warehouses are part of the order splitting package, each warehouse is linked to
one or more base store, under each warehouse you find stock levels.
Warehouses are used by the stock service and splitting strategies.
Point of services
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 cockpit. 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 backoffice itself.
25
– images, folder for widget’s images
– labels, folder for widget’s localization
– definition.xml, your widget definition
– .css
– .zul
– cockpit-config.xml, default configuration for your widget
– editors or actions, folder for new editors and actions (editors to edit
item types that are not supported by the backoffice and actions to
perfom business)
– images
– labels, your widget localization
– definition.xml, your widget definition
– .css
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 reorganize 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).
During backoffice development activate the following property :
backoffice.cockpitng.hotDeployment.enabled=true to be able to
reload the backoffice application without restarting your server.
Run ant build and click on redeploy from the backoffice admin
perspective.
To create a new backoffice perspective you need to :
1. create a new BackofficeRole group
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.
Create a controller :
1 package com.hybhub.backoffice.widgets;
2
3 import de.hybris.platform.customerreview.enums.
CustomerReviewApprovalType;
4 import de.hybris.platform.customerreview.model.CustomerReviewModel;
5
6 import org.zkoss.zk.ui.Component;
7 import org.zkoss.zk.ui.event.Events;
8 import org.zkoss.zk.ui.select.annotation.WireVariable;
9 import org.zkoss.zul.Button;
10
11 import com.hybhub.services.CustomerReviewSearchService;
12 import com.hybris.cockpitng.annotations.ViewEvent;
13 import com.hybris.cockpitng.search.data.pageable.PageableList;
14 import com.hybris.cockpitng.util.DefaultWidgetController;
15
16
21 @WireVariable
22 private CustomerReviewSearchService customerReviewSearchService;
23
24 @Override
25 public void initialize(final Component comp)
26 {
27 super.initialize(comp);
28 reviews.setLabel(this.getWidgetSettings().getString("name"));
29 }
30
40 }
41
42 }
And a view :
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <widget xmlns="http://www.zkoss.org/2005/zul"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xmlns:h="http://www.w3.org/1999/xhtml"
6 xmlns:w="http://www.zkoss.org/2005/zk/client"
7 xmlns:zk="http://www.zkoss.org/2005/zk"
8 xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.
hybris.com/schema/cockpitng/zul/zul.xsd"
9 height="100%">
10
11 <div height="100%" style="background: #ccc;">
12 <div>
13 <button id="reviews" label="Pending Reviews"/>
14 </div>
15 <widgetchildren slotID="additionalArea" id="additionalArea"
type="tab" width="100%" height="100%"/>
16 </div>
17 </widget>
30
8 [echo] Java platform: Java(TM) SE Runtime
Environment, 1.8.0_60-b27
9 [echo] Java compiler: org.eclipse.jdt.core.
JDTCompilerAdapter
10 [echo] Build target: 1.8
11 [echo] Compilation mode: strict
12 [echo] hybris Platform directory: /Workspace/hybris/hybris
-6.0.0/hybris/bin/platform
13 [echo] hybris Platform version: 6.0.0.0-SNAPSHOT
14 [echo] Ant version: Apache Ant(TM) version 1.9.1
compiled on May 15 2013
15 [echo] Ant memory settings: -Xmx512m -Dfile.encoding=UTF-8
16 [echo] -----
17 .....
18 [echo] -----
19 [echo]
20
21 extgen:
22 [input]
23 [input] Please choose a template for generation.
24 [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)
25 yaddon
26 [input]
27 [input] Please choose the name of your extension. It has to start
with a letter followed by letters and/or numbers.
28 [input] Press [Enter] to use the default value [training]
29 hybhubaddon
30 [input]
31 [input] Please choose the package name of your extension. It has
to fulfill java package name convention.
32 [input] Press [Enter] to use the default value [org.training]
33 com.hybhub.hybhubaddon
34 [echo] Using extension template source: /Workspace/hybris/hybris
-6.0.0/hybris/bin/ext-template/yaddon
35 [mkdir] Created dir: /Workspace/hybris/hybris-6.0.0/hybris/temp/
hybris/extgen
36 [echo] Copying template files from /Workspace/hybris/hybris
-6.0.0/hybris/bin/ext-template/yaddon to /Workspace/hybris/
hybris-6.0.0/hybris/temp/hybris/extgen
37 [copy] Copying 156 files to /Workspace/hybris/hybris-6.0.0/
hybris/temp/hybris/extgen
38 [copy] Copying 156 files to /Workspace/hybris/hybris-6.0.0/
hybris/temp/hybris/extgen_final
39 [mkdir] Created dir: /Workspace/hybris/hybris-6.0.0/hybris/bin/
custom/hybhubaddon/lib
40 [copy] Copying 143 files to /Workspace/hybris/hybris-6.0.0/
hybris/bin/custom/hybhubaddon
41 [echo]
42 [echo]
43 [echo] Next steps:
44 [echo]
45 [echo] 1) Add your extension to your /Workspace/hybris/hybris
-6.0.0/hybris/config/localextensions.xml
46 [echo]
47 [echo] <extension dir="/Workspace/hybris/hybris-6.0.0/
hybris/bin/custom/hybhubaddon"/>
48 [echo]
49 [echo] 2) Please remove all template extensions (again) before
you proceed.
50 [echo]
51 [echo] 3) Make sure the applicationserver is stopped before you
build the extension the first time.
52 [echo]
53 [echo] 4) Perform 'ant' in your hybris/platform directory.
54 [echo]
55 [echo] 5) Restart the applicationserver
56 [echo]
57 [echo]
58
59 BUILD SUCCESSFUL
60 Total time: 29 seconds
In my case my addon’s name is hybhubaddon and the store front extension I’m
using is yacceleratorstorefront so I need to execute :
1 ant addoninstall -Daddonnames="hybhubaddon" -DaddonStorefront.
yacceleratorstorefront="yacceleratorstorefront"
2 .....
3 addoninstall:
4 [echo] Storefront templates found in command line :
yacceleratorstorefront,
5 [delete] Deleting: /Workspace/hybris/hybris-6.0.0/hybris/bin/
platform/null2070331373
6 [echo] AddOn name list: hybhubaddon
7 [echo] ------------------Instaling addon : hybhubaddon
---------------
8 [echo] Generate project.properties file from template /Workspace
/hybris/hybris-6.0.0/hybris/bin/custom/hybhubaddon/project.
properties.template
9 [copy] Copying 1 file to /Workspace/hybris/hybris-6.0.0/hybris/
bin/custom/hybhubaddon
10 [echo] Add additionalWebSpringConfigs line for
storefrontTemplate 'yacceleratorstorefront' and storefronts
'yacceleratorstorefront'
11 [propertyfile] Updating property file: /Workspace/hybris/hybris
-6.0.0/hybris/bin/custom/hybhubaddon/project.properties
12 [echo] Adding addon 'hybhubaddon' to extensioninfo.xml for '
yacceleratorstorefront'
13 [echo] Adding addon 'hybhubaddon' to addons.less for '
yacceleratorstorefront'
14
15 BUILD SUCCESSFUL
16 Total time: 2 seconds
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 :
1 <%@ page trimDirectiveWhitespaces="true"%>
2 <%@ taglib prefix="template" tagdir="/WEB-INF/tags/responsive/
template"%>
3
4 <template:page pageTitle="${pageTitle}">
5 <h1>From Hybhub Addon</h1>
6 </template:page>
3 import de.hybris.platform.addonsupport.controllers.page.
AbstractAddOnPageController;
4 import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
5 import de.hybris.platform.cms2.model.pages.ContentPageModel;
6
7 import org.springframework.stereotype.Controller;
8 import org.springframework.ui.Model;
9 import org.springframework.web.bind.annotation.RequestMapping;
10 import org.springframework.web.bind.annotation.RequestMethod;
11
12
13 @Controller
14 @RequestMapping(value = "/hybhub")
15 public class HybHubAddonPageController extends
AbstractAddOnPageController
16 {
17
18 @RequestMapping(method = RequestMethod.GET)
19 public String hybhub(final Model model) throws
CMSItemNotFoundException
20 {
21 final ContentPageModel page = getContentPageForLabelOrId(null
);
22 storeCmsPageInModel(model, page);
23 setUpMetaDataForContentPage(model, page);
24
25 return "addon:/hybhubaddon/pages/layout/hybhubAddonLayout";
26 }
27 }
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 it, so we could easily deploy this on any other project.
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.
The OCC module contains the following extensions:
• 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 and
are made to be reused as templates, so to add new webservices or
to change existing web services you will need to generate a new
commerce web service extensions from the
ycommercewebservices template.
Currently 2 versions of the web services coexists:
• V1 (/v1/*) which is the old version released with Hybris V5.1. The key
features of version 1 are:
– Stateful
– Response format (XML or JSON)
• 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:
• GET a request to get data
• POST a request to create data
• PUT a request to update data
• HEAD a request to get information about the data (number of elements
for example)
Remember that OCC doesn’t use normal users, it has its own data
type to manage credentials, have a look at OAuthClientDetails
1 <itemtype code="OAuthClientDetails" generate="true" autocreate="true"
>
2 <deployment table="OAuthClientDetails" typecode="6500" />
3
4 <attributes>
5 <attribute qualifier="clientId" type="java.lang.String">
6 <description>Client Id</description>
7 <modifiers unique="true" optional="false" initial="true"
write="false" />
8 <persistence type="property" />
9 </attribute>
10
11 <attribute qualifier="resourceIds" type="StringSet">
12 <description>Set of Resource Id's</description>
13 <persistence type="property" />
14 </attribute>
15
16 <attribute qualifier="clientSecret" type="java.lang.String">
17 <description>Client Secret</description>
18 <persistence type="property" />
19 </attribute>
20
21 <attribute qualifier="scope" type="StringSet">
22 <description>Set of client scopes</description>
23 <persistence type="property" />
24 </attribute>
25
26 <attribute qualifier="authorizedGrantTypes" type="StringSet"
>
27 <description>Set of grant types for client</description>
28 <persistence type="property" />
29 </attribute>
30
31 <attribute qualifier="registeredRedirectUri" type="StringSet
">
32 <description>Set of redirect Uri for client</description>
33 <persistence type="property" />
34 </attribute>
35
36 <attribute qualifier="authorities" type="StringSet">
37 <description>Set of authorities granted to client</
description>
38 <persistence type="property" />
39 </attribute>
40
41 <attribute qualifier="accessTokenValiditySeconds" type="java
.lang.Integer">
42 <description>Set of authorities granted to client</
description>
43 <persistence type="property" />
44 </attribute>
45
46 <attribute qualifier="refreshTokenValiditySeconds" type="
java.lang.Integer">
47 <description>Set of authorities granted to client</
description>
48 <persistence type="property" />
49 </attribute>
50
51 <attribute qualifier="autoApprove" type="StringSet">
52 <description>Set of auto approve scopes of client</
description>
53 <persistence type="property" />
54 </attribute>
55 </attributes>
56
57 <indexes>
58 <index name="clientIdIdx" unique="true">
59 <key attribute="clientId" />
60 </index>
61 </indexes>
62 </itemtype>
Install OCC
To activate and use the Omni Channel Connect module you need to have these
extension activated :
• ycommercewebservices
• ycommercewebserviceshmc
• ycommercewebservicestest
• commercewebservicescommons
• webservicescommonsbackoffice
• cmswebservices
If you have created your own web services extensions from the y
templates, 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 would be able to manage the OAuthClientDetails and see the current
OAuthAccessToken from the backoffice.
OAUTH
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
could import the one provided with the cmswebservices extension inside the
impex file sampledata-oauthclients.impex.
1 INSERT_UPDATE OAuthClientDetails;clientId[unique=true];resourceIds;
scope;authorizedGrantTypes;authorities;clientSecret;
registeredRedirectUri
2 ;client-side;hybris;basic;implicit,client_credentials;ROLE_CLIENT;
secret;http://localhost:9001/authorizationserver/
oauth2_implicit_callback;
3 ;mobile_android;hybris;basic;authorization_code,refresh_token,
password,client_credentials;ROLE_CLIENT;secret;http://localhost
:9001/authorizationserver/oauth2_callback;
4 ;trusted_client;hybris;extended;authorization_code,refresh_token,
password,client_credentials;ROLE_TRUSTED_CLIENT;secret;;
Curl
1 curl -k -X POST https://localhost:9002/authorizationserver/oauth/
token\?client_id\=trusted_client\&client_secret\=secret\&
grant_type\=client_credentials
2 {
3 "access_token" : "16582579-a158-4c31-ad3a-438c9e587dae",
4 "token_type" : "bearer",
5 "scope" : "extended",
6 "expires_in" : 41780
7 }%
Postman
Post Request: https://localhost:9002/authorizationserver/oauth/token?client_
id=trusted_client&client_secret=secret&grant_type=client_credentials
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.
1 <hybrisconfig xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='../bin/platform/resources/schemas/
extensions.xsd'>
2 <extensions>
3 <path dir='${HYBRIS_BIN_DIR}' autoload='false' />
4 ...
5 <extension name="mywebservices"/>
6 ...
7 </extensions>
8 </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 CronJobsController under web/src source folder and
inside the com.hybhub.webservices.v2.controller package :
1 package com.hybhub.webservices.v2.controller;
2
3 import de.hybris.platform.servicelayer.cronjob.CronJobService;
4 import java.util.stream.Collectors;
5 import javax.annotation.Resource;
6 import org.springframework.security.access.annotation.Secured;
7 import org.springframework.stereotype.Controller;
8 import org.springframework.web.bind.annotation.RequestMapping;
9 import org.springframework.web.bind.annotation.RequestMethod;
10 import org.springframework.web.bind.annotation.ResponseBody;
11 import com.hybhub.webservices.dto.cronjob.CronJobListWsDTO;
12
13 @Controller
14 @RequestMapping(value = "/{baseSiteId}/cronjobs")
15 public class CronJobsController extends BaseController
16 {
17 @Resource
18 CronJobService cronJobService;
19
20 @Secured("ROLE_TRUSTED_CLIENT")
21 @RequestMapping(value = "/running", method = RequestMethod.GET)
22 @ResponseBody
23 public CronJobListWsDTO getRunningCronJobCode()
24 {
25 final CronJobListWsDTO cronJobList = new CronJobListWsDTO();
26 cronJobList.setCronJobsCode(
27 cronJobService.getRunningOrRestartedCronJobs().
28 parallelStream().map(c -> c.getCode()).collect(
Collectors.toList()));
29 return cronJobList;
30 }
31 }
Run ant clean all then start your server, check that you have at least one running
cronjob otherwise your list will be empt, then you can call our newly created
webservice :
Then update our controller to be Cacheable, 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 :
1 @Controller
2 @CacheControl(directive = CacheControlDirective.PUBLIC, maxAge = 30)
3 @RequestMapping(value = "/{baseSiteId}/cronjobs")
4 public class CronJobsController extends BaseController
5 ...
6 @Secured("ROLE_TRUSTED_CLIENT")
7 @RequestMapping(value = "/running", method = RequestMethod.GET)
8 @Cacheable(value = "cronjobCache", key = "T(de.hybris.platform.
commercewebservicescommons.cache.CommerceCacheKeyGenerator).
generateKey(false,false,'getRunningCronJobCode')")
9 @ResponseBody
10 public CronJobListWsDTO getRunningCronJobCode()
Now it should take 30 seconds before any changes to cronjobs status appear
when you call our cronjob.
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.orderSplittingService, this service contains a
list of splitting strategy to apply on a given order. A strategy needs to
implement de.hybris.platform.ordersplitting.strategy.SplittingStrategy, the out
of the box strategy are :
• splitByAvailableCount
• splitByDeliveryMode
• splitByPoS
• splitByNamedDeliveryDate
• splitByEntryDeliveryAddress
• splitByWarehouse
To implement a new strategy use
de.hybris.platform.ordersplitting.strategy.AbstractSplittingStrategy,
this abstract class helps by doing most of the work, all you have to
do is to implement getGroupingObject (to select the attribute to
group order entries) and afterSplitting to create consignment.
Promotion
SAP Hybris V6 introduced a major change with the new Promotion Engine
(Running with the new rule engine), unlike the now legacy Promotion Module
which was still using the deprecated Jalo Layer, the new Promotion Engine uses
the services layer and is highly flexible.
For backward compatibility reasons under SAP Hybris V6 both
legacy Promotion Module and new Promotion Engine are available,
all new promotion implementation should be done using the
Promotion Engine
The rule engine is based on Drools
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.
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 :
• Authorization, Authorized amount of money remains locked on card’s
account until it is captured or authorization is reversed (cancelled) or
authorization is expired
• Capture, Capturing an authorization means the authorized amount of
money is actually transferred from the card holder account to the
merchant account. Capture operation requires a previous successful
authorization that has not yet expired
• Partial Capture, Capture only a fragment of the reserved amount
• Void, cancel an on going authorization
• 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.
SAP Hybris can have multiple PSP configured at the same time, it’s
up to the checkout flow to gibe the customer the option to choose the
final PSP
Internationalization
SAP Hybris supports out of the box :
• Languages (localizations of business objects)
• Countries and Regions (tax regulations)
• Currencies (currency formats, rounding)
• Time Zones (online / offline dates, order dates)
• Number Formats (separation characters)
• Language fallbacks
• Tenant-specific settings
• Localized API for the service layer
• Compatible UI to manage localized attributes
The following services to work with internationalization and localization are
available :
• de.hybris.platform.servicelayer.i18n.I18NService, service to work with
Java internationalization objects(Locale, Currency, TimeZone)
• de.hybris.platform.servicelayer.i18n.CommonI18NService, service to work
with SAP Hybris localization objects (LanguageModel, CurrencyModel,
CountryModel, RegionModel), those items can be used to create a Java
Locale object
• de.hybris.platform.servicelayer.i18n.L10NService, provides methods
localized resources bundles
•
de.hybris.platform.commerceservices.i18n.CommerceCommonI18NService,
provides localization objects for the current base site
internationalization is making your software compatible with
different currencies, countries…. localization is providing the
appropriate resources for a specific language
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 :
The dispatcherServlet (org.springframework.web.servlet.DispatcherServlet )is
responsible of handling 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 changing from your configuration (they
are intentionally empty):
1 hybhubstorefront.webroot=
2 storefrontContextRoot=
Request filters
3 import java.io.IOException;
4
5 import javax.servlet.FilterChain;
6 import javax.servlet.ServletException;
7 import javax.servlet.ServletRequest;
8 import javax.servlet.ServletResponse;
9 import javax.servlet.http.HttpServletRequest;
10
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.web.filter.GenericFilterBean;
14
20 @Override
21 public void doFilter(final ServletRequest paramServletRequest,
final ServletResponse paramServletResponse,
22 final FilterChain paramFilterChain) throws IOException,
ServletException
23 {
24 final HttpServletRequest httpRequest = (HttpServletRequest)
paramServletRequest;
25
29 paramFilterChain.doFilter(paramServletRequest,
paramServletResponse);
30 }
31
32 }
The order you place your filter matters as they are executed in the
list order!
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 :
1. an inbound channel detects a new file matching a pattern (file:inbound-
channel-adapter)
2. an outbound channel moves the file to a new folder (file:outbound-gateway)
3. activators setup the headers (int:service-activator)
4. resolve the mapping between the file name and the type to import
5. generate the impex
6. run the impex
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.
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
SAP Hybris gives you the ability to extend the existing model definition, this
way you can completely customize the SAP Hybris platform with your own
types, your own attributes for existing types and your own relations between
types.
All types definition are done using XML item files, from extensions with a core
module :
1 <coremodule generated="true"
2 manager="de.hybris.platform.jalo.extension.GenericManager"
packageroot="com.hybhub.myextension"/>
• 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 :
1 <maptype code="localized:java.lang.String"
2 argumenttype="Language"
3 returntype="java.lang.String"
4 autocreate="true"
5 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 :
1 <relation code="Country2RegionRelation" generate="true" localized="
false" autocreate="true">
2 <sourceElement type="Country" qualifier="country" cardinality="
one">
3 <modifiers read="true" write="true" search="true" optional="
false" unique="true"/>
4 </sourceElement>
5 <targetElement type="Region" qualifier="regions" cardinality="
many">
6 <modifiers read="true" write="true" search="true" partof="
true"/>
7 </targetElement>
8 </relation>
• 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, following
is an example extracted from core-items.xml :
1 <itemtype code="Title"
2 extends="GenericItem"
3 jaloclass="de.hybris.platform.jalo.user.Title"
4 autocreate="true"
5 generate="true">
6 <!-- deployment="de.hybris.platform.persistence.user.Title" -->
7 <deployment table="Titles" typecode="24"/>
8 <attributes>
9 <attribute autocreate="true" qualifier="code" type="java.lang
.String">
10 <persistence type="property"/>
11 <modifiers read="true" write="true" search="true" initial
="true" optional="false" unique="true"/>
12 <custom-properties>
13 <property name="hmcIndexField">
14 <value>"thefield"</value>
15 </property>
16 </custom-properties>
17 </attribute>
18 <attribute autocreate="true" qualifier="name" type="localized
:java.lang.String">
19 <modifiers read="true" write="true" search="true"
optional="true"/>
20 <persistence type="property"/>
21 <custom-properties>
22 <property name="hmcIndexField">
23 <value>"thefield"</value>
24 </property>
25 </custom-properties>
26 </attribute>
27 </attributes>
28
29 <indexes>
30 <index name="codeIdx">
31 <key attribute="code"/>
32 </index>
33 </indexes>
34 </itemtype>
Our main objective here is to model a blog as we want to add the ability for our
employees to blog about new products and the company :
We have posts, they represent the content of each blog entry, each post is linked
to a blog linked to one or more CMSSites, each posts can have comments linked
to users.
First we need enum types : * for post status (draft, published, deleted) * for
comment status (pending, approved, blocked)
1 <enumtypes>
2 <enumtype code="PostStatus">
3 <value code="DRAFT"/>
4 <value code="PUBLISHED"/>
5 <value code="DELETED"/>
6 </enumtype>
7 <enumtype code="CommentStatus">
8 <value code="PENDING"/>
9 <value code="APPROVED"/>
10 <value code="BLOCKED"/>
11 </enumtype>
12 </enumtypes>
1 <itemtypes>
2 <itemtype code="Blog" extends="GenericItem" autocreate="true"
generate="true">
3 <deployment table="blog" typecode="11001" />
4 <attributes>
5 <attribute qualifier="code" type="java.lang.String">
6 <modifiers initial="true" read="true" write="false"
optional="false" unique="true" />
7 <persistence type="property" />
8 </attribute>
9 <attribute qualifier="active" type="boolean">
10 <persistence type="property" />
11 </attribute>
12 </attributes>
13 </itemtype>
14
15 <itemtype code="Post" extends="GenericItem" autocreate="true"
generate="true">
16 <deployment table="post" typecode="11002" />
17 <attributes>
18 <attribute qualifier="blog" type="Blog">
19 <persistence type="property"/>
20 </attribute>
21 <attribute qualifier="date" type="java.util.Date">
22 <modifiers optional="false"/>
23 <persistence type="property" />
24 </attribute>
25 <attribute qualifier="author" type="Employee">
26 <modifiers optional="false"/>
27 <persistence type="property" />
28 </attribute>
29 <attribute qualifier="title" type="localized:java.lang.
String">
30 <persistence type="property" />
31 </attribute>
32 <attribute qualifier="content" type="localized:java.lang.
String">
33 <persistence type="property">
34 <columntype>
35 <value>HYBRIS.LONG_STRING</value>
36 </columntype>
37 </persistence>
38 <modifiers search="false"/>
39 </attribute>
40 <attribute qualifier="keywords" type="StringCollection">
41 <persistence type="property" />
42 </attribute>
43 <attribute qualifier="status" type="PostStatus">
44 <persistence type="property" />
45 <defaultvalue>em().getEnumerationValue("PostStatus",
"DRAFT")</defaultvalue>
46 </attribute>
47 </attributes>
48 </itemtype>
49
50 <itemtype code="PostComment" extends="GenericItem" autocreate="
true" generate="true">
51 <deployment table="postcomment" typecode="11003" />
52 <attributes>
53 <attribute qualifier="author" type="User">
54 <persistence type="property"/>
55 </attribute>
56 <attribute qualifier="content" type="java.lang.String">
57 <persistence type="property">
58 <columntype>
59 <value>HYBRIS.LONG_STRING</value>
60 </columntype>
61 </persistence>
62 <modifiers search="false" optional="false"/>
63 </attribute>
64 <attribute qualifier="status" type="CommentStatus">
65 <persistence type="property" />
66 </attribute>
67 </attributes>
68 </itemtype>
69 </itemtypes>
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 than 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):
We can see that all newly defined items are available in our current system.
1 INSERT_UPDATE Blog;code[unique=true];active[default=true]
2 ;myBlog;
3
4 INSERT_UPDATE Post;date[unique=true][dateformat=dd-MM-yyyy];Blog(code
);author(uid)
5 ;01-01-2016;myBlog;admin
6
7 INSERT_UPDATE PostComment;content[unique=true];author(uid);status(
code);
8 ;This is the content;admin;PENDING
SAP Hybris not only gives you the ability to create new types, but also gives
you the ability to extend the core item types (User, Product,…) without
changing any of the core extensions so you would be able to update SAP
Hybris without breaking anything. This is one of the greatest feature of SAP
Hybris the possibility of building your e-commerce platform not from SAP
Hybris but on top of the existing code.
Let’s do two examples of how we can extend existing item types :
• Users will have a birthday attribute
• Products will have a boolean to activate or not an export to Google
Shopping
1 <itemtype code="Product" autocreate="false" generate="false">
2 <attributes>
3 <attribute qualifier="exportToGoogleShopping" type="java.lang
.Boolean">
4 <persistence type="property"/>
5 </attribute>
6 </attributes>
7 </itemtype>
8
9 <itemtype code="Customer" autocreate="false" generate="false">
10 <attributes>
11 <attribute qualifier="birthday" type="java.util.Date">
12 <persistence type="property"/>
13 </attribute>
14 </attributes>
15 </itemtype>
Update your system and check from the backoffice that new attributes have
been added to your types :
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 :
1 <attribute autocreate="true" qualifier="name" type="localized:java.
lang.String">
2 <modifiers read="true" write="true" search="true" optional="true"
/>
3 <persistence type="property"/>
4 <custom-properties>
5 <property name="hmcIndexField">
6 <value>"thefield"</value>
7 </property>
8 </custom-properties>
9 </attribute>
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 :
1 MariaDB [database]> explain productslp;
2 +-----+--------------+------+-----+---------+-------+
3 | Field | Type | Null | Key | Default
| Extra |
4 +-----+--------------+------+-----+---------+-------+
5 | ITEMPK | bigint(20) | NO | PRI | 0
| |
6 | ITEMTYPEPK | bigint(20) | YES | | NULL
| |
7 | LANGPK | bigint(20) | NO | PRI | 0
| |
8 | p_name | varchar(255) | YES | | NULL
| |
9 | p_description | text | YES | | NULL
| |
10 | p_manufacturertypedescription | varchar(255) | YES | | NULL
| |
11 | p_segment | varchar(255) | YES | | NULL
| |
12 | p_articlestatus | longblob | YES | | NULL
| |
13 | p_summary | text | YES | | NULL
| |
14 | p_directionofuse | text | YES | | NULL
| |
15 | p_specialpricedescription | text | YES | | NULL
| |
16 | p_style | varchar(255) | YES | | NULL
| |
17 | p_size | varchar(255) | YES | | NULL
| |
18 | p_color | varchar(255) | YES | | NULL
| |
19 +-----+--------------+------+-----+---------+-------+
20 14 rows in set (0.01 sec)
Each localized attribute of an item are grouped in this table and linked to a
language through LANGPK.
The model service will create getters and setters like this :
1 /**
2 * <i>Generated method</i> - Getter of the <code>Product.description
</code> attribute defined at extension <code>core</code>.
3 * @return the description
4 */
5 @Accessor(qualifier = "description", type = Accessor.Type.GETTER)
6 public String getDescription()
7 {
8 return getDescription(null);
9 }
10 /**
11 * <i>Generated method</i> - Getter of the <code>Product.description
</code> attribute defined at extension <code>core</code>.
12 * @param loc the value localization key
13 * @return the description
14 * @throws IllegalArgumentException if localization key cannot be
mapped to data language
15 */
16 @Accessor(qualifier = "description", type = Accessor.Type.GETTER)
17 public String getDescription(final Locale loc)
18 {
19 return getPersistenceContext().getLocalizedValue(DESCRIPTION, loc
);
20 }
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).
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:
1 <enumtype code="OrderStatus" autocreate="true" generate="true"
dynamic="true">
2 <value code="CREATED"/>
3 <value code="ON_VALIDATION"/>
4 <value code="COMPLETED"/>
5 <value code="CANCELLED"/>
6 </enumtype>
You can add new values from a different extension if needed, for example the
OrderStatus enumeration is defined within the core extension, from my extension
hybhubaddon I’m adding a new value :
1 <enumtype code="OrderStatus" autocreate="false" generate="false"
dynamic="true">
2 <value code="MYSTATUS"/>
3 </enumtype>
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) :
1 import de.hybris.platform.enumeration.EnumerationService;
2 import de.hybris.platform.core.enums.OrderStatus;
3
4 EnumerationService es = spring.getBean("enumerationService");
5 OrderStatus os = es.getEnumerationValue("ORDERSTATUS", "MYSTATUS");
6 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:
• Format data like addresses or names
• Create a calculated field
• Combine multiple non dynamic attributes
Don’t use a dynamic attribute to:
• Integrate your model with any external systems or database
• Trigger any intensive operation, it would slow down the platform as getters
and setters are frequently called by the cache mechanism
• Implement your own SQL query
11 @Override
12 public String get(final PostCommentModel postComment)
13 {
14 final StringBuilder sb = new StringBuilder(postComment.
getStatus().getCode());
15 sb.append(SEP);
16 sb.append(postComment.getAuthor().getDisplayName());
17 sb.append(SEP);
18 sb.append(postComment.getContent().length() > MAX_CONTENT ?
postComment.getContent().substring(0, MAX_CONTENT)
19 : postComment.getContent());
20
21 return sb.toString();
22 }
23
24 @Override
25 public void set(final PostCommentModel postComment, final String
str)
26 {
27 throw new IllegalAccessError("Cannot set that attribute [
Summary]");
28 }
29
30 }
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/ :
1 import com.hybhub.hybhubaddon.model.PostCommentModel
2 import de.hybris.platform.servicelayer.model.ModelService
3 import de.hybris.platform.servicelayer.search.FlexibleSearchService
4 import java.util.List
5 import de.hybris.platform.servicelayer.user.UserService
6
7 UserService us = spring.getBean("userService")
8 ModelService ms = spring.getBean("modelService")
9 FlexibleSearchService fss = spring.getBean("flexibleSearchService")
10
If you open the output tab you should see : PENDING - Administrator - This
is the content of the PostComment
Indices & Deployment
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 need 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 in file: 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:
1 <itemtype code="Blog" extends="GenericItem" autocreate="true"
generate="true">
2 <deployment table="blog" typecode="11001" />
3 ...
4 </itemtype>
Indices
SAP Hybris gives you the ability to add database indices on item types, indices
have a name and one or more key (composite indices), here is an example of an
index on the blog type:
1 <indexes>
2 <index name="blogIDX" unique="true">
3 <key attribute="code" lower="true"/>
4 <key attribute="active"/>
5 </index>
6 </indexes>
SAP Hybris will run the following SQL command (may vary upon the targeted
database, here we use HSQL):
1 CREATE UNIQUE INDEX blogIDX_11001 ON BLOG (P_CODE, P_ACTIVE);
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 :
1 <database-schema database="mysql" primary-key="primary key" null=""
not-null="not null" >
2 <type-mapping type="java.lang.String" persistence-type="varchar
(255)" />
3 <type-mapping type="String" persistence-type="varchar(255)" />
4
5 <type-mapping type="java.lang.Float" persistence-type="float
(20,5)" />
6 <type-mapping type="java.lang.Double" persistence-type="double" /
>
7 <type-mapping type="java.lang.Byte" persistence-type="smallint" /
>
8 <type-mapping type="java.lang.Character" persistence-type="
smallint" />
9 <type-mapping type="java.lang.Short" persistence-type="integer" /
>
10 <type-mapping type="java.lang.Boolean" persistence-type="tinyint
(1)" />
11 <type-mapping type="java.lang.Long" persistence-type="bigint" />
12 <type-mapping type="java.lang.Integer" persistence-type="integer"
/>
13
14 <type-mapping type="float" persistence-type="float(20,5) DEFAULT
0" />
15 <type-mapping type="double" persistence-type="double DEFAULT 0" /
>
16 <type-mapping type="byte" persistence-type="smallint DEFAULT 0" /
>
17 <type-mapping type="char" persistence-type="smallint DEFAULT 0" /
>
18 <type-mapping type="short" persistence-type="integer DEFAULT 0" /
>
19 <type-mapping type="boolean" persistence-type="tinyint(1) DEFAULT
0" />
20 <type-mapping type="long" persistence-type="bigint DEFAULT 0" />
21 <type-mapping type="int" persistence-type="integer DEFAULT 0" />
22
23 <type-mapping type="java.util.Date" persistence-type="datetime" /
>
24 <type-mapping type="java.math.BigDecimal" persistence-type="
DECIMAL(30,8)" />
25 <type-mapping type="java.io.Serializable" persistence-type="
LONGBLOB" />
26
27 <type-mapping type="HYBRIS.LONG_STRING" persistence-type="TEXT" /
>
28 <type-mapping type="HYBRIS.COMMA_SEPARATED_PKS" persistence-type=
"TEXT" />
29 <type-mapping type="HYBRIS.PK" persistence-type="BIGINT" />
30 </database-schema>
To see what commands SAP Hybris uses to creates your item types you can use
the dry-run functionality (Dry Run), for example for our Post type on HSQL
SAP Hybris will execute :
1 CREATE CACHED TABLE post
2 (
3 hjmpTS BIGINT,
4 createdTS TIMESTAMP,
5 modifiedTS TIMESTAMP,
6 TypePkString BIGINT,
7 OwnerPkString BIGINT,
8 PK BIGINT NOT NULL,
9 p_blog BIGINT,
10 p_date TIMESTAMP,
11 p_author BIGINT,
12 p_keywords LONGVARBINARY,
13 p_status BIGINT,
14 aCLTS BIGINT DEFAULT 0,
15 propTS BIGINT DEFAULT 0,
16 PRIMARY KEY (PK)
17 );
18 CREATE CACHED TABLE postlp
19 (
20 ITEMPK BIGINT,
21 ITEMTYPEPK BIGINT,
22 LANGPK BIGINT,
23 p_title NVARCHAR(255),
24 p_content LONGVARCHAR,
25 PRIMARY KEY (ITEMPK, LANGPK)
26 );
FSQL or flexible search query language helps you looking for items and types
using a SQL-like syntax. Why SAP Hybris is doing this? SAP Hybris is
compatible with Various Databases (HSQL, Mysql, Oracle and Microsoft SQL
Server) but each of them implements a different SQL version, SAP Hybris
needed to have a database abstraction layer, allowing you to write a FSQL
query that would run on any compatible databases (SAP Hana, Mysql, SQL
Server, HSQL, Postgres). It abstracts from you details such as column and
table names and it is translated into native SQL statements on execution.
allowing nearly every aspect of SQL SELECT statements (but no data
manipulation is possible, update or delete are not available).
Flexible Search Queries are only for search, they cannot do any SQL
DML or SQL DDL queries
Flexible Search Queries are executed on the database trough a SQL
query, therefore it is not possible to flexible search queries on Jalo or
dynamic attributes
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:
1 query_cache_size=0
Restrictions
Restrictions are manageable from the SearchRestrictionService:
1 package de.hybris.platform.search.restriction;
2
3 import de.hybris.platform.core.model.security.PrincipalModel;
4 import de.hybris.platform.core.model.type.ComposedTypeModel;
5 import de.hybris.platform.core.model.type.SearchRestrictionModel;
6 import de.hybris.platform.search.restriction.session.
SessionSearchRestriction;
7 import java.util.Collection;
8
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:
1 INSERT_UPDATE SearchRestriction;code[unique=true];name[lang=en];query
;principal(UID);restrictedType(code);active;generate
2 ;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):
1 select {name} from {Language}
SAP Hybris will execute this SQL query (*pay attention to the WHERE clause
where our restriction is added):
1 SELECT lp_t0.p_name FROM languages item_t0 JOIN languageslp lp_t0
2 ON item_t0.PK = lp_t0.ITEMPK AND lp_t0.LANGPK =?
3 WHERE (item_t0.TypePkString=? AND ( item_t0.p_active = true))
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:
1 SELECT <selects> FROM <types> ( WHERE <conditions> )? ( ORDER BY <
order> )?
• 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
• 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 :
1 SELECT {p:PK}
2 FROM {Product AS p}
3 WHERE {p:description[en]:o} LIKE '%text%'
4 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
1 select * from {User}
You can test all flexible search queries directly from the HAC
3 import de.hybris.platform.core.model.ItemModel;
4 import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
5 import de.hybris.platform.servicelayer.search.RelationQuery;
6 import de.hybris.platform.servicelayer.search.SearchResult;
7 import de.hybris.platform.servicelayer.search.TranslationResult;
8 import java.util.List;
9 import java.util.Map;
10
11
14 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.
1 <enumtypes>
2 <enumtype code="ScreenSize">
3 <value code="THIRTEEN" />
4 <value code="FOURTEEN" />
5 <value code="FIFTEEN" />
6 </enumtype>
7 </enumtypes>
8
9 <itemtypes>
10 <itemtype code="Laptop" extends="Product" autocreate="true"
generate="true">
11 <attributes>
12 <attribute qualifier="ScreenSize" type="ScreenSize">
13 <persistence type="property" />
14 </attribute>
15 </attributes>
16 </itemtype>
17
18 <itemtype code="LaptopVariant" extends="VariantProduct"
autocreate="true" generate="true"
19 jaloclass="com.hybhub.jalo.Car">
20 <attributes>
21 <attribute qualifier="diskCapacity" type="int" metatype="
VariantAttributeDescriptor">
22 <persistence type="property"/>
23 </attribute>
24 </attributes>
25 </itemtype>
26 </itemtypes>
This is a bad idea, since it is described on the variant level, you need to define
a screen size for all your variants, even if they all have the same.
Why not defining the screen size directly on the product type ? well it’s also a
bad design since you might have products that are not laptops !
Diagram showing what the problem with product variant is:
Category Variants
A different approach is to build category variants with specific attributes. For
example our laptop category has a screen size attribute:
1 <itemtype code="LaptopCategory" extends="VariantValueCategory">
2 <attributes>
3 <attribute qualifier="ScreenSize" type="ScreenSize">
4 <persistence type="property" />
5 </attribute>
6 </attributes>
7 </itemtype>
8
9 <itemtype code="LaptopVariant" extends="VariantProduct" autocreate="
true" generate="true">
10 <attributes>
11 <attribute qualifier="diskCapacity" type="int" metatype="
VariantAttributeDescriptor">
12 <persistence type="property"/>
13 </attribute>
14 </attributes>
15 </itemtype>
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 give 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…
The difference is that categorization is vertical while classification is horizontal.
For example to classify our laptop :
1 $productCatalog=electronicsProductCatalog
2 $productCatalogName=Electronics Product Catalog
3 $catalogVersion=catalogversion(catalog(id[default=$productCatalog]),
version[default='Staged'])[unique=true,default=$productCatalog:
Staged]
4 $classCatalogVersion=catalogversion(catalog(id[default='
ElectronicsClassification']),version[default='1.0'])[unique=true,
default='ElectronicsClassification:1.0']
5 $classSystemVersion=systemVersion(catalog(id[default='
ElectronicsClassification']),version[default='1.0'])[unique=true]
6 $class=classificationClass(ClassificationClass.code,
$classCatalogVersion)[unique=true]
7 $supercategories=supercategories(code, $catalogVersion)
8 $supercategoriesRel=source(code, $classCatalogVersion)[unique=true]
9 $categories=target(code, $catalogVersion)[unique=true]
10 $attribute=classificationAttribute(code,$classSystemVersion)[unique=
true]
11 $unit=unit(code,$classSystemVersion)
12 $approved=approvalstatus(code)[default='check']
13 $baseProduct=baseProduct(code,$catalogVersion)
14 $clAttrModifiers=system='ElectronicsClassification',version='1.0',
translator=de.hybris.platform.catalog.jalo.classification.impex.
ClassificationAttributeTranslator,lang=en
15
16 # Insert Classifications
17 INSERT_UPDATE ClassificationClass;$classCatalogVersion;code[unique=
true];name[lang=en];allowedPrincipals(uid)[default='customergroup
']
18 ;;2002;Laptop
19
20 # Insert Classification Attributes
21 INSERT_UPDATE ClassificationAttribute;$classSystemVersion;code[unique
=true];name[lang=en]
22 ;;screen size;Screen Size
23
24 INSERT_UPDATE ClassAttributeAssignment;$class;$attribute;position;
$unit;attributeType(code[default=string]);multiValued[default=
false];range[default=false];localized[default=false]
25 ;2002;screen size;1;16;number;false;false
26
27 INSERT_UPDATE CategoryCategoryRelation;$categories;
$supercategoriesRel
28 ;1;2002
29
30 $feature1=@screen size[$clAttrModifiers];
31 INSERT_UPDATE Product;code[unique=true];$supercategories;
manufacturerName;manufacturerAID;unit(code);variantType(code);
$feature1;$catalogVersion;$approved
32 ;000010;1;Apple;MBP-13;pieces;LaptopVariant;13
33 ;000011;1;Apple;MBP-15;pieces;LaptopVariant;15
34
35 INSERT_UPDATE LaptopVariant;code[unique=true];$baseProduct;unit(code)
;diskCapacity;approvalstatus(code)[default='approved'];
$catalogVersion
36 ;000100_256;000010;pieces;256;
37 ;000100_512;000010;pieces;512;
38 ;000101_256;000011;pieces;256;
39 ;000101_512;000011;pieces;512;
The same product could be classified from two different classification tree ! It
offers a lot of flexibility and it can be modified without changing the SAP Hybris
model type !
Chapter 5
Order management
Through this chapter you will learn how to work with orders within an SAP
Hybris e-commerce system.
Business process
SAP Hybris has out of the box a process engine (yacceleratorfulfilmentprocess
extension). Business processes help you to define a list of actions that depend on
each other, and terminate with a status that will decide the action that would
follow. For example the first steps of the order-process.xml business process :
88
Let’s create our own business process, we won’t do anything just having few
actions, first we need to define our business process :
1 <itemtype code="MyProcess" autocreate="true" generate="true" extends=
"BusinessProcess">
2 <attributes>
3 <attribute qualifier="fail" type="boolean">
4 <persistence type="property" />
5 </attribute>
6 <attribute qualifier="error" type="boolean">
7 <persistence type="property" />
8 </attribute>
9 </attributes>
10 </itemtype>
You know need to define your process, create a new file named
myprocess-process.xml under /resources/hybhubaddon/process/, my extension
is hybhubaddon :
1 <?xml version="1.0" encoding="utf-8"?>
2 <process xmlns="http://www.hybris.de/xsd/processdefinition" start="
firstStep" name="myProcess" processClass="com.hybhub.hybhubaddon.
model.MyProcessModel">
3
4 <action id="firstStep" bean="firstStepAction">
5 <transition name="OK" to="secondStep"/>
6 <transition name="NOK" to="abortStep"/>
7 </action>
8
9 <action id="secondStep" bean="secondStepAction">
10 <transition name="OK" to="success"/>
11 <transition name="NOK" to="error"/>
12 </action>
13
14 <action id="abortStep" bean="abortStepAction">
15 <transition name="OK" to="failed"/>
16 </action>
17
18 <end id="error" state="ERROR">All went wrong.</end>
19 <end id="failed" state="FAILED">Couldn't run the process.</end>
20 <end id="success" state="SUCCEEDED">All good.</end>
21
22 </process>
3 import de.hybris.platform.processengine.action.
AbstractSimpleDecisionAction;
4 import de.hybris.platform.task.RetryLaterException;
5
6 import com.hybhub.hybhubaddon.model.MyProcessModel;
7
19 return Transition.OK;
20 }
21 }
Second step, will return success or error based on the error flag
1 package com.hybhub.hybhubaddon.actions.myprocess;
2
3 import de.hybris.platform.processengine.action.
AbstractSimpleDecisionAction;
4 import de.hybris.platform.task.RetryLaterException;
5
6 import com.hybhub.hybhubaddon.model.MyProcessModel;
7
3 import de.hybris.platform.processengine.action.
AbstractSimpleDecisionAction;
4 import de.hybris.platform.task.RetryLaterException;
5
6 import org.apache.log4j.Logger;
7
8 import com.hybhub.hybhubaddon.model.MyProcessModel;
9
10
15 @Override
16 public Transition executeAction(final MyProcessModel myProcess)
throws RetryLaterException, Exception
17 {
18 LOG.error("The process " + myProcess.getCode() + " failed !")
;
19 return Transition.OK;
20 }
21 }
13 modelService.save(myprocess)
14 bpService.startProcess(myprocess)
15
16 modelService.refresh(myprocess)
17 println myprocess.state
You can play around with the two flags and check the result on the HMC, you
can see the process state, and the log for each steps.
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 :
1. Check order, verify required data
2. Check authorize payment, check that the current order has a payment info
attached
3. Reserve amount, change the status of the order to
PAYMENT_AMOUNT_RESERVED
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 check by a
customer agent
9. Order manual checked, take the decision to follow or not the fulfillment
process after the manual check
10. Schedule for cleanUp, try to cleanup a fraudulent or failed order
11. Cancel order
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
you can find the order fulfillment process under
/yacceleratorfulfilmentprocess/resources/yacceleratorfulfilmentprocess/process/order-
process.xml
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 let you validate
on enter and on exit the step controller, here is our implementation for the
hybhub step:
1 package com.hybhub.storefront.checkout.steps.validation.impl;
2
3 import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps
.validation.AbstractCheckoutStepValidator;
4 import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps
.validation.ValidationResults;
5 import de.hybris.platform.commercefacades.order.data.CartData;
6
7 import org.apache.log4j.Logger;
8 import org.springframework.web.servlet.mvc.support.RedirectAttributes
;
9
10
16 @Override
17 public ValidationResults validateOnEnter(final RedirectAttributes
redirectAttributes)
18 {
19 final CartData cartData = getCheckoutFacade().getCheckoutCart
();
20 LOG.info("Validating on enter with Hybhub Validator cart : "
+ cartData.getCode());
21 return ValidationResults.SUCCESS;
22 }
23
24 @Override
25 public ValidationResults validateOnExit()
26 {
27 final CartData cartData = getCheckoutFacade().getCheckoutCart
();
28 LOG.info("Validating on exit with Hybhub Validator cart : " +
cartData.getCode());
29 return ValidationResults.SUCCESS;
30 }
31 }
3 import de.hybris.platform.acceleratorstorefrontcommons.annotations.
PreValidateCheckoutStep;
4 import de.hybris.platform.acceleratorstorefrontcommons.annotations.
RequireHardLogIn;
5 import de.hybris.platform.acceleratorstorefrontcommons.checkout.steps
.CheckoutStep;
6 import de.hybris.platform.acceleratorstorefrontcommons.constants.
WebConstants;
7 import de.hybris.platform.acceleratorstorefrontcommons.controllers.
pages.checkout.steps.AbstractCheckoutStepController;
8 import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
9
10 import org.springframework.stereotype.Controller;
11 import org.springframework.ui.Model;
12 import org.springframework.web.bind.annotation.RequestMapping;
13 import org.springframework.web.bind.annotation.RequestMethod;
14 import org.springframework.web.servlet.mvc.support.RedirectAttributes
;
15
16
17 @Controller
18 @RequestMapping(value = "/checkout/multi/hybhub")
19 public class HybhubStepController extends
AbstractCheckoutStepController
20 {
21 private static final String HYBHUB = "hybhub";
22
23 @RequestMapping(method = RequestMethod.GET)
24 @RequireHardLogIn
25 @Override
26 @PreValidateCheckoutStep(checkoutStep = HYBHUB)
27 public String enterStep(final Model model, final
RedirectAttributes redirectAttributes) throws
CMSItemNotFoundException
28 {
29
30 this.prepareDataForPage(model);
31 storeCmsPageInModel(model, getContentPageForLabelOrId(HYBHUB)
);
32 setUpMetaDataForContentPage(model, getContentPageForLabelOrId
(HYBHUB));
33 model.addAttribute(WebConstants.BREADCRUMBS_KEY,
34 getResourceBreadcrumbBuilder().getBreadcrumbs("
checkout.multi.deliveryMethod.breadcrumb"));
35 model.addAttribute("metaRobots", "noindex,nofollow");
36 setCheckoutStepLinksForModel(model, getCheckoutStep());
37
38 return "pages/checkout/multi/hybhubPage";
39 }
40
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
that 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 localextensions.xml file :
1 <extension name="assistedservicefacades"/>
2 <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 :
1 ant addoninstall -Daddonnames="assistedservicestorefront" -
DaddonStorefront.yacceleratorstorefront="hybhubstorefront"
Now start your server and run a system update (with assistedservicefacades
and assistedservicestorefront 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 :
http://localhost:9001/hybhubstorefront/?site=electronics&asm=true.
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
• Support a customer during add to cart and checkout flow processes
• Help a customer to manage his/her account
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 : http://localhost:9001/cscockpit/.
It is meant to be used by operators in a call center environment for customer,
pre-sales and post sales operations.
You need to remember that from the customer service cockpit operators can :
• Manage customers (create or edit)
• Manage orders in behalf of a customer (create, cancel, update, refund,
return)
• Manage a customer’s cart
• 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
Chapter 6
SAP Hybris provides a fast and customizable search and navigation with the
help of a Apache SOLR server (More information).
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 define 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 consider a
connection attempt a failure
– Socket timeout, timeout before SAP Hybris consider a socket access
a failure
– Total connections, total open connection 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
• one or more SolrEndpointUrl
107
– A url to access Apache solr (for example : http://solr.local:8983)
– A boolean to flag the node as a master
• A SolrIndexConfig, which defines the way SAP Hybris will index
documents within Apache SOLR
– Batch size, how many products SAP Hybris will index at the same
time, this configuration can have a lot of impact on the performances
– Number of threads, number of threads within SAP Hybris to handle
the indexing process
– Indexer mode, DIRECT means SAP Hybris will execute operation
on the running SOLR Index this means that the search result would
be inconsistent during the indexing operation this mode should be
used only during development, the TWO_PHASE mode will create
a new index where SAP Hybris will inject the new indexing result,
once the operation is done SAP Hybris will switch the active index
to be the one newly created
– Commit mode, Apache SOLR data are not reachable until you
commit them, there are different commit modes, never, after_index,
after_batch, and mixed
– Optimize mode, Apache SOLR can optimize its index by
defragmenting it, this operation could be resource expensive, you
can configure when it would be executed, never, after an index
operation or after a full index operation
– Errors 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
– Composed type, the type of item to index
– A list of properties to index (More : Solr Indexed Property)
– A list of indexed queries (More : Solr Indexed Query)
– The default property value provider
– Model fields value provider
– Result converter
Solr Indexed Property
A Solr indexed type defines a list of properties from an item type that need to
be indexed, each of those properties are defined with :
• A name, this name will be used under the Solr index
• A type, the type of the attribute under the Solr index
• A sortable type
• A localized flag
• A currency flag
• A multi-value flag
• A used for spell checking flag
• A include in response flag
• A range and range sets
• A property value provider
• Value provider parameter(s)
• Category field flag
• Free text settings
• Facet settings
• Boost rules
Example, with the following customized product model :
1 <itemtype code="Product" autocreate="false" generate="false">
2 <attributes>
3 <attribute qualifier="exportToGoogleShopping" type="java.lang
.Boolean">
4 <persistence type="property" />
5 </attribute>
6 <attribute qualifier="lastCustomerReview" type="java.lang.
String">
7 <persistence type="property" />
8 </attribute>
9 </attributes>
10 </itemtype>
We will create 2 new properties for our product index, one facet property from
the exportToGoogleShopping and one free text search property from
lastCustomerReview :
exportToGoogleShopping facet :
1 INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=
true];name[unique=true];type(code);sortableType(code);currency[
default=false];localized[default=false];multiValue[default=false
];facet[default=true];facetType(code);facetSort(code);priority;
visible;useForSpellchecking[default=false];useForAutocomplete[
default=false];fieldValueProvider;valueProviderParameter;
facetDisplayNameProvider;customFacetSortProvider;
topValuesProvider;rangeSets(name)
2 ;electronicsProductType;exportToGoogleShopping;boolean;;;;false;;
MultiSelectAnd;;100;true;;;springELValueProvider;
getExportToGoogleShopping();;
In order to add a new free text attribute you need to configure the solr search
config with legacy mode to false, or to update the commerceSearchTextPopulator
bean and add your new field, in our case lastCustomerReview :
1 INSERT_UPDATE SolrSearchConfig;description[unique=true];pageSize;
legacyMode
2 ;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
3 import de.hybris.platform.core.model.product.ProductModel;
4 import de.hybris.platform.solrfacetsearch.config.IndexedProperty;
5 import de.hybris.platform.solrfacetsearch.config.exceptions.
FieldValueProviderException;
6 import de.hybris.platform.solrfacetsearch.indexer.IndexerBatchContext
;
7 import de.hybris.platform.solrfacetsearch.indexer.spi.InputDocument;
8 import de.hybris.platform.solrfacetsearch.provider.impl.
AbstractValueResolver;
9
10
14 @Override
15 protected void addFieldValues(final InputDocument inputDocument,
final IndexerBatchContext IndexerBatchContext,
16 final IndexedProperty indexedProperty, final ProductModel
productModel,
17 final ValueResolverContext<Object, Object>
valueResolverContext) throws
FieldValueProviderException
18 {
19 inputDocument.addField(indexedProperty,
20 productModel.getExportToGoogleShopping() == null ?
Boolean.FALSE : productModel.
getExportToGoogleShopping(),
21 valueResolverContext.getFieldQualifier());
22 }
23
24 }
We need to create a Spring bean for our value provider, it has to have
abstractValueResolver as a parent bean definition :
1 <bean id="productExportToGS" class="com.hybhub.hybhubaddon.search.
solrfacetsearch.provider.impl.ProductExportToGS"
2 parent="abstractValueResolver"/>
Run a full indexation, you should now see that all products have a
exportToGoogleShopping facet, since we set it to Boolean.FALSE by default.
Indexer queries are used by the system to get the list of PKs it needs to work
on, there are different scenarios for the indexing process :
• Full query it runs a full indexation, SAP Hybris will get all products pks
from this query, by default it runs :**
1 SELECT {PK} FROM {Product}
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
:
• de.hybris.platform.solrfacetsearch.indexer.IndexerListener, will be
executed around indexations
• de.hybris.platform.solrfacetsearch.indexer.IndexerBatchListener, will be
executed around batch executions
• de.hybris.platform.solrfacetsearch.indexer.IndexerQueryListener, will be
executed around query executions
First let’s create an Abstract class for our listeners :
1 package com.hybhub.hybhubaddon.search.solrfacetsearch.indexer.impl;
2
3 import org.springframework.beans.factory.annotation.Required;
4
14 @Required
15 public void setName(final String name)
16 {
17 this.name = name;
18 }
19 }
3 import de.hybris.platform.solrfacetsearch.indexer.IndexerContext;
4 import de.hybris.platform.solrfacetsearch.indexer.IndexerListener;
5 import de.hybris.platform.solrfacetsearch.indexer.exceptions.
IndexerException;
6
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10
16 @Override
17 public void beforeIndex(final IndexerContext arg0) throws
IndexerException
18 {
19 LOG.info("Before Index : " + getName());
20 }
21
22 @Override
23 public void afterIndex(final IndexerContext arg0) throws
IndexerException
24 {
25 LOG.info("After Index : " + getName());
26 }
27
28 @Override
29 public void afterIndexError(final IndexerContext arg0) throws
IndexerException
30 {
31 LOG.info("After Index Error : " + getName());
32 }
33
34 }
Example how to declare a bean for the listener and configure it as global :
1 <bean id="globaltHybhubIndexerListener" class="com.hybhub.
hybhubaddon.search.solrfacetsearch.indexer.impl.
HybhubIndexerListenerImpl">
2 <property name="name" value="globaltHybhubIndexerListener" />
3 </bean>
4
5 <bean id="globaltHybhubIndexerListenerDefinition" parent="
solrListenerDefinition">
6 <property name="listener" ref="globaltHybhubIndexerListener"
/>
7 </bean>
Listeners are called based on their priority, from the highest to the lowest
(reversed order for the after method) :
• Global listeners first, ordered by their priority index (default is 100)
• Listeners configured in the Facet Search Config
• Listeners configured in the Indexed Type
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…
If you still don’t understand what this means go to any of the big online retailers
you know, and you will that when you search for a product you can enter its
name then you would 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 :
1 INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=
true];name[unique=true];type(code);fieldValueProvider;facet;
facetType(code);priority;
2 ;electronicsProductType;pickupAvailableFlag;boolean;
productPickupAvailabilityValueProvider;true;MultiSelectAnd;50;
facetType could be :
• Refine, meaning that this would be the only facet used if selected
• MultiSelectAnd, it filters all search
• MultiSelectOr, it adds products based on the facet
After running a full SOLR indexation you should see the new facet under your
product search page.
In order to have efficient facets in some cases you would need to create ranges,
the simplest example is for prices. Without ranges SAP Hybris would create
one facet perspective per price, that would be inefficient and resource consuming.
To achieve efficient facets you will need to create ranges.
The simplest way to understand is to have a look at the out of the box price
ranges available under SAP Hybris, in the example below we create different
ranges for prices in USD, from 0 to 50…For each facet we have a UI string to
display “$0-$49.99” for example, :
1 # Define price range set
2 INSERT_UPDATE SolrValueRangeSet;name[unique=true];qualifier;type;
solrValueRanges(&rangeValueRefID)
3 ;electronicsPriceRangeUSD;USD;double;rangeRefUSD1,rangeRefUSD2,
rangeRefUSD3,rangeRefUSD4,rangeRefUSD5
4
5 # Define price ranges
6 INSERT_UPDATE SolrValueRange;&rangeValueRefID;solrValueRangeSet(name)
[unique=true];name[unique=true];from;to
7 ;rangeRefUSD1;electronicsPriceRangeUSD; $0-$49.99; 0; 49.99
8 ;rangeRefUSD2;electronicsPriceRangeUSD; $50-$199.99; 50; 199.99
9 ;rangeRefUSD3;electronicsPriceRangeUSD; $200-$499.99; 200; 499.99
10 ;rangeRefUSD4;electronicsPriceRangeUSD; $500-$999.99; 500; 999.99
11 ;rangeRefUSD5;electronicsPriceRangeUSD;$1,000-$100,000;1000; 100000
Auto suggestion
Keywords
Keywords are configured within the solr facet search config, they provide you a
the ability to redirect the customer to a page for a given query, for example if
a customer enters the work cart under the search component you redirect him
or her to the cart page.
First you need a SolrFacetSearchKeywordRedirect, this would hold :
• 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 :
– a category redirect
– a direct url
– a page redirect
– a product redirect
Example how to create a new redirect for a product :
1 $productCatalog=electronicsProductCatalog
2 $productCatalogVersion=catalogVersion(CatalogVersion.catalog(Catalog.
id[default=$productCatalog]),CatalogVersion.version[default=
Staged])[default=$productCatalog:Staged]
3 INSERT_UPDATE SolrProductRedirect;redirectItem(code,
$productCatalogVersion)[unique=true];&redirectRefID
4 ;726510;contentCatalogName-redirectRefID-726510
5
6 INSERT_UPDATE SolrFacetSearchKeywordRedirect;facetSearchConfig(name)[
unique=true];language(isocode)[unique=true];keyword[unique=true];
matchType(code)[unique=true];redirect(&redirectRefID);ignoreCase
7 ;electronicsIndex;en;"the best camera";EXACT;contentCatalogName-
redirectRefID-726510;true
Try a search using the best camera as a keyword.
Stopwords
Stopwords are words that SAP Hybris is ignoring during a search, because you
don’t want to search words like the or a, so 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 config
folder config/solr/instances/default/
configsets/default/conf/lang/stopwords_en.txt (example with
stopwords for English, but other languages are available).
If you want to manage stopwords from SAP Hybris you could create them from
Impex queries :
1 INSERT_UPDATE SolrStopWord;facetSearchConfig(name)[unique=true];
language(isocode)[unique=true];stopword[unique=true]
2 ;electronicsIndex;en;the
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, for example let’s 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 one :
1 INSERT_UPDATE SolrSynonymConfig;facetSearchConfig(name)[unique=true];
language(isocode)[unique=true];synonymFrom[unique=true];synonymTo
2 ;electronicsIndex;en;"gigabytes";"GB"
Hero products
SAP Hybris gives the possibility to prioritize which products should appear on
top of the category listing by having hero products. Hero products work on a
category based level, it means that if you don’t navigate inside a given category
but instead do a normal search hero products have no influence on the result
sorting.
For example when a customer navigates to the Camera top category through the
top menu link (Accelerator store front) we want to display the product 478828
(10.2 Megapixel D-SLR with Standard Zoom Lens) first, below the Impex query
:
1 $productCatalog=electronicsProductCatalog
2 $productCatalogVersion=catalogVersion(CatalogVersion.catalog(Catalog.
id[default=$productCatalog]),CatalogVersion.version[default=
Online])[default=$productCatalog:Online]
3 INSERT_UPDATE SolrHeroProductDefinition;$productCatalogVersion[unique
=true];category(code, $productCatalogVersion);code[unique=true];
indexedType(identifier);products(code, $productCatalogVersion)
4 ;;575;575_electronicsProductType;electronicsProductType;478828
5
6 INSERT_UPDATE Product;code[unique=true];$productCatalogVersion[unique
=true];solrHeroProductDefinitions(code)
7 ;478828;;575_electronicsProductType
Now navigate to home -> open catalogue -> cameras -> digital cameras, you
should see your product on top of the search result.
Boost rules
Boost rules help you to adjust the SOLR server answers in the way that for
example product in stock would show up before out of stock products, based on
different factors you will artificially boost the results.
SAP Hybris implemented boosting at query time, meaning that you
do not need to re-index to see the changes!
For example you want the product 1312564 to always be on top you can execute
this Impex query :
1 $solrIndexedType=electronicsProductType
2
3 INSERT_UPDATE GlobalSolrSearchProfile;code[unique=true];indexedType(
identifier)
4 ;globalcatalog-srch-profile0000000001;$solrIndexedType
5
6 INSERT_UPDATE SolrBoostRule;propertyValue[unique=true];
solrIndexedProperty(name);operator(code)[unique=true];boostFactor
;solrSearchProfiles(code)
7 ;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 a SOLR query executed when your
search for battery :
1 localhost:8983/solr/master_electronics_Product/select?
2 q=....'((code_string:battery^90.0)+
3 OR+(keywords_text_en:battery^20.0)+
4 OR+(manufacturerName_text:battery^40.0)+
5 OR+(categoryName_text_en_mv:battery^20.0)+
6 OR+(lastCustomerReview_string:battery^100.0)+
7 OR+(ean_string:battery^100.0)+
8 OR+(name_text_en:battery^50.0))+
9 OR+((keywords_text_en:battery~^10.0)+
10 OR+(manufacturerName_text:battery~^20.0)+
11 OR+(categoryName_text_en_mv:battery~^10.0)+
12 OR+(lastCustomerReview_string:battery~^50.0)+
13 OR+(name_text_en:battery~^25.0))+
14 OR+((code_string:battery*^45.0)+
15 OR+(ean_string:battery*^50.0))+
16 OR+((keywords_text_en:"battery"^40.0)+
17 OR+(manufacturerName_text:"battery"^80.0)+
18 OR+(categoryName_text_en_mv:"battery"^40.0)+
19 OR+(name_text_en:"battery"^100.0))'})+
20 //
21 // This is our custom boost query !
22 //
23 AND+({!func+v="sum(map(query({!v=code_string:1312564})
,0,0,0,1000.0))"})
24 //
25 &sort=score+desc,inStockFlag_boolean+desc,score+desc
26 &start=0&rows=20
27 &facet.field=Resolution,+80_string
28 &facet.field=Mounting,+1867_en_string
29 &facet.field=categoryPath_string_mv
30 &facet.field=Megapixel,+63_string
31 &facet.field=exportToGoogleShopping_boolean
32 &facet.field=availableInStores_string_mv
33 &facet.field=pickupAvailableFlag_boolean
34 &facet.field=Colour+of+product,+1766_en_string
35 &facet.field=price_usd_string
36 &facet.field=allPromotions_string_mv
37 &facet.field=allCategories_string_mv
38 &facet.field=Lens+type,+472_en_string_mv
39 &facet.field=category_string_mv
40 &facet.field=brand_string_mv
41 &facet=true
42 &facet.sort=count
43 &facet.mincount=1
44 &facet.limit=50
45 &spellcheck=true
46 &spellcheck.q=battery
47 &spellcheck.dictionary=en
48 &spellcheck.collate=true
49 &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 :
1 log4j2.logger.search.name=de.hybris.platform.solrfacetsearch
2 log4j2.logger.search.level = debug
3 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 didn’t think
that this could need to be easily updated and made all beans around it without
aliases, so in order to change the maxBoostFactorValue attribute you have 3
options :
• change it directly under
commercesearch/resources/commercesearch-spring.xml, but changing
SAP Hybris source files means it’s hard to update to newer
versions….
• import boost factor rules in legacy mode (without service layer
interceptors)
• using Spring AOP to update the existing bean, the preferred solution
from far
How to change boostRuleValidator bean using AOP, first you need to create a
class to handle the change, this would be called around the validate method call
from the interceptor :
1 package com.hybhub.hybhubaddon.commercesearch.searchandizing.boost.
interceptors;
2
3 import de.hybris.platform.commercesearch.searchandizing.boost.
interceptors.BoostRuleValidator;
4 import org.aspectj.lang.ProceedingJoinPoint;
5 import org.springframework.beans.factory.annotation.Required;
6
17 @Required
18 public void setMaxBoostFactorValue(final int maxBoostFactorValue)
19 {
20 this.maxBoostFactorValue = maxBoostFactorValue;
21 }
22 }
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 :
1 <bean id="hybhubBoostRuleValidatorMethodInterceptor"
2 class="com.hybhub.hybhubaddon.commercesearch.searchandizing.boost
.interceptors.HybhubBoostRuleValidatorAspect">
3 <property name="maxBoostFactorValue" value="500" />
4 </bean>
5
6 <aop:config>
7 <aop:aspect id="boostValidatorAspect" ref="
hybhubBoostRuleValidatorMethodInterceptor">
8 <aop:pointcut id="boostValidatorPoincut"
9 expression="execution(* de.hybris.platform.commercesearch
.searchandizing.boost.interceptors.BoostRuleValidator
.onValidate(..))" />
10 <aop:around method="around" pointcut-ref="
boostValidatorPoincut"/>
11 </aop:aspect>
12 </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 :
1 INSERT_UPDATE SolrBoostRule;propertyValue[unique=true];
solrIndexedProperty(name);operator(code)[unique=true];boostFactor
;solrSearchProfiles(code)
2 ;1312564;code;EQUAL_TO;500;globalcatalog-srch-profile0000000001
Chapter 7
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
124
• 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 current 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
Update
During the update process SAP Hybris update the item types to match the new
items.xml definition, unlike the initialization process there are no loss of data
during an update because update process :
• doesn’t rename tables
• doesn’t rename attributes
• doens’t change an attribute type
• doesn’t drop any table
• doesn’t delete any data
• change indices by recreating them
• doesn’t modify an attribute from optional to required
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)
• Add new type system
• create essential data and project data (if enabled)
On a production system it is a good idea to lock the initialization
from the HAC, configure system.unlocking.disabled=true
3 import de.hybris.platform.commerceservices.setup.AbstractSystemSetup;
4 import de.hybris.platform.core.initialization.SystemSetup;
5 import de.hybris.platform.core.initialization.SystemSetup.Process;
6 import de.hybris.platform.core.initialization.SystemSetup.Type;
7 import de.hybris.platform.core.initialization.SystemSetupContext;
8 import de.hybris.platform.core.initialization.SystemSetupParameter;
9 import de.hybris.platform.core.initialization.
SystemSetupParameterMethod;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import com.hybhub.constants.HybhubhookConstants;
18
19 @SystemSetup(extension = HybhubhookConstants.EXTENSIONNAME)
20 public class HybhubHookSystemSetup extends AbstractSystemSetup
21 {
22
25 @SystemSetupParameterMethod
26 @Override
27 public List<SystemSetupParameter> getInitializationOptions()
28 {
29 final List<SystemSetupParameter> params = new ArrayList<>();
30 params.add(createBooleanSystemSetupParameter("key", "Import ?
", false));
31 return params;
32 }
33
Import by convention
During the initialization and update processes, the platform looks for ImpEx
files under /resources/impex folder. In particular:
• For essential data: The platform scans the /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 /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 essential data, add the property .essentialdata-impex-pattern.
• For project data, use .projectdata-impex-pattern.
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 .essentialdata-impex-
pattern=*.impex.
In contrast to the example above, the pattern
.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
.essentialdata-impex-pattern=impex/essentialdata*.impex.
If you need to control in what order the Impex files are being imported, you can
create a file that match the import pattern, and from this files you will import
all the other Impex files you need in the wanted order :
1 "#% impex.includeExternalData(SampleDataManager.class.
getResourceAsStream(""/firstFileToBeImported.csv""), ""utf-8"",
0, 0 );";
2 "#% impex.includeExternalData(SampleDataManager.class.
getResourceAsStream(""/secondFileToBeImported.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) :
1 def sessionService = spring.getBean("sessionService")
2 def jaloSession = sessionService.getCurrentSession().getJaloSession()
3 def sessionContext = jaloSession.getSessionContext()
4
5 println jaloSession.getHttpSessionId()
6 println sessionContext.getLanguage()
7 println sessionContext.getLocale()
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 :
• lib folder for external libraries
• resources folder for configuration and localization
• src folder for source code
• testsrc folder for the tests
• web folder for the we application
• buildcallbacks.xml file for build call backs configuration
• extensioninfo.xml extension configuration
• project.properties extension properties
• external-dependencies.xml libraries managed by maven
extensioninfo.xml
localextensions.xml
It’s also possible to load external web application (war files for
example), using the webapp tag :
1 <webapp context="/path/to/your/context.xml" path="/mypath"/>
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) :
1 ...
2 [echo] -----
3 [echo] --- Extensions in dependency order ( options:
4 [echo] --- @deprecated: is deprecated, p: platform extension,*: auto
-required
5 [echo] --- ?: lazy-loaded, i: got items.xml, b: got beans.xml, c:
got core module
6 [echo] --- w: got web module, h: got HMC module )
7 [echo] -----
8 [echo] core 6.0.0.0-SNAPSHOT [p*cib]
9 [echo] testweb 6.0.0.0-SNAPSHOT [p*w]
10 [echo] scripting 6.0.0.0-SNAPSHOT [p*ci]
11 ....
You can create new extensions based on an existing template, below example
create a new extension base on the yempty template :
1 $ platform ant extgen
2 ...
3 ...
4 [input]
5 [input] Please choose a template for generation.
6 [input] Press [Enter] to use the default value (ywebservices,
ysmarteditmodule, yoccaddon, yhacext, [yempty],
ycommercewebservices, ycommercewebservicestest,
ycommercewebserviceshmc, ycmssmartedit,
ychinaacceleratorstorefront, yatddtests, yaddon,
yacceleratorstorefront, yacceleratorordermanagement,
yacceleratorfulfilmentprocess,
yacceleratorfractusfulfilmentprocess, yscala, ygroovy,
ycockpit, ybackoffice, hybhubstorefront,
hybhubfulfilmentprocess)
7 yempty
8 [input]
9 [input] Please choose the name of your extension. It has to start
with a letter followed by letters and/or numbers.
10 [input] Press [Enter] to use the default value [training]
11 myextension
12 [input]
13 [input] Please choose the package name of your extension. It has
to fulfill java package name convention.
14 [input] Press [Enter] to use the default value [org.training]
15 com.hybhub
16 ...
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 extensioninfo.xml file and configure it with usemaven=”true” :
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <extensioninfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="extensioninfo.xsd">
3 <extension abstractclassprefix="Generated" classprefix="
Hybhubhook" managername="HybhubhookManager"
4 managersuperclass="de.hybris.platform.jalo.extension.
Extension" name="hybhubhook" usemaven="true">
5 <requires-extension name="commerceservices" />
6 <coremodule generated="true" manager="com.hybhub.jalo.
HybhubhookManager" packageroot="com.hybhub" />
7 <webmodule jspcompile="false" webroot="/hybhubhook" />
8 </extension>
9 </extensioninfo>
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 :
• config/local.properties
• your extensions project.properties files
• platform directory project.properties file
Configuration properties are defined using a key and a value, example :
1 #A comment
2 the.key=myValue
Configuration Service
You can read or edit the current configuration, have a look at the interface
org.apache.commons.configuration.Configuration.
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 keyword, for example within my configuration
I have :
1 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)
:
1 export y_hybhub_config=fromConsole
Build
SAP Hybris build framework is based on :
• Apache Ant, automation framework build in Java
• 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
• resolves extensions dependencies
– you cannot predict the order extensions are being built
– 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)
• collects localization property files (locales_XY.properties)
• collects layout configuration files (hmc.xml)
• updates the hybris Server
You can use ant with different scopes :
• platform, will execute the target for all extensions
• extension, will execute the target for a single extension
To see all ant targets, you can use ant -p.
Unless you execute ant clean Java classes are not compiled every time
you call ant all, because the javac command will compare timestamp
of the source and target and compile the source only if its timestamp
is newer than the target
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 build
:
1 <macrodef name="hybhubhook_before_build">
2 <sequential>
3 <echo message="Hybhub is being build !!" level="info"/>
4 </sequential>
5 </macrodef>
Tenant
SAP Hybris can run in a multi tenant mode, meaning that each tenant are using
a different set of data.
Each tenant has :
• isolated data
• option to have a separate database
• option to use a different time zone and locales
• option to use different extensions
To declare new tenants :
1 installed.tenants=junit,foo,t1,t2,hybhub
Cache
SAP Hybris cache helps to reduce the number of database queries, it caches
three type of objects :
• Flexible Search Queries results
• Item instances
• Item attributes
The cache is used within the Service Layer, it is completely transparent to use
it, when you call a getter on an item attribute, if it hasn’t been loaded yet it
would be 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 :
• Cache is full and the replacement strategy is removing an entry
• Cache is no longer valid :
• 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 region, each region has its own configuration,
caches different kind of objects and has a maximum size. Regions can have
different kind of eviction strategy :
• 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
ehCacheEntityCacheRegion and uses LRU eviction strategy.
To create new cache region you need to create a new Spring Beans within the
global Spring context, first I configure for my extension named hybhubhook a
new global spring context file :
1 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.
Interceptors
The service layer gives the ability to activate interceptor when life cycle of a
model reaches certain steps :
• load interceptor
(de.hybris.platform.servicelayer.interceptor.LoadInterceptor) is loaded
when the service layer loads an item. You may use this interceptor to
change or check values loaded by the service layer.
• init default interceptor
(de.hybris.platform.servicelayer.interceptor.InitDefaultsInterceptor) is
called when you create a new item from the model service. You may use
this interceptor to fill the item with default value you couldn’t configure
from the *items.xml
• prepare interceptor
(de.hybris.platform.servicelayer.interceptor.PrepareInterceptor) is called
before an item is saved by the service layer. You may use this interceptor
to add or update attribute values before they are saved
• validate interceptor
(de.hybris.platform.servicelayer.interceptor.ValidateInterceptor) is called
before an item is saved and after it has been prepared. You may use this
interceptor to validate the integrity of the data
• remove interceptor
(de.hybris.platform.servicelayer.interceptor.RemoveInterceptor) is called
before an item is being removed by the service layer. You may use this
interceptor to prevent removal of data or to delete related data.
Example on how to create an interceptor for product items :
1 package com.hybhub.hybhubaddon.servicelayer.interceptor;
2
3 import de.hybris.platform.core.model.product.ProductModel;
4 import de.hybris.platform.servicelayer.interceptor.InterceptorContext
;
5 import de.hybris.platform.servicelayer.interceptor.
InterceptorException;
6 import de.hybris.platform.servicelayer.interceptor.RemoveInterceptor;
7
8 import java.util.regex.Pattern;
9
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13
21 @Override
22 public void onRemove(final ProductModel prd, final
InterceptorContext ctx) throws InterceptorException
23 {
24 LOG.info("Removing product : " + prd.getCode());
25 if (PROTECTED_PRODUCTS.matcher(prd.getCode()).find())
26 {
27 throw new InterceptorException("Product is protected,
cannot remove it !");
28 }
29 LOG.info("Product : " + prd.getCode() + " removed");
30 }
31 }
You need to declare the interceptor as a Spring bean and to configure the type
mapping :
1 <alias name="defaultProductRemoveInterceptor" alias="
productRemoveInterceptor" />
2 <bean id="defaultProductRemoveInterceptor" class="com.hybhub.
hybhubaddon.servicelayer.interceptor.ProductRemoveInterceptor" />
3 <bean id="productRemoveInterceptorMapping" class="de.hybris.platform.
servicelayer.interceptor.impl.InterceptorMapping">
4 <property name="interceptor" ref="productRemoveInterceptor" />
5 <property name="typeCode" value="Product" />
6 </bean>
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 :
• a replacedInterceptors collection, if you want to replace existing
interceptors
• an order of priority to run them in a sequence if there are multiple
interceptors
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 :
1 final Map<String, Object> params = ImmutableMap.of(
InterceptorExecutionPolicy.DISABLED_INTERCEPTOR_TYPES,
2 ImmutableSet.of(InterceptorExecutionPolicy.
DisabledType.VALIDATE));
3 sessionService.executeInLocalViewWithParams(params, new
SessionExecutionBody()
4 {
5 @Override
6 public void executeWithoutResult()
7 {
8 modelService.save(item); // executed without any validate
interceptors
9 }
10 });
Transactions
Transactions are used to keep the data consistent at any time, SAP Hybris
provides a wrapper to easily work with transactions.
Simple groovy example :
1 def transaction = de.hybris.platform.tx.Transaction.current()
2
3 transaction.begin()
4
Tasks
SAP Hybris provides a task service with the following features :
• Scheduling, time and event based
• Cluster aware, a task may be executed by any of the available node
• pool of workers, to avoid to overload the cluster with too many tasks, there
is a maximum number of running workers (see project.properties from the
processing extension)
Chapter 8
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
• Events can be published locally or across cluster nodes
• SAP Hybris Event System is based on the Spring event system
To create your own event, you need to extend the class
de.hybris.platform.servicelayer.event.events.AbstractEvent :
1 package com.hybhub.event;
2
3 import de.hybris.platform.servicelayer.event.events.AbstractEvent;
4
14 @Override
15 public String toString()
144
16 {
17 return "Hybhub Event : " + this.name;
18 }
19 }
3 import de.hybris.platform.servicelayer.event.impl.
AbstractEventListener;
4
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7
14 @Override
15 protected void onEvent(final HybhubEvent hybhubEvent)
16 {
17 LOG.info("Received event(Hybhub Event) : " + hybhubEvent);
18 }
19
20 }
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 :
• make your event cluster aware by implementing
de.hybris.platform.servicelayer.event.ClusterAwareEvent, when you
implement this interface your events are always processed asynchronously
even if they are executed on the same node they were created
1 package com.hybhub.event;
2
3 import de.hybris.platform.servicelayer.event.ClusterAwareEvent;
4 import de.hybris.platform.servicelayer.event.events.AbstractEvent;
5
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
22 @Override
23 public String toString()
24 {
25 LOG.info(Thread.currentThread().getName());
26 return "Hybhub Event : " + this.name;
27 }
28
29 @Override
30 public boolean publish(final int sourceClusterId, final int
targetClusterId)
31 {
32 return true; //Returning true means your event will be
broadcasted on all nodes
33 }
34 }
• update the Spring bean platformClusterEventSender with an executor :
1 <bean id="platformClusterEventSender" class="de.hybris.platform.
servicelayer.event.impl.PlatformClusterEventSender">
2 <property name="serializationService" ref="serializationService"/
>
3 <property name="tenant" ref="tenantFactory"/>
4 <property name="executor">
5 <bean class="java.util.concurrent.Executors" factory-method="
newCachedThreadPool"/>
6 </property>
7 </bean>
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, it means import and export, it is an
out of the box CSV based import framework, from an impex file you can :
• import data
• update data
• import / update data
• remove data
• export data
Impex are useful for:
• 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
An Impex query has :
• 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
You can also specify a subtype of the Header item type on the value line, for
example :
1 INSERT User;uid[unique=true]
2 Customer;aCustomer
3 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), but 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 lookup for them based on their own attributes.
1 INSERT Product;code;unit(code);catalogVersion(catalog(id), version)
2 ;product;pieces;electronic:Staged
To localized attributes you need to use a modifier within the header attributes
like [lang=en] to localize an attribute in English :
1 INSERT Type;localizedAttribute[lang=en]
A commented line starts with a dash # and are completely ignored during
import :
1 INSERT_UPDATE Product;code
2 #Begin importing products
3 ;product1;
4 #Finished importing products
Macro
Impex files can easily be huge, 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 :
1 #Macro definition
2 $unit=pieces
3 $variantType=LaptopVariant
4 $aid=MBP-
5 $manufacturer=Apple
6
7 $catalogVersion=catalogversion(catalog(id[default=$productCatalog]),
version[default='Staged'])[unique=true,default=$productCatalog:
Staged]
8 $supercategories=supercategories(code, $catalogVersion)
9
10 INSERT_UPDATE Product;code[unique=true];$supercategories;
manufacturerName;manufacturerAID;unit(code);variantType(code);
$catalogVersion;$approved
11 ;000010;000100;$manufacturer;$aid13;$unit;$variantType
12 ;000011;000100;$manufacturer;$aid15;$unit;$variantType
Abbreviations
Another way to shorten Impex files is to use abbreviations, you could use system
wide regex replacement for you Impex headers, for example out of the box there
is an header replacement for the classification header :
1 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 :
1 # Classification: Technical details (4593)
2 $feature1=@Motor diameter, 6752[$clAttrModifiers]; # Motor diameter
in millimeter (mm)
Document ID
Sometimes item references lookup method trough attributes is not enough 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 :
1 INSERT_UPDATE Customer;groups(uid);uid[unique=true];name;
defaultPaymentAddress( &addrID )
2 ;customergroup;[email protected];Andrew;addr1
3
4 INSERT Address;&addrID;owner(Customer.uid);
5 ;addr1;[email protected];
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 :
1 INSERT_UPDATE Media;code[unique=true];realfilename;@media[translator=
de.hybris.platform.impex.jalo.media.MediaDataTranslator];mime[
default='image/jpeg'];$catalogVersion
2 ;/img/low_pic/574-4346.jpg;574-4346.jpg;$siteResource/images/img/
low_pic/574-4346.jpg;
When an item type relation is set to a basic item type such as ItemType for
example you could find the referenced item from multiple attributes, you can in
this case give the Impex attribute different options, below is an example with
the address owner type which is set to ItemType :
1 INSERT_UPDATE Address;lastname;owner( Principal.uid | AbstractOrder.
code )
2 ;Robert;[email protected]
3 ;Dupre;00000001
Distributed Impex
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 :
• a global static application context shared by all tenants
– to configure it you need to configure an extra property within your
extension configuration extname.global-context=spring.xml
• a core application context for each tenant
– its parent the global application context
– to configure it within your extension
– use the convention resources/extname-spring.xml
– configure a different path extname.application-context=spring.xml
• a web application context for each web application
– 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 application 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.
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
• importing or exporting data
A cronjob is made of :
• a job to do
• a trigger to start the job (not mandatory)
• 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 :
1 <typegroup name="hybhub">
2 <itemtype code="DeactivateOutdatedProductCronJob" extends="
CronJob">
3 <description>Job to deactivate out-dated products</
description>
4 <attributes>
5 <attribute type="java.util.Date" qualifier="minLastUpdate
">
6 <persistence type="property" />
7 </attribute>
8 </attributes>
9 </itemtype>
10 </typegroup>
Then we need to create the actual job that deactivate products based on the
minLastUpdate attribute :
1 package com.hybhub.job;
2
3 import de.hybris.platform.catalog.CatalogVersionService;
4 import de.hybris.platform.catalog.enums.ArticleApprovalStatus;
5 import de.hybris.platform.core.model.product.ProductModel;
6 import de.hybris.platform.cronjob.enums.CronJobResult;
7 import de.hybris.platform.cronjob.enums.CronJobStatus;
8 import de.hybris.platform.servicelayer.cronjob.AbstractJobPerformable
;
9 import de.hybris.platform.servicelayer.cronjob.PerformResult;
10 import de.hybris.platform.servicelayer.model.ModelService;
11 import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
12 import de.hybris.platform.servicelayer.search.FlexibleSearchService;
13
14 import java.util.List;
15
16 import javax.annotation.Resource;
17
18 import com.hybhub.model.DeactivateOutdatedProductCronJobModel;
19
20
24 @Resource
25 private FlexibleSearchService flexibleSearchService;
26
27 @Resource
28 private CatalogVersionService catalogVersionService;
29
30 @Resource
31 private ModelService modelService;
32
33 @Override
34 public PerformResult perform(final
DeactivateOutdatedProductCronJobModel cronjob)
35 {
36 final FlexibleSearchQuery fsq = new FlexibleSearchQuery("
SELECT {pk} FROM {Product} "
37 + "WHERE {modifiedtime} <= ?minLastUpdate " + " AND {
catalogVersion} = ?catalogVersion");
38
39 fsq.addQueryParameter("minLastUpdate", cronjob.
getMinLastUpdate());
40 fsq.addQueryParameter("catalogVersion", catalogVersionService
.getCatalogVersion("electronicsProductCatalog", "Staged")
);
41
44 productsToUpdate.stream().forEach((prd) -> {
45 prd.setApprovalStatus(ArticleApprovalStatus.UNAPPROVED);
46 modelService.save(prd);
47 });
48
52 }
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 !
1 import com.hybhub.model.DeactivateOutdatedProductCronJobModel
2 import de.hybris.platform.cronjob.model.JobModel
3 import de.hybris.platform.cronjob.model.TriggerModel
4
13 DeactivateOutdatedProductCronJobModel cron =
14 modelService.create(DeactivateOutdatedProductCronJobModel.class)
15
16 cron.setMinLastUpdate(new Date())
17 cron.setCode("deleteOutdatedProductsss")
18 cron.setJob(job)
19
20 modelService.save(cron)
21
31 cronJobService.performCronJob(cron)
Be careful this will change the status of all your products under the
staged electronic product catalog !
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
• cron jobs / events for specific nodes
• session failover
• 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
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 would send a
request (TCP or UDP depends on your cluster configuration) so other nodes
would discard the item and reload it from the database the next time they need
to access that object.
Configuration
Nodes need to have a unique identifier, prior to SAP Hybris V6 you had to
manually configure an id for each node :
1 clustermode=true
2 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 will keep track of each nodes within the database :
1 clustermode=true
2 cluster.nodes.autodiscovery=true
Price calculation
SAP Hybris provides a flexible, scalable and configurable way to handle prices,
all price informations 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 DefaultPriceFactoryService
To be selected by the price factory a price row needs (following the order of
execution) :
158
• match the customer / customer group or be empty
• match the product / product group
• within the date range if any configured
• quantity is equal or bigger than the minimum quantity if any configured
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 :
• product and customer
• product group and customer
• product and customer group
• product group and customer group
• product and all customers
• product group and all customers
• all products and customer
• all products and customer group
• all products and all customers
When the price factory returns more than one price if they are more than one
match the PriceService will select the lowest one.
Taxes
Taxes are represented by tax rows, they define :
• an absolute flag
• a currency
• a date range
• a product tax group
• a product
• a product match qualifier
• a tax object
• a user tax group
• a user
• a user match qualifier
• 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 :
• customer / customer group or empty field
• product / product group or empty field
• date range
Discounts
Discounts are represented by discount rows, they define :
• an absolute flag
• a currency
• a date range
• a product discount group
• a product
• a product match qualifier
• a discount object
• a user discount group
• a user
• a user match qualifier
• 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 :
• customer / customer group or empty field
• product / product group or empty field
• 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 location on the disk or remote location
• a unique identifier
• a catalog version
• a mime type
• a URL
• 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 Amazon 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 formats help you to server the same image in different but for different
contexts, for example on the product listing page (PLP) you need to get a
small image of the products but on the product detail page (PDP) you need
a bigger image, all those formats are loaded within a media container which is
a container for multiple medias, inside a product media data object and you
can simply select the appropriate format on your front end. The out of the box
formats are :
1 <alias name="acceleratorImageFormatMapping" alias="imageFormatMapping
"/>
2 <bean id="acceleratorImageFormatMapping" parent="
defaultImageFormatMapping">
3 <property name="mapping">
4 <map>
5 <entry key="superZoom" value="1200Wx1200H"/>
6 <entry key="zoom" value="515Wx515H"/>
7 <entry key="store" value="365Wx246H"/>
8 <entry key="product" value="300Wx300H"/>
9 <entry key="thumbnail" value="96Wx96H"/>
10 <entry key="cartIcon" value="65Wx65H"/>
11 <entry key="styleSwatch" value="30Wx30H"/>
12 </map>
13 </property>
14 </bean>
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
To secure all media turn configure it to true, if you need to secure only one
folder you can use :
1 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)
A catalog can have multiple versions. A Synchronization could merge
two Staged catalog into one Online catalog.
To create a new CatalogVersionSyncJob from an Impex query :
1 $productCatalog=productCatalog
2 $defaultCurrency=EUR
3 $languages=en
4 $defaultLanguage=en
5 $prices=europe1prices[translator=de.hybris.platform.europe1.jalo.
impex.Europe1PricesTranslator]
6 $stagedProduct=catalogVersion(catalog(id[default=$productCatalog]),
version[default='Staged'])[unique=true,default='$productCatalog:
Staged']
7 $onlineProduct=catalogVersion(catalog(id[default=$productCatalog]),
version[default='Online'])[unique=true,default='$productCatalog:
Online']
8
9 $sourceProductCV=sourceVersion(catalog(id[default=$productCatalog]),
version[default='Staged'])[unique=true,default='$productCatalog:
Staged']
10 $targetProductCV=targetVersion(catalog(id[default=$productCatalog]),
version[default='Online'])[unique=true,default='$productCatalog:
Online']
11
12 INSERT_UPDATE CatalogVersionSyncJob;code[unique=true];
$sourceProductCV;$targetProductCV;
13 ;sync productCatalog:Staged->Online;;;;
Workflow
SAP Hybris workflows help you modeling business processes like writing and
validating a product description in multiple languages, a workflow is defined by
:
• workflow template, it has a sequence of action templates
• workflow action template, define a step of a workflow, it produces an
option
• Option, possible result of an action it also defines the next step to follow
• workflow, an instance of a workflow template, created by making a copy
of the template
• workflow action, an instance of a workflow action template, created by
making a copy of the template
• decision, stores the option result of an action
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 updated, 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
165
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 :
1 $START_USERRIGHTS
2 Type;UID;MemberOfGroups;Password;Target;read;change;create;delete;
change_perm
3 UserGroup;employeegroup;;
4 ;;;;Product;+;-;-;-;-
5 ;;;;CMSItem.name;+;-;-;-;-
6 $END_USERRIGHTS
Permission service
12 PermissionAssignment permission =
13 new PermissionAssignment("read", productmanager, true)
14 pms.addTypePermission(typeService.getComposedTypeForCode("Product")
15 , permission)
16
Remember :
• de.hybris.platform.servicelayer.
security.permissions.PermissionCheckingService is used to check
permissions
• de.hybris.platform.servicelayer.
security.permissions.PermissionManagementService is used to configure
permissions
• de.hybris.platform.servicelayer.
security.permissions.PermissionCRUDService is used to check CRUD
operations (read, change, create, remove, change rights)
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
• admin group users
• direct item type access though the model service
To deactivate search restriction use de.hybris.platform.search.
restriction.SearchRestrictionService.enableSearchRestrictions()
Since restrictions are linked to a session you have access to sessions attributes
within the restriction {user} = ?session.user. To create a restriction you can :
• use the service layer to create a restriction item
• execute an impex query
Impex example
1 INSERT_UPDATE SearchRestriction;code[unique=true];name[lang=en];query
;principal(UID);restrictedType(code);active;generate
2 ;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 :
– administrator, can manage a unit
– manager, can access reports
– approver, can approve orders and define user’s monetary limit
– customer, place orders (automatically approved if under the approval
threshold)
• 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.
Chapter 11
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 plan how you envision it :
1. I setup a V6 environment on my local
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
4. I pass the assessment exam
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
7. I study again point listed from the first mocked exam
8. I pass the second mocked exam in real condition and list all unclear
concepts and wrong answers
9. I study again point listed from the second mocked exam
10. the days before the exam I randomly pick questions and check if I know
the answer
169
Play with SAP Hybris
To be ready for the exam you need to be able to create a new B2C
implementation, customize the initial data, create new pages and controllers
and customize the backoffice. While you are doing this you need not to only
follow the trails, try to remember things you would love to see within SAP
Hybris and implement then yourself (image compression, attribute automatic
translation, customized checkout…).
Most important is to learn how to tackle issues while developing, understand
why an impex file is not being imported or learn the difference between the Jalo
layer and service layer!
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
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
Solution
171
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
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
Solution
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
3. inserts line by batches, default batch size is 20
4. There is no such header modifier
Solution
Mock 1 - Question 6
What are the steps in order to create a backoffice widget ?
1. create a widget view
2. create a widget model hook
3. create a widget definition
4. execute ant widgetGen
Solution
Mock 1 - Question 7
What is correct definition of the LTU eviction strategy ?
1. The oldest element would be deleted first
2. The youngest element would be deleted first
3. The most unused element would be deleted first
4. This is not a valid eviction strategy
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
4. Item types are not compatible with inheritance
Solution
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
2. Model View Controller
3. Service Layer
4. Facade
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
2. you cannot perform a flexible search being admin
3. you will only see in the result for the admin catalog
4. at least one restriction must be configured or no search will be performed
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
2. each line under header is a potential value line
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
Solution
Mock 1 - Question 12
OAUTH2 is
1. a library built by SAP Hybris to handle authentification
2. a library built by Spring to handle authentification
3. an application protocol like HTTP but for authorization
4. an authorization protocol
Solution
Mock 1 - Question 13
To load a localized resource bundle, what service should you use ?
1. L10NService
2. I18NService
3. CommonI18NService
4. CommerceCommonI18NService
Solution
Mock 1 - Question 14
How can you activate the cluster mode ?
1. cluster mode is on by default
2. cluster mode is always on
3. configure clustermode=true
4. configure clustering=true
Solution
Mock 1 - Question 15
What are the logging framework shipped with Hybris ?
1. LOG4J
2. LOG4J2
3. LOG4J3
4. SLF4J
Solution
Mock 1 - Question 16
What happen when you run the following Impex script when the currency doesn’t
exist yet ?
1 UPDATE Currency;isocode[unique=true];conversion;digits;symbol
2 ;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
Solution
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
2. the customerCartService wrapper is preferred to the raw cart service
3. getSessionCart() is deprecated, use getInMemoryCart() instead
4. getEntries() could be null
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
2. process all incoming requests made to the root path
3. servlet responsible to find a matching controller and view to generate a
response
4. servlet responsible to load data from the database, load the JSP view and
delegate the request handling to a matching controller
Solution
Mock 1 - Question 19
What template do you use do create a new cockpit ?
1. ycockpit
2. cockpit
3. ybackoffice
4. backoffice
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.xml
2.
cockpitextension/resources/cockpitextension/cscockpit/cockpitgroup/listViewContentBrowser_CatalogVer
3. cockpitextension/resources/cockpitextension-
admin/cscockpit/cockpitgroup/listViewContentBrowser.xml
4. cockpitextension/resources/cockpitextension-
config/cscockpit/cockpitgroup/listViewContentBrowser_CatalogVersion.xml
Solution
Mock 1 - Question 21
Which methods are valid to create and save a new product item from the service
layer ?
1.
1 ModelService modelService = spring.getBean("modelService");
2 ProductModel prd = new ProductModel();
3 //Fill the product object with valid data
4 modelService.save(prd);
2.
1 ModelService modelService = spring.getBean("modelService");
2 ProductModel prd = modelService.create("Product");
3 //Fill the product object with valid data
4 modelService.save(prd);
3.
1 ModelService modelService = spring.getBean("modelService");
2 ProductService productService = spring.getBean("productService");
3 //Assuming we load a valid product
4 ProductModel prdTemplate = productService.getProductForCode("000001")
5 ProductModel prd = modelService.clone(prdTemplate)
6 //Set all unique data
7 modelService.save(prd);
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
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 ?
1 INSERT_UPDATE Currency;isocode[unique=true];conversion;digits;symbol
2 ;DKK;1;2;DKK
3
4 INSERT Currency;isocode[unique=true];conversion;digits;symbol
5 ;DKK;7;2;DKK
6
7 INSERT_UPDATE Currency;isocode[unique=true];conversion;digits
8 ;VND;7;2;VND
1. none
2. one
3. two
4. three
Solution
Mock 1 - Question 24
Which of the following application contexts are valid ?
1. tenant service application context
2. tenant core application context
3. global web application context
4. hac web application context
Solution
Mock 1 - Question 25
Is this a valid item type definition ?
1 <itemtype code="DeactivateOutdatedProductCronJob">
2 <description>Job to deactivate out-dated products</description>
3 <attributes>
4 <attribute type="java.util.Date" qualifier="minLastUpdate">
5 <persistence type="memory" />
6 </attribute>
7 </attributes>
8 </itemtype>
Solution
Mock 1 - Question 26
What does the ant target customize do ?
1. inject all properties into tomcat configuration
2. execute all call back scripts
3. copies all files from /config/customize folder to /bin folder recursively
4. customize the tomcat configuration folder from the config folder
Solution
Mock 1 - Question 27
What SQL query could be generated from the following flexible search query ?
1 select {pk} from {Product as prd}
Solution
Mock 1 - Question 28
Which of the following item type attribute default value definition valid ?
1. java.lang.Boolean.FALSE
2. enumerationService().getEnumerationValue(“validEnumeration”,
“validValue”)
3. Boolean.FALSE
4. com.hybhub.core.ExistingClass.EXISTING_STATIC_STRING
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
2. lock a model object
3. remove a model object
4. create new item type definition
Solution
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
2. you use it to create and modify back office application
3. you use it to import new data
4. you need to press F4 to activate it
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
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
2. defines an application as a collection of components, in which API calls
between components are made through concrete classes, not abstract
interfaces
3. defines an application as a collection of static components, in which API
calls between components are made static references
4. defines an application as a collection of RESTFUL API entry points, calls
between components are made through HTTP requests
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
2. create a job implementation of JobPerformable
3. Update your system
4. create a new item that extends cronjob
Solution
Mock 1 - Question 34
How do you declare an attribute dynamic ?
1.
2.
3.
4.
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
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 administrators only
2. configure expressUpdateCatalogVersions=catalog:version
3. each product can be synchronized individually out of the box
4. PCM is not for products
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
Solution
Mock 1 - Question 38
In order to test a dao implementation what test should you write ?
1. @UnitTest
2. @DatabaseTest
3. @SqlTest
4. @IntegrationTest
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= assuming the env variable exists and is name
y_hybhub_config
4. 3. using hybhub.config=? assuming the env variable exists and is name
hybhub_config
Solution
Mock 1 - Question 40
What statements are correct about he following impex ?
1 INSERT_UPDATE MediaFolder;qualifier[unique=true];path[unique=true]
2 ;images;images
3 ;email-body;email-body
4 ;email-attachments;email-attachments
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’
Solution
Mock 1 - Question 42
Choose the right definition for a payment capture ?
1. authorize an amount of money after it has been reserved
2. transfer money back for a given order
3. transfer money from after it has been authorized
4. lock an amount of money on the card’s holder account
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
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
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
Solution
Mock 1 - Question 46
How many transactions would be created by the following Groovy script ?
1 def transaction = de.hybris.platform.tx.Transaction.current()
2
3 transaction.begin()
4
5 transaction.begin()
6 //Do something
7 transaction.commit()
8
9 transaction.begin()
10 //Do something
11 transaction.commit()
12
13 transaction.commit()
Mock 1 - Question 47
What is the main entry servlet of Spring MVC application ?
1. SpringMvcServlet
2. DispatcherServlet
3. JaloServlet
4. RequestContextServlet
Solution
Mock 1 - Question 48
What statements are true about CMSItem and CMSRelation item types ?
1. their sub items are catalog version aware
2. it’s used by all tag components
3. every CMS types extend one or the other
4. they are defined under the core extension
Solution
Mock 1 - Question 49
How can you configure a new checkout flow ?
1. from an impex query
2. from a java implementation of
de.hybris.platform.acceleratorstorefrontcommons.checkout.CheckoutFLow
3. from a spring configuration
4. from JSP tag file
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
Solution
Mock 1 - Question 51
Choose the best definition for the following exception :
de.hybris.platform.servicelayer.exceptions.AmbiguousIdentifierException ?
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
4. the service layer doesn’t know the item type
Solution
Mock 1 - Question 52
What informations can you extract from a PK ?
1. type code
2. last modified time
3. created time
4. user who created the item
Solution
Mock 1 - Question 53
The Spring Integration Framework is used for ?
1. OCC webservices
2. Datahub
3. Hot Folder
4. Service Layer
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
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
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
Solution
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 product definition
3. products are virtual
4. all variant objects and the base product share the same unique code which
makes any search not trivial
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
2. use a paginated solr search query
3. use a facet range
4. use a facet sort
Solution
Mock 1 - Question 59
Which of the following interceptors are valid ?
1. load
2. init
3. prepare
4. remove
Solution
Mock 1 - Question 60
What statements are true wrong about the build framework ?
1. it compiles extension in a pre-defined order
2. it generates and compiles sources from items.xml files
3. every ant targets compile the source files
4. it is runnable only from your platform folder
Solution
Mock 1 - Question 61
A Media can be ?
1. a image
2. a zip file
3. a flat file
4. a string
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
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 ?
1 {name} is not null
Solution
Mock 1 - Question 64
What happened when you execute the following Groovy script ?
1 import java.util.HashSet
2 import de.hybris.platform.core.model.user.UserGroupModel
3
12
18 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
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
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
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
Solution
Mock 1 - Question 68
Why would run the following flexible search query ?
1 select {pk} from {Product!}
Solution
Mock 1 - Question 69
What is the right way to create a localized string attribute ?
1.
1 <attribute qualifier="name" type="java.lang.String">
2 <persistence type="property" localized="true"/>
3 </attribute>
2.
1 <attribute qualifier="name" type="localized:String">
2 <persistence type="property"/>
3 </attribute>
3.
1 <attribute qualifier="name" type="localized:java.lang.String">
2 <persistence type="property" />
3 </attribute>
4.
1 <attribute qualifier="name" type="localized:java.lang.String">
2 </attribute>
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
Solution
Mock 1 - Question 71
What is the purpose of the following class ?
1 /*
2 * [y] hybris Platform
3 *
4 * Copyright (c) 2000-2016 SAP SE
5 * All rights reserved.
6 *
7 * This software is the confidential and proprietary information of
SAP
8 * Hybris ("Confidential Information"). You shall not disclose such
9 * Confidential Information and shall use it only in accordance with
the
10 * terms of the license agreement you entered into with SAP Hybris.
11 */
12 package com.hybhub.setup;
13
14 import ...
15
16 @SystemSetup(extension = HybhubhookConstants.EXTENSIONNAME)
17 public class HybhubHookSystemSetup extends AbstractSystemSetup
18 {
19
22 @SystemSetupParameterMethod
23 @Override
24 public List<SystemSetupParameter> getInitializationOptions()
25 {
26 final List<SystemSetupParameter> params = new ArrayList<>();
27 params.add(createBooleanSystemSetupParameter("key", "Choice",
false));
28 return params;
29 }
30
45 }
Solution
Mock 1 - Question 72
Solution
Is this a valid impex import ?
1 INSERT_UPDATE Title;code
2 #% beforeEach: print(line[1]);
3 ;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
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
Solution
Mock 1 - Question 74
Which are valid steps of the ant build all target ?
1. Resolving extensions dependencies
2. Restart the application server
3. Delete all previously compiled classes
4. Generate sources for all extensions
Solution
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
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
Solution
Mock 1 - Question 77
Is this a valid business process definition ?
1 <?xml version="1.0" encoding="utf-8"?>
2 <process>
3
4 <action id="action1" bean="action1">
5 <transition name="OK" to="success"/>
6 <transition name="NOK" to="action2"/>
7 </action>
8
9 <action id="action2" bean="action2">
10 <transition name="OK" to="error"/>
11 </action>
12
13 <end id="error" state="ERROR">All went wrong.</end>
14 <end id="success" state="SUCCEEDED">Order placed.</end>
15
16 </process>
1. yes
2. yes if you had a new action with start=true
3. yes if action1 implements StartProcess
4. no
Solution
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
2. create an item that extends CMSItem or one of its subtype
3. a Spring MVC controller that extends AbstractCMSComponentController
4. a JSP (or other front end technology) to render the component
Solution
Mock 1 - Question 79
When should you run a full Apache SOLR indexation ?
1. when you restart the SOLR server
2. when you update a product
3. when you update prices
4. every day to recreate a clean index (not defragmented)
Solution
Mock 1 - Question 80
How many websites could you have per tenant ?
1. only one because orders and customers are tenant dependent
2. websites are not tenant aware
3. as many as you need
4. as many as you want if you are running a cluster
Solution
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.
Solution
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.
Solution
Mock 1 - Solution 3
2,4 are correct.
The setantenv scrips configure :
• PLATFORM_HOME
• ANT_OPTS
• ANT_HOME
• add ANT_HOME to your path
Solution
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.
Solution
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.
Solution
Mock 1 - Solution 6
1,3 are correct.
Solution
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)
Solution
Mock 1 - Solution 8
**1,2,3,4*8 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)
Solution
Mock 1 - Solution 9
4 is correct.
Solution
Mock 1 - Solution 10
1 is correct.
Solution
Mock 1 - Solution 11
2 is correct.
After a header all lines would be imported (unless they are empty, contain
comments or macro).
Solution
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.
Solution
Mock 1 - Solution 13
1 is correct.
• I18NService is to load Java Locale objects
• CommonI18NService is to load SAP Hybris internationalization objects
(CountryModel, LangageModel…)
• CommerceCommonI18NService is to load SAP Hybris internationalization
objects (CountryModel, LangageModel…) for the current base site
Solution
Mock 1 - Solution 14
3 is correct.
Solution
Mock 1 - Solution 15
2 is correct.
SLF4J is a simple logging facade for logging frameworks.
Solution
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.
Solution
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. 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.
Solution
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.
Solution
Mock 1 - Solution 19
1 is correct.
Question
Mock 1 - Solution 20
4 is correct.
Remember extensionName/resources/extensionName-
config/userGroup/context_itemType.xml
Question
Mock 1 - Solution 21
Question
1,2,3 are correct
Mock 1 - Solution 22
1 is correct.
Question
Mock 1 - Solution 23
2 is correct.
1 INSERT Currency;isocode[unique=true];conversion;digits
2 ;DKK;7;2;DKK
Question
Mock 1 - Solution 24
2,4 are correct.
Question
Mock 1 - Solution 25
Question
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.
Mock 1 - Solution 26
3 is correct.
Question
Mock 1 - Solution 27
2 is correct.
Question
Mock 1 - Solution 28
1,3,4 are correct.
The correct way to load enumeration default values is to call the enumeration
manager using em().
Question
Mock 1 - Solution 29
2,3 are correct.
have a look at de.hybris.platform.servicelayer.model.ModelService.
Question
Mock 1 - Solution 30
1,3 are correct.
Question
Mock 1 - Solution 31
1,3 are correct.
Question
Mock 1 - Solution 32
1 is correct.
Question
Mock 1 - Solution 33
2,3,4 are correct.
Question
Mock 1 - Solution 34
2 is correct.
Question
Mock 1 - Solution 35
4 is correct.
Question
Mock 1 - Solution 36
Question
2 is correct.
Mock 1 - Solution 37
2 is correct.
Question
Mock 1 - Solution 38
4 is correct.
Question
Mock 1 - Solution 39
3 is correct.
Question
Mock 1 - Solution 40
3,4 are correct.
Question
Mock 1 - Solution 41
1 is correct.
Question
Mock 1 - Solution 42
3 is correct.
Capture, is the action of transferring money into the merchant account after it
has been authorized.
Question
Mock 1 - Solution 43
2 is correct.
1,2 don’t respect the convent (**essentialdata*.impex**) 3 project data are not
being imported in this scenario.
Question
Mock 1 - Solution 44
1 is correct.
Question
Mock 1 - Solution 45
4 is correct.
Question
Mock 1 - Solution 46
2 is correct.
Remember that only one transaction per thread can be created.
Question
Mock 1 - Solution 47
2 is correct.
Question
Mock 1 - Solution 48
1,3 are correct.
Question
Mock 1 - Solution 49
3 is correct.
Question
Mock 1 - Solution 50
4 is correct.
Question
Mock 1 - Solution 51
2 is correct.
Question
Mock 1 - Solution 52
1 is correct.
Question
Mock 1 - Solution 53
3 is correct.
Question
Mock 1 - Solution 54
2 is correct.
Question
Mock 1 - Solution 55
1 is correct.
Question
Mock 1 - Solution 56
4 is correct.
Question
Mock 1 - Solution 57
2 is correct.
Product variants have an attribute baseProduct of type Product, so any to add
shared attributes between variants object you need to update the base product
definition.
Question
Mock 1 - Solution 58
3 is correct.
Question
Mock 1 - Solution 59
1,2,3,4 are correct.
Question
Mock 1 - Solution 60
1,3,4 are correct.
Question
Mock 1 - Solution 61
1,2,3 are correct.
Question
Mock 1 - Solution 62
4 is correct.
Question
Mock 1 - Solution 63
3 is correct.
Question
Mock 1 - Solution 64
4 is correct.
Question
Mock 1 - Solution 65
1,3 are correct.
Question
Mock 1 - Solution 66
1 is correct.
Question
Mock 1 - Solution 67
4 is correct.
1 is wrong since SAP Hybris V6 Apache SOLR is running in its own process.
Question
Mock 1 - Solution 68
2 is correct.
Question
Mock 1 - Solution 69
3 is correct.
4 is wrong, persistence is mandatory.
Question
Mock 1 - Solution 70
2,3,4 are correct.
Question
Mock 1 - Solution 71
3 is correct.
Question
Mock 1 - Solution 72
4 is correct.
A bean shell script can be executed from an impex script but an update need a
unique identifier.
Question
Mock 1 - Solution 73
1 is correct.
Question
Mock 1 - Solution 74
1,2,3 are correct.
Question
Mock 1 - Solution 75
3,4 are correct.
Question
Mock 1 - Solution 76
3 is correct.
Question
Mock 1 - Solution 77
4 is correct.
Missing start=“startAction” name=“processName”
processClass=“Process.Class”
Question
Mock 1 - Solution 78
1,4 are correct.
You don’t have to provide a controller, if none is provided the
DefaultCMSComponentController is used.
Question
Mock 1 - Solution 79
4 is correct.
Question
Mock 1 - Solution 80
3 is correct.
Question
Chapter 13
Mock exam 2
Questions
Mock 2 - Question 1
What describe best the JALO layer ?
1. means Jakarta Logic
2. mix data and business logic
3. it’s a piece of the service layer
4. JALO classes are generated during runtime
Solution
Mock 2 - Question 2
For the following query to be imported successfully what changes need to be done
?
1 $productCatalog=apparelProductCatalog
2 $productCatalogName=Apparel Product Catalog
3
4 INSERT_UPDATE ApparelProduct;code;$catalogVersion;unit(code);
supercategories(code,$catalogVersion)
5 ;300441142;;pieces;Blue Tomato,caps
217
4. use the type Product instead of ApparelProduct
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
Solution
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
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
Solution
Mock 2 - Question 6
Why does the rule engine (used by the promotion engine) include a versioning
and archiving mechanism ?
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
Solution
Mock 2 - Question 7
What is wrong with the following item type definition ?
1 <itemtype code="Subscription" extends="GenericItem">
2 <attributes>
3 <attribute type="java.lang.String" qualifier="code">
4 <persistence type="property" />
5 <modifiers unique="true"/>
6 </attribute>
7 </attributes>
8 <indexes>
9 <index name="codeIdx">
10 <key attribute="code"/>
11 </index>
12 </indexes>
13 </itemtype>
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
Solution
Mock 2 - Question 9
What steps you need to have to fulfill in order to create a new cronjob ?
1. create a new cron job expression from Spring
2. implement a job
3. create a new item type extending CronJob
4. add the new cronjob in your local.properties
Solution
Mock 2 - Question 10
What statements are false about catalogs synchronization ?
1. only existing items can be updated
2. no items can be deleted
3. all item types are being synchronized
4. the same catalog can a target and a source
Solution
Mock 2 - Question 11
Cached data are removed from the cache when ?
1. the cache is full
2. a cache invalidation notification is received from another node
3. an item is created
4. an item is removed
Solution
Mock 2 - Question 12
What statements are true about classification ?
1. classification is horizontal unlike categorization which is vertical
2. a product can be classified by only one classification attribute
3. classification is not being used by SAP Hybris because its model type
definition is flexible
4. classification is not compatible with SOLR
Solution
Mock 2 - Question 13
What can you do from an addon ?
1. add front end files (JSP, HTML, CSS and Javascript)
2. generate or customize the data model
3. declare new Spring Services or Facades or customize existing
4. declare new Controllers or customize existing
Solution
Mock 2 - Question 14
What configuration file has the highest priority ?
1. project.properties from the platform extension
2. advanced.properties from the platform extension
3. local.properties from the config extension
4. local.properties from the custom extension
Solution
Mock 2 - Question 15
When you create the following item type A what classes are being generated ?
1 <itemtype code="A" extends="ItemB" generate="false">
2 <attributes>
3 <attribute type="java.lang.String" qualifier="code">
4 <persistence type="property" />
5 <modifiers unique="true"/>
6 </attribute>
7 </attributes>
8 </itemtype>
1. A.java
2. GeneratedA.java
3. AJalo.java
4. AModel.java
Solution
Mock 2 - Question 16
When configuring the Apache SOLR indexer mode what does DIRECT means
?
1. access the embedded Apache SOLR server
2. send request to Apache SOLR using its REST API
3. all index operations would be made directly on the index
4. all index operations would be made on a temporary index before indexes
are switch
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
2. yes using allowed.extensions and forbidden.extensions inside a tenant
specific configuration file
3. yes using .allowed.extensions and .forbidden.extensions inside your
configuration
4. no, SAP Hybris is not compatible with this
Solution
Mock 2 - Question 18
How do you install a new addon ?
1. add the addon inside your localextensions.xml
2. add the addon under external-dependencies.xml
3. use the ant target addoninstall
4. use the ant target syncaddons
Solution
Mock 2 - Question 19
Is this a valid Flexible Search Query ?
1 select {p.description[fr]:o} from {Product as p} where {p:pk} in
2 ( {{ select {p:pk} from {product as p} where {p:code} like '%0%' }} )
1. no
2. yes if we delete :o
3. yes if we delete the whole where statement
4. yes
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
2. from the backoffice open the asm perspective
3. go to the /asmcockpit
4. go to the /cscockpit
Solution
Mock 2 - Question 21
How can you initialize SAP Hybris ?
1. using ant initialize
2. from the HAC
3. from the HMC
4. from the backoffice
Solution
Mock 2 - Question 22
What is highest B2B organization block ?
1. company
2. unit
3. division
4. region
Solution
Mock 2 - Question 23
In order to force a product to be listed on top of a give category, what out of the
box features should you use ?
1. boost rules
2. hero rules
3. hero products
4. top products
Solution
Mock 2 - Question 24
What payment steps is described by the following definition ?
1 Transfer back money to a customer account, the transfer not being
associated with any order or previous transactions.
1. capture
2. stand alone refund
3. capture
4. refund
Solution
Mock 2 - Question 25
The BTG module is used to ?
1. personalize a web applications based on customers
2. business to groups
3. provides a upgraded version of the CMS cockpit
4. add business targets accessible from the backoffice
Solution
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
Solution
Mock 2 - Question 27
What Spring context has the larger scope ?
1. web context
2. core context
3. shared context
4. international context
Solution
Mock 2 - Question 28
During an Impex import what will happen when the import process can’t find a
reference to an item type ?
1. import process will fail and move onto the next file
2. the value line would be ignored
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
Solution
Mock 2 - Question 29
When loading available prices what is the price factory trying to match ?
1. customer / customer group
2. product / product group
3. date range if any configured
4. promotion / promotion group
Solution
Mock 2 - Question 30
What is the problem with the following business process action ?
1 package com.hybhub.core.process.action;
2
3 import de.hybris.platform.core.model.order.OrderModel;
4 import de.hybris.platform.orderprocessing.model.OrderProcessModel;
5 import de.hybris.platform.processengine.action.
AbstractSimpleDecisionAction;
6 import de.hybris.platform.servicelayer.model.ModelService;
7 import de.hybris.platform.task.RetryLaterException;
8
9 import javax.annotation.Resource;
10
11
18 @Override
19 public Transition executeAction(final OrderProcessModel
orderProcess) throws RetryLaterException, Exception
20 {
21 OrderModel order = orderProcess.getOrder();
22
23 if(order!= null){
24 order.setNet(Boolean.TRUE);
25 modelService.save(order);
26 return Transition.OK;
27 }
28
29 return null;
30 }
31
32 }
Solution
Mock 2 - Question 31
What is true about the DefaultCMSComponentController* controller ?*
1. it will inject all attributes into the model
2. it will inject all front-end attributes (non system) into the model
3. it is used by default if no specific controller are implemented
4. it should be avoided
Solution
Mock 2 - Question 32
What is true about the following log extracted from the build process ?
1 [echo] catalog->(validation,commons) 6.0.0.0-SNAPSHOT [p*cib]
Solution
Mock 2 - Question 33
Choose the correct user rights definition to complete the following import query.
1 $START_USERRIGHTS
2 Type;UID;MemberOfGroups;Password;Target;read;change;create;delete;
change_perm
3 UserGroup;employeegroup;;
4 <Choose the right answer to complete this>
5 $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
Solution
Mock 2 - Question 34
Which of the following components are deprecated ?
1. cockpit framework
2. Jalo layer
3. task engine
4. service layer
Solution
Mock 2 - Question 35
What is the correct way of configuring a new logger for the package
com.hybhub.hybhubaddon* ?*
1.
1 log4j.logger.com.hybhub.hybhubaddon = info
2.
1 log4j.logger.hybhub.name = com.hybhub.hybhubaddon
2 log4j.logger.hybhub.level = info
3 log4j.logger.hybhub.appenderRef.stdout.ref = STDOUT
3.
1 log4j2.logger.hybhub.name = com.hybhub.hybhubaddon
2 log4j2.logger.hybhub.level = info
3 log4j2.logger.hybhub.appenderRef.stdout.ref = STDOUT
4.
1 log4j2.logger.com.hybhub.hybhubaddon = info
2 log4j2.logger.com.hybhub.hybhubaddon = STDOUT
Solution
Mock 2 - Question 36
The OCC webservices are ?
1. restful API
2. restless API
3. soap API
4. oAuth API
Solution
Mock 2 - Question 37
What statements are wrong about converters ?
1. they all have the same bean parent abstractPopulatingConverter
2. they contain a list of attributes to convert
3. they contain a list a populators to call
4. they are un-aware of the object type they are converting
Solution
Mock 2 - Question 38
What is wrong with the following extensioninfo.xml* file ?*
1 <extensioninfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="extensioninfo.xsd">
2 <extension abstractclassprefix="Generated" classprefix="
HybhubFacades" name="hybhubfacades">
3 <requires-extension name="hybhubfacades"/>
4 <requires-extension name="hybhubcore"/>
5 <coremodule generated="true" manager="de.hybris.platform.jalo
.extension.GenericManager" packageroot="com.hybhub.
facades"/>
6 </extension>
7 </extensioninfo>
Solution
Mock 2 - Question 39
Is the following dynamic attribute handler correct ?
1 package com.hybhub.core.model.dynamic;
2
3 import de.hybris.platform.core.model.product.ProductModel;
4 import de.hybris.platform.servicelayer.model.attribute.
DynamicAttributeHandler;
5
15 }
Solution
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
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
Solution
Mock 2 - Question 42
What is the following Spring configuration doing ?
1 <context:annotation-config/>
2 <context:component-scan
3 base-package="...,..."
4 scope-resolver="..."/>
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
Solution
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
2. separates application’s concerns
3. hides the complexities of the system and provides a simplified interface to
the client
4. add new functionality to an existing object without altering its structure
Solution
Mock 2 - Question 45
Select the existing Impex header mode.
1. INSERTED
2. UPDATE_INSERT
3. REMOVE
4. DELETE
Solution
Mock 2 - Question 46
How could you configure a new hot folder ?
1. from the HAC
2. from the HMC
3. from the import cockpit
4. from a Spring config file
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 Interceptor interface
3. run a system update
4. add a Spring bean mapping the item type and the Interceptor
implementation
Solution
Mock 2 - Question 48
A checkout step has ?
1. checkoutGroup reference
2. checkoutStepValidator reference
3. transitions map
4. progressBarId string
Solution
Mock 2 - Question 49
What are are valid legacy cockpit areas ?
1. navigation
2. item
3. browser
4. editor
Solution
Mock 2 - Question 50
When running an initialization on one tenant SAP Hybris will ?
1. delete all tables
2. delete all known tables
3. delete all known tables starting with the tenant table prefix
4. delete and recreate the database
Solution
Mock 2 - Question 51
When creating a new item how do you generate a new primary key ?
1. using java.util.UUID.randomUUID()
2. using the primaryKeyService
3. primary keys creation is automatically handled by the database
4. primary keys creation is automatically handled by the service layer
Solution
Mock 2 - Question 52
How could you declare configure an attribute to be encrypted ?
1.
1 <attribute qualifier="sensible" autocreate="true" type="java.lang.
String">
2 <persistence type="property"/>
3 <modifiers encrypted="true"/>
4 </attribute>
2.
1 <attribute qualifier="sensible" autocreate="true" type="encrypted:
java.lang.String">
2 <persistence type="property"/>
3 </attribute>
3.
1 <attribute qualifier="sensible" autocreate="true" type="java.lang.
String">
2 <persistence type="property" encrypted="true"/>
3 </attribute>
4.
1 <attribute qualifier="sensible" autocreate="true" type="java.lang.
String">
2 <modifiers type="property" encrypted="true"/>
3 </attribute>
Solution
Mock 2 - Question 53
Which item types exist ?
1. collectiontype
2. enumtype
3. atomictype
4. listtype
Solution
Mock 2 - Question 54
A customer segment could be executed in ?
1. optimized processing
2. full processing
3. jalo processing
4. complete processing
Solution
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
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
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
2. to boost configured words while searching
3. to stop the query after a configured word
4. to split the query in two queries
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
Solution
Mock 2 - Question 59
How could you improve the following code (groovy) ?
1 import de.hybris.platform.processengine.enums.ProcessState
2
9 businessProcessService.startProcess(process)
10
11 modelService.refresh(process)
12 if(ProcessState.SUCCEEDED != process.getProcessState()){
13 businessProcessService.startProcess(process)
14 }
1. use the method T startProcess(String arg0, String arg1); to create a
process
2. delete the second call trying to start the business process
3. delete the useless call to save
4. generate a unique identifier for the business process
Solution
Mock 2 - Question 60
What statements are true about the following table (SQL DDL for HSQL) ?
1 CREATE CACHED TABLE b2bbudgetslp
2 (
3 ITEMPK BIGINT,
4 ITEMTYPEPK BIGINT,
5 LANGPK BIGINT,
6 p_name NVARCHAR(255),
7 PRIMARY KEY (ITEMPK, LANGPK)
8 );
Solution
Mock 2 - Question 61
Why would you use classification ?
1. to optimize Apache SOLR requests
2. to have dynamic product features
3. to speed up search
4. to unify product and category attributes
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
Solution
Mock 2 - Question 63
What statements are wrong about extensions ?
1. they have to be inside the bin folder
2. they need to have a dependency to yempty
3. they can written using Groovy
4. they are always automatically loaded
Solution
Mock 2 - Question 64
What statements are true about the SAP Hybris server ?
1. based on Apache Tomcat
2. good for production
3. compatible with EJB
4. can be started from the command line
Solution
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
2. you are using the service layer
3. you are using the jalo layer
4. import relaxed is activated
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
3. perform an inventory once per week at midnight
4. any task that isn’t database related, cronjobs are designed to perform
operating System tasks, not database system tasks
Solution
Mock 2 - Question 67
Content slots for page template are ?
1. place holder for CMS component
2. place holder for JSP tags
3. shared across all pages using the page template
4. configured on the JSP view page
Solution
Mock 2 - Question 68
Which bean would be loaded from getBean(“bean”)* ?*
1 <bean name="stringBean" class="java.lang.String" >
2 <constructor-arg><value>my String Name</value></constructor-arg>
3 </bean>
4
5 <bean id="stringBean" class="java.lang.String" >
6 <constructor-arg><value>my String ID</value></constructor-arg>
7 </bean>
8
9 <alias name="stringBean" alias="bean" />
1. my String Name
2. my String ID
3. a new String
4. none
Solution
Mock 2 - Question 69
Is it possible to add new enumeration values by runtime ?
1. no
2. yes if you are using JRebel
3. yes if the enumeration is dynamic
4. yes if the enumeration is a subtype of the HybrisEnumValue class
Solution
Mock 2 - Question 70
What a POS is ?
1. a warehouse
2. a physical store
3. a web store
4. a geolocalization service
Solution
Mock 2 - Question 71
What statements are wrong about Backoffice widgets ?
1. widget can extend each other
2. widget ids must be unique or the compilation fails
3. views are implemented using JSP tags
4. widgets can have parameters
Solution
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
2. the test class should extend ServicelayerTest
3. use Mockito to stub dependencies
4. wrap all tests inside a transaction
Solution
Mock 2 - Question 73
What is the notification framework used for ?
1. notify cockpit users
2. notify customers
3. notify administrators
4. facade for the event service
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
3. a base store is attached to a single warehouse
4. a product can be sold even if it has no stock
Solution
Mock 2 - Question 75
The CS cockpit was designed for ?
1. customer segment management
2. order life cycles management
3. css rendering management
4. customer security management
Solution
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
Solution
Mock 2 - Question 77
Choose the flexible query which has generated the following SQL query ?
1 SELECT item_t0.PK, item_t1.p_code
2 FROM products item_t0 LEFT JOIN medias item_t1
3 ON item_t1.PK = item_t0.p_logo
4 WHERE ((item_t0.TypePkString=? AND (item_t1.TypePkString IS NULL OR
( item_t1.TypePkString=? ) )))
Mock 2 - Question 78
What service should you use to save an model ?
1. persistenceService
2. jaloService
3. serviceLayerService
4. modelService
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
Solution
Mock 2 - Question 80
By default when you load an item from the service what is fetched inside the
object ?
1. nothing all attributes are lazy loaded
2. only literal values
3. only references values
4. all
Solution
Solutions
Mock 2 - Solution 1
1,2 are correct.
Question
Mock 2 - Solution 2
2,3 are correct.
Question
Mock 2 - Solution 3
1 is correct.
Question
Mock 2 - Solution 4
3 is correct.
Question
Mock 2 - Solution 5
3 is correct.
Question
Mock 2 - Solution 6
2 is correct.
Question
Mock 2 - Solution 7
4 is correct.
Question
Mock 2 - Solution 8
1,3,4 are correct.
Question
Mock 2 - Solution 9
2,3 are correct.
Question
Mock 2 - Solution 10
1,2,3 are correct.
Question
Mock 2 - Solution 11
1,2,4 are correct.
Question
Mock 2 - Solution 12
1 is correct.
Question
Mock 2 - Solution 13
1,2,3,4 are correct.
Question
Mock 2 - Solution 14
3 is correct.
Question
Mock 2 - Solution 15
4 is correct.
generate=“false” means that Jalo classes won’t be generated.
Question
Mock 2 - Solution 16
3 is correct.
Question
Mock 2 - Solution 17
2 is correct.
Question
Mock 2 - Solution 18
3 is correct.
Question
Mock 2 - Solution 19
4 is correct.
Question
Mock 2 - Solution 20
1 is correct.
Question
Mock 2 - Solution 21
1,2 are correct.
Question
Mock 2 - Solution 22
2 is correct.
Question
Mock 2 - Solution 23
3 is correct.
Question
Mock 2 - Solution 24
2 is correct.
Question
Mock 2 - Solution 25
1 is correct.
Question
Mock 2 - Solution 26
3 is correct.
The installer is not an ant target. extgen would generate a single extension while
here we need to generate a whole new project.
Question
Mock 2 - Solution 27
2 is correct.
Web contexts are contained within a core context (one per tenant), the two
other contexts are not valid.
Question
Mock 2 - Solution 28
3 is correct.
Question
Mock 2 - Solution 29
1,2,3 are correct.
Question
Mock 2 - Solution 30
1 is correct.
Question
Mock 2 - Solution 31
2,3 are correct.
Question
Mock 2 - Solution 32
1,2,4 are correct.
Question
Mock 2 - Solution 33
3 is correct.
Question
Mock 2 - Solution 34
1,2 are correct.
Question
Mock 2 - Solution 35
3 is correct.
Question
Mock 2 - Solution 36
1 is correct.
Question
Mock 2 - Solution 37
2,4 are correct.
Question
Mock 2 - Solution 38
4 is correct.
Question
Mock 2 - Solution 39
2 is correct.
Question
Mock 2 - Solution 40
1,3 is correct.
Question
Mock 2 - Solution 41
3 is correct.
Question
Mock 2 - Solution 42
2 is correct.
Question
Mock 2 - Solution 43
1 is correct.
Question
Mock 2 - Solution 44
3 is correct.
Question
Mock 2 - Solution 45
3 is correct.
Question
Mock 2 - Solution 46
4 is correct.
Question
Mock 2 - Solution 47
2,3 are correct.
Question
Mock 2 - Solution 48
1,2,3,4 are correct.
Question
Mock 2 - Solution 49
1,3,4 are correct.
Question
Mock 2 - Solution 50
3 is correct.
Question
Mock 2 - Solution 51
4 is correct.
Question
Mock 2 - Solution 52
1 is correct.
Question
Mock 2 - Solution 53
1,2,3 are correct.
Question
Mock 2 - Solution 54
1,2 are correct.
Question
Mock 2 - Solution 55
2 is correct.
Question
Mock 2 - Solution 56
1,3 are correct.
Question
Mock 2 - Solution 57
1 is correct.
Question
Mock 2 - Solution 58
1,4 are correct.
Question
Mock 2 - Solution 59
1,2,3 are correct.
Question
Mock 2 - Solution 60
3 is correct.
Question
Mock 2 - Solution 61
2 is correct.
Question
Mock 2 - Solution 62
2 is correct.
Question
Mock 2 - Solution 63
3 is correct.
Have a look at the extension template ygroovy.
Question
Mock 2 - Solution 64
1,2,4 are correct.
Question
Mock 2 - Solution 65
2 is correct.
Question
Mock 2 - Solution 66
1,3 are correct.
Question
Mock 2 - Solution 67
1,3 are correct.
Question
Mock 2 - Solution 68
4 is correct.
Question
Mock 2 - Solution 69
3,4 are correct.
Question
Mock 2 - Solution 70
2 is correct.
Question
Mock 2 - Solution 71
3 is correct.
Question
Mock 2 - Solution 72
3 is correct.
Question
Mock 2 - Solution 73
2 is correct.
Question
Mock 2 - Solution 74
1,2,4 are correct.
Question
Mock 2 - Solution 75
2 is correct.
Question
Mock 2 - Solution 76
2 is correct.
Question
Mock 2 - Solution 77
3 is correct.
Question
Mock 2 - Solution 78
4 is correct.
Question
Mock 2 - Solution 79
4 is correct.
Question
Mock 2 - Solution 80
1 is correct.
Question