* 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.
Hi Harish,
ReplyDeletei am unable to add new attribute to RegisterForm.java which is you have specified in Step 6. When i am adding new attribute called dob to my RegisterForm.java and do ant all it is getting deleted. i am adding it in the RegisterForm.java of My custom storefront extension.
Can you help me on this how to resolve it.
Thanks,
Shankar.