* We Use Dynamic Attributes to define attributes whose values are not persisted in a database.
Dynamic attribute has some key features:-
· The persistence type is set to dynamic
· The attributeHandler points to a bean that must handle the DynamicAttributeHandler
interface
· The write attribute is set to false, and therefore the attribute is read-only
UseCase:-
Calculate age based on date of birth. Here Age attribute is not present in DB. But we can calculating using Dynamic attribute.
==============================================================
Step 1:- Add the attributes date of birth and age to customer model in *core-items.xml.
<itemtype code="Customer" autocreate="false" generate="false">
<attributes>
<attribute type="java.util.Date" qualifier="dob">
<persistence type="property"></persistence>
<modifiers read="true" write="true" optional="true"/>
</attribute>
<attribute type="java.lang.Integer" qualifier="age">
<persistence type="dynamic" attributeHandler="dynamicAgeHandler"></persistence>
<modifiers read="true" write="true" optional="true"/>
</attribute>
</attributes>
</itemtype>
|
Step 2:-
For dynamic attributes, we have the attributesHandler property which is to be set to the bean id of the class which is implementing DynamicAttributeHandler interface.
* we have to create a class
package com.training.facades.attributehandler;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.servicelayer.model.attribute.DynamicAttributeHandler;
import java.util.Calendar;
import java.util.Date;
public class DynamicAgeHandler implements DynamicAttributeHandler<Integer, CustomerModel>
{
public static int age = 0;
@Override
public Integer get(final CustomerModel model)
{
try
{
System.out.println("***** Before date1 :");
final Date date = model.getDob();
System.out.println("************************" + date);
final Calendar cal = Calendar.getInstance();
cal.setTime(date);
final int year = cal.get(Calendar.YEAR);
System.out.println(year);
final int year1 = Calendar.getInstance().get(Calendar.YEAR);
System.out.println(year1);
age = year1 - year;
System.out.println("***** age :" + age);
}
catch (final Exception e)
{
e.printStackTrace();
}
return Integer.valueOf(age);
}
@Override
public void set(final CustomerModel model, final Integer val)
{
if (val != null)
{
throw new UnsupportedOperationException();
}
}
}
|
Step 3:-
In **facade-springs.xml create a bean for above class
<bean id="dynamicAgeHandler" class="com.training.facades.attributehandler.DynamicAgeHandler"></bean>
Step 4:-
For Registerdata add a new field in *facades-beans.xml
<bean class="de.hybris.platform.commercefacades.user.data.RegisterData">
<property name="age" type="java.lang.String"/>
<property name="dob" type="java.util.Date"/>
</bean>
Ant clean all to clean and build with newly added fields.
Step 5:-
In register.tag add fields for getting the value from and store into
DB.
---------------------------------------------------------------
<formElement:formInputBox idKey="register.dob" labelKey="register.dob" path="dob" inputCSS="text" mandatory="true"/>
IN base-en.properties in storefront add a label for dob.
register.dob = Date of Birth
Step 6:-
In RegisterForm.java add your own fields and write setter and getter
methods.
@DateTimeFormat(pattern = "dd/MM/yyyy")
private Date dob;
public Date getDob()
{
return dob;
}
void setDob(final Date dob)
{
this.dob = dob;
}
|
Step 7:-
In LoginPageController.java add your own attribute by getting the
values from form and set into RegisterData object in
processRegisterUserRequest() method.
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String doRegister(@RequestHeader(value = "referer", required = false) final String referer, final RegisterForm form,
final BindingResult bindingResult, final Model model, final HttpServletRequest request,
final HttpServletResponse response, final RedirectAttributes redirectModel) throws CMSItemNotFoundException
{
getRegistrationValidator().validate(form, bindingResult);
return processRegisterUserRequest(referer, form, bindingResult, model, request, response, redirectModel);
}
@Override
protected String processRegisterUserRequest(final String referer, final RegisterForm form, final BindingResult bindingResult,
final Model model, final HttpServletRequest request, final HttpServletResponse response,
final RedirectAttributes redirectModel) throws CMSItemNotFoundException
{
if (bindingResult.hasErrors())
{
model.addAttribute(form);
model.addAttribute(new LoginForm());
model.addAttribute(new GuestForm());
GlobalMessages.addErrorMessage(model, "form.global.error");
return handleRegistrationError(model);
}
final RegisterData data = new RegisterData();
data.setFirstName(form.getFirstName());
data.setLastName(form.getLastName());
data.setLogin(form.getEmail());
data.setPassword(form.getPwd());
data.setTitleCode(form.getTitleCode());
data.setDob(form.getDob());
System.out.println("************** data is set" + form.getDob());
try
{
getCustomerFacade().register(data);
getAutoLoginStrategy().login(form.getEmail().toLowerCase(), form.getPwd(), request, response);
GlobalMessages.addFlashMessage(redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER,
"registration.confirmation.message.title");
}
catch (final DuplicateUidException e)
{
LOG.warn("registration failed: " + e);
model.addAttribute(form);
model.addAttribute(new LoginForm());
model.addAttribute(new GuestForm());
bindingResult.rejectValue("email", "registration.error.account.exists.title");
GlobalMessages.addErrorMessage(model, "form.global.error");
return handleRegistrationError(model);
}
return REDIRECT_PREFIX + getSuccessRedirect(request, response);
}
|
Step 8:-
In DefaultCustomerFacade.java, in register() method add your Attribute.
newCustomer.setDob(registerData.getDob());
Step 9:-
To get the details of current user CustomerModel we create a class in facades
DynamicCusAge.java
package com.training.facade.impl;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.core.model.user.UserModel;
import de.hybris.platform.servicelayer.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
public class DynamicCusAge
{
@Autowired
private UserService userService;
public UserService getUserService()
{
return userService;
}
public void setUserService(final UserService userService)
{
this.userService = userService;
}
public Integer getAge()
{
final UserModel cus = getUserService().getCurrentUser();
final CustomerModel cus1 = (CustomerModel) cus;
final Integer age = cus1.getAge();
return age;
}
}
|
Step 10:-
In **facade-springs.xml create a bean id for above class
<bean id="dynamicCusAge" class="com.training.facade.impl.DynamicCusAge">
<property name="userService" ref="userService"/>
Step 11:-
Into the AccountPageController.java , in profile() method through
Your DynamicCusAge class call the method to get the age.
@Autowired
private DynamicCusAge dynamicCusAge;
....
.
.
....
@RequestMapping(value = "/profile", method = RequestMethod.GET)
@RequireHardLogIn
public String profile(final Model model) throws CMSItemNotFoundException
{
final List<TitleData> titles = userFacade.getTitles();
final CustomerData customerData = customerFacade.getCurrentCustomer();
if (customerData.getTitleCode() != null)
{
model.addAttribute("title", findTitleForCode(titles, customerData.getTitleCode()));
}
final Integer age = dynamicCusAge.getAge();
System.out.println("************ AGe:" + age);
model.addAttribute("age", age);
model.addAttribute("customerData", customerData);
storeCmsPageInModel(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
setUpMetaDataForContentPage(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
model.addAttribute("breadcrumbs", accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile"));
model.addAttribute("metaRobots", "noindex,nofollow");
return getViewForPage(model);
}
|
Step 12:-
In accountprofilepage.jsp
<h2><u>Dynamic Attribute</u></h2>
<table>
<tr>
<td><spring:theme code="profile.firstName" text="First name"/>:
<b>${fn:escapeXml(customerData.firstName)}</b></td>
</tr>
<tr>
<td><spring:theme code="profile.lastName" text="Last name"/> :
<b>${fn:escapeXml(customerData.lastName)}</b></td>
</tr>
<tr>
<td><spring:theme code="profile.age" text="Age"/> :
<b>${age} years</b></td>
</tr>
</table>
|
Step 13:-
We have to create the PageTemplate,ContentPage,contentslot,JspIncludeComponent through impex.
INSERT_UPDATE PageTemplate;$contentCV[unique=true];uid[unique=true];name;frontendTemplateName;restrictedPageTypes(code);active[default=true]
;;AccountPageTemplate;Account Page Template;account/accountLayoutPage;ContentPage
INSERT_UPDATE ContentPage;$contentCV[unique=true];uid[unique=true];name;masterTemplate(uid,$contentCV);label;defaultPage[default='true'];approvalStatus(code)[default='approved'];homepage[default='false']
;;ProfileContentPage;profile Content Page;AccountPageTemplate;profile
INSERT_UPDATE JspIncludeComponent;$contentCV[unique=true];uid[unique=true];name;page;actions(uid,$contentCV);&componentRef
;;ProfilePageComponent;Profile Page Component;accountProfilePage.jsp;;ProfilePageComponent
INSERT_UPDATE ContentSlot;$contentCV[unique=true];uid[unique=true];name;active;cmsComponents(&componentRef);;;
;;ProfilePageComponentCOntentSlot;Profile Page Component ContentSlot;true;ProfilePageComponent;;;
INSERT_UPDATE ContentSlotForPage;$contentCV[unique=true];uid[unique=true];position[unique=true];page(uid,$contentCV)[unique=true][default='ProfileContentPage'];contentSlot(uid,$contentCV)[unique=true];;;
;;ProfilePageComponentCOntentSlotPage;profile;;ProfilePageComponentCOntentSlot;;;
Step 13:-
add below code in this file AccountLayoutPage.jsp.
<div class="account-section">
<cms:pageSlot position="profile" var="feature" element="div" class="account-section-content">
<cms:component component="${feature}" />
</cms:pageSlot>
</div>
|
Note:
=> Position ‘profile’ must be same in ContentSlotForPage and AccountLayoutPage.jsp
=>Try by adding full path of jsp in JspIncludeComponent.
These are the URL's to access the electronic site with our storefront.