Sunday, 30 August 2015

Dynamic Attribute in hybris with example


Use Dynamic Attributes to define attributes that values are not persisted in a database. 
Let us learn the concept by doing real time task like giving date of birth during registration 
will get the age dynamically generated for user. 
Define the Dynamic attribute in the items.xml file
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>
As Customermodel is not a new Item type the generate and autocreate variables for item is false.
 For dynamic attributes we have attributeHandler variables which is to be set to the bean id of class 
which is implementing Dynamic AttributeHandler interface.
Add the DynamicAgeHandler class in **facades extension.
public class DynamicAgeHandler implements DynamicAttributeHandler<Integer, CustomerModel>
{
public static int age = 0;

@Override
public Integer get(final CustomerModel model)
{
try
{
final Date date = model.getDob();
final Calendar cal = Calendar.getInstance();
cal.setTime(date);
final int year = cal.get(Calendar.YEAR);
final int year1 = Calendar.getInstance().get(Calendar.YEAR);
age = year1 - year;
}
catch (final Exception e)
{
e.printStackTrace();
}
return Integer.valueOf(age);
}
@Override
public void set(final CustomerModel model, final Integer val)
{
// YTODO Auto-generated method stub
if (val != null)
{
throw new UnsupportedOperationException();
}
}
}
In **facade-springs.xml create a bean id for above class

<bean id="dynamicAgeHandler" class="com.facades.attributehandler.DynamicAgeHandler"></bean>
During registration we need to store D.O.B attribute so we add the age and dob in register data.
For Registerdata add 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>

Do Ant clean all to generate and add new attributes to model.
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 label for dob..

register.dob    = Date of Birth

In Registration.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;
}
In LoginPageController.java add your own attribute by getting the  
  values from form and set into RegisterData object in 
  processRegisterUserRequest() method.
  --------------------------------------------------------------
   data.setDob(form.getDob());

If only the above case is not working..

Some times the newly added dob field in form is not forwarded to super class. 
So it may cause error if the date field in not moving so print it in processregisteruserrequest method.. 
If It is getting null values then try to override this method in LoginPageController.java..
LOginpageController.java

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String doRegister(@RequestHeader(value = "referer", required = falsefinal 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 modelfinal 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);
}

In DefaultCustomerFacade.java, in register() method add your 
   Attribute.
   ------------------------------------------------------------
   newCustomer.setDob(registerData.getDob());

To get the details of current user CustomerModel we create a class in facades

DynamicCusAge.java
public class DynamicCusAge
{
@Autowired
private UserService userService;
protected UserService getUserService()
{
return userService;
}
@Required
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;
}
}

In **facade-springs.xml create a bean id for above class

<bean id="dynamicCusAge" class="com.facade.impl.DynamicCusAge">
<property name="userService" ref="userService"/>

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();
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);
}
In accountprofilepage.jsp
   --------------------------
   <tr>
<td><spring:theme code="profile.age" text="Age"/></td>
<td>${age} years</td>
</tr>

1 comment:

  1. very good explanation. can you please post promotion customization example

    ReplyDelete