You are on page 1of 22

Interceptors

INTERNAL – SAP and Partners Only


Preparation for the Trail

§ Version 2211 of commerce

§ Installed and initialized using a recipe with at least one b2c shop
- e.g. cx (OOTB) or live_sessions_dev (provided by trainer)

2
Interceptors: Overview

§ Interceptors allow you to alter the course of a Model’s life cycle


§ An interceptor targets one or more aspect of a Model's life cycle
§ With interceptors, you can modify a Model or throw an exception
to interrupt the current operation
– For instance, a value may be validated before saving a Model
§ An interceptor is registered as a Spring bean

3
Lifecycle of a Model
Model Instantiate a Model
Runtime
Create new Model

modelService.create(XyzModel.class);
Modify Model Values
InitDefaultsInterceptor
modelService.initDefaults();

XyzModel myXyz = new XyzModel();


Save Model Values
PrepareInterceptor
Load from Database
ValidateInterceptor
LoadInterceptor

ModelService
modelService.remove()
modelService.get() modelService.save()
RemoveInterceptor

Database 4
Implementing Interceptors
Implementing an Interceptor

§ To define an interceptor class, implement one or more of the following interfaces:


- A LoadInterceptor is called whenever a model is loaded from the database
- An InitDefaultsInterceptor is called to populate a model with default values
- A PrepareInterceptor is called before a model is saved to the database
but before it is validated by any ValidateInterceptor
- A ValidateInterceptor is called before a model is saved to the database
and after it has been prepared by a PrepareInterceptor
- A RemoveInterceptor is called before an model is removed from the database

6
Implementation: Registering an Interceptor

§ After implementing an interceptor, it is registered as a Spring bean in myextension-spring.xml:


<bean id="myLoadInterceptor"
class="my.package.MyLoadInterceptor"/>

public class MyLoadInterceptor implements LoadInterceptor<CustomerModel>


{
public void onLoad(CustomerModel model, InterceptorContext ctx)
throws InterceptorException
{
...
}
}

7
Implementation – mapping the interceptor

§ The interceptor is then mapped in myextension-spring.xml:

<bean id="myLoadMapping"
class="de.hybris.platform.servicelayer.interceptor.impl.InterceptorMapping">

<property name="interceptor" ref="myLoadInterceptor"/>


<property name="typeCode" value="Customer"/>
<property name="order" value="1"/>
<property name="replacedInterceptors"
ref="existingInterceptorA,existingInterceptorB"/>
</bean>

The Interceptor with the lowest number is called first.

If this property is not set, the highest integer number is used by


default.
If two or more interceptors have the same order value, then the
exact order in which these interceptors trigger is not deterministic 8
Interceptor Context
InterceptorContext: Overview

A context object passed to the execute method of every interceptor implementation

One important function: register a model instance with the interceptor for operation to be performed

ctx.registerElementFor(modelA, PersistenceOperation.SAVE)

ctx.registerElementFor(modelA, PersistenceOperation.DELETE)

A good example is to generate audit entry for removed item


10
InterceptorContext: an Example

(Assume the type, UserAuditEntry, has been defined in *-items.xml )


To create a new UserAuditEntry item whenever a User is removed:
public class AuditingUserRemoveInterceptor implements RemoveInterceptor<UserModel> {

@Override
public void onRemove(UserModel user, InterceptorContext ctx)
throws InterceptorException
{
final UserAuditEntryModel userAuditEntry =
ctx.getModelService().create( UserAuditEntryModel.class );
userAuditEntry.setChangeTimestamp( new Date() );
userAuditEntry.setDisplayName( user.getDisplayName() );
userAuditEntry.setName( user.getName() );
userAuditEntry.setUid( user.getUid() );
//register item for SAVE operation
ctx.registerElementFor(userAuditEntry, PersistenceOperation.SAVE);
}
}
Registering an item for a persistence operation is preferred over to modelService.save()
n Because the involved models can be tracked within the intercepting process
11
InterceptorContext: Additional Functions

§ Check whether the given model is already registered with a certain operation
E.g. to see if a modelA is already registered for deletion:

ctx.contains(modelA, PersistenceOperation.DELETE);

§ Get all models registered for a certain operation


E.g. to get all models that are to be deleted:

ctx.getElementsRegisteredFor( PersistenceOperation.DELETE );

12
Disabling Interceptor
Disabling Interceptors

§ This option can be used for relaxing certain constraints imposed on a data model in data
integration scenarios, or for performance reasons.

§ Interceptors can be disabled


- Using API by calling the sessionService.executeInLocalViewWithParams() method
- In ImpEx (e.g.: INSERT_UPDATE Currency [disable.interceptor.types=VALIDATE]; isocode...)

§ There are 3 system properties that allow you to disable specific interceptors
- disable.interceptor.beans
(takes comma-separated list of Spring bean IDs)
- disable.interceptor.types
(takes comma-separated list of InterceptorType Enum values:
INIT_DEFAULTS, LOAD, PREPARE, REMOVE, VALIDATE)
- disable.UniqueAttributesValidator.for.types
(takes comma-separated list of Commerce item types)

UniqueAttributeValidator is a validation interceptor, which is used to validate for any Model if


the unique keys for this model are unique in the database
14
Disabling Interceptors: Programmatically

§ Disable all validate interceptors when saving a currency model:

15
Disabling Interceptors: ImpEx

§ Disable a specific interceptor with the id validateCurrenceyDataInterceptor:

INSERT_UPDATE
Currency[disable.interceptor.beans='validateCurrencyDataInterceptor'];isocode[unique=true];symbol;digits;
;bitcoin ;$ ;-2 ;

16
Interceptor Best Practices
Interceptors: Best Practice I
Naming Conventions

– Prefix the interceptor's name by the type it is intercepting.


Suffix it by the interface it implements.
E.g. CustomerPrepareInterceptor
– The Interceptor classes should be placed in a package called interceptor/interceptors
– The bean id should be the same as the class name but start with a lowercase letter,
to indicate it will be a runtime instance, e.g.:
<bean id="customerPrepareInterceptor”
class="de.hybris.abc.interceptors.CustomerPrepareInterceptor”

18
Interceptors: Best Practice II
§ Avoid multiple interceptors have same order value

§ Use the correct interceptor for the job, e.g.:


– PrepareInterceptor should not validate values/models

– ValidateInterceptor should not change values/models

§ Keep performance in mind:

– Avoid too-complicated logic in interceptor implementation


▫ Especially when intercepting a type with a large number of models
– Avoid duplicated code execution
▫ e.g. when intercepting products during synchronization (Staged and Online)
– Disable interceptors before CRUD if necessary

▫ If you know interceptor logic are not needed during that CRUD operation
19
Interceptors Exercise
References

Introduction:

Interceptors | SAP Help Portal

Disabling Interceptors:

Disabling Interceptors | SAP Help Portal

Interceptor best practices:

Create Interceptors | SAP Help Portal

21
Thank you.

© 2023 SAP SE or an SAP affiliate company. All rights reserved. See Legal Notice on www.sap.com/legal-notice for use terms, disclaimers, disclosures, or restrictions related to SAP Materials for general audiences.

You might also like