Java 8 | Default methods in interface

Every developer in office is instructed to write no-nonsense code. That’s a protocol.

So when there is no exception, why should every developer create their own creative ways to code. Every one should follow a consistent methodology. Let that manager of your’s define the PMDs for you. I know you will gonna hate it. But then…

It makes sense to have some non abstract methods in an interface. This may be conveniently called default implementation.

Java 8 let you do this. Now you can define a default implementation, which is available to all implementing classes.

Below is a sample.

Interface

package com.bitbyte;

public interface Developer {
	
	public void writeReadableCode();
	
	default void thinkSimple(){
		System.out.println("At bitbyte, Developers think Simple");
	}

}

Implementing class

package com.bitbyte;

public class JavaDeveloper implements Developer {

	@Override
	public void writeReadableCode() {
		System.out.println("Please write Simple and readable code");
	}
}

Client Class

package com.bitbyte;

public class Client {

	public static void main(String args[]) {

		JavaDeveloper coolDeveloper = new JavaDeveloper();
		
		// abstract method call
		coolDeveloper.writeReadableCode();
		// Non abstract method call
		coolDeveloper.thinkSimple();
	}
}

Since you always have a jackAss in team, who still want his own implementation. He can do so.


package com.bitbyte;

public class CoolDeveloper implements Developer {

	@Override
	public void writeReadableCode() {
		System.out.println("Please write Simple and readable code");
	}
	
	@Override
	public void thinkSimple() {
		
		System.out.println("I am cool myself. I know what i am doing!!!");
		
	}
}

How to submit a form to Hybris from external application

Gate crash is embarrassing, back door entry is risky. Great is to be welcomed by a friend inside the party, when you are not invited.

Recently, i came to a situation, where i wanted to submit a form to hybris from a application. I thought it would be easy, and all i need is to do a post to a URL.

Booom. It came out with a flat Bad or missing csrf value error.

Once i thought, perhaps i am trying to breach the hybris security. Since there is a contract between client (browser) and the server (hybris) to exchange information. To keep this information just between them, a shared private token is used. This token, known as csrf token, is bound to a session.

@sumitg88 talked about it one of his blog.

Bypassing a request from security layer is one thing. What i wanted was to go through the security layer, and still be able to submit a form, from outside the spring context of Hybris storefront.

I created an API in storefront, which can pass a csrf-token for the current session. The current session can be opened by application, by hitting the home page, may be in an iframe, or through a java program in backend.

Hybris forcefully adds a csrf token inside a hidden field, in every spring mvc form. You can see this happening by going to html source of a page with form. This token is actually validated against the session token to allow a request to pass to the services.

hiddenFields.put(CSRFTokenManager.CSRF_PARAM_NAME, CSRFTokenManager.getTokenForSession(request.getSession()));

In Html forms you can see:

      <input type="hidden" name="CSRFToken" value="0b4eefff-1a05-4bdb-843a-fa9598633dab">

Our API could give the same csrf token, which we can pass through our form in external application. This way, Hybris will take this request as a valid one, and we can submit the form.

The API could look like below:

      public static String getTokenForSession(final HttpSession session)
	{

		// cannot allow more than one token on a session - in the case of two requests trying to
		// init the token concurrently
		Enumeration<String> enumeration=session.getAttributeNames();
		String csrfTokenAttr=null;
		String token=null;
		while(enumeration.hasMoreElements())
		{
			String attrName=enumeration.nextElement();

			if (attrName.contains("CSRFTokenManager.tokenval"))
			{ 
				csrfTokenAttr=attrName;
			}
		}
		synchronized (session)
		{
			token = (String) session.getAttribute(csrfTokenAttr);
			if (null == token)
			{
				token = UUID.randomUUID().toString();
				session.setAttribute(csrfTokenAttr, token);
			}
		}
		return token;
	}

Once you have a valid token, from one of the session, you can submit any form smoothly.

Enjoy!!!!

Hot Deployment – Hybris

Introduction

In this tutorial I will be covering the configuration of JRebel with Hybris. With JRebel configured you will be able to modify java source classes and compile them on the fly.

“No need to build and start the server again and again”

The configuration is very simple, just 3 steps and you are good to go!

Step 1

  • Download JRebel: Archive can be downloaded from the below link http://zeroturnaround.com/software/jrebel/download/prev-releases/
  • Extract the zip file at a location of your preference, for eg: C:/jrebel
    unzip
  • Active JRebel:
    – Go inside bin folder of JRebel.
    – Start the activation utility by running “activate-gui.cmd” file.
    – It will open a Jrebel activation window. The window will contain 2 tabs:
    Try JRebel    for free and I already have a license.Choose Try JRebel for FREE and fill the basic information.

jrebelfreeform
OR
Buy a license and fill the information in the I already have a license section.

Step 2

  • Add the below given property in local.properties file
    tomcat.javaoptions=-agentpath:C:/jrebel/lib/jrebel64.dll
    ** change the version of the jrebel[XX].dll according to the machine specifications.

 Creation of rebel.xml file:
– You will be required to add the rebel.xml file in the resource folder of each extension.

rebel.png

– Create a new rebel.xml class and copy/paste the below given content into the file:

<?xml version=”1.0″ encoding=”UTF-8″?>
<application xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns=”http://www.zeroturnaround.com&#8221; xsi:schemaLocation=”http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd”&gt;
<classpath>
<!– Make sure to replace Absolute_Path with your concrete values –>
    <dir name=”{Absolute_Path}/classes”/>
</classpath>
</application>

**   The absolute path should be the complete path to the classes folder.
Example: C:/hybris/bin/custom/demo/demofacades/classes

***The classes folder is the compiled source folder of Hybris and not IDE’s(eclipse).

Step 3

  • Change the IDE(eclipse) compile output path in “.classpath” file of the extension.classpath.png
    TO
    classpath1.png
    Path structure:
    path.png
    All the configurations are completed.You just need to recompile the code from IDE(eclipse) after making the changes in the Java source file.For Eclipse you need to do the below mentioned step:

    • Just go to Project -> Clean
    • Select “Clean projects selected below” option and select the extensions which contains the modified java source classes.
    • Select “Start build immediately”.
    • Select “Build only the selected projects”.
    • Press OK and you are done!

Load balancing configurations for SAP Hybris

As mentioned in one of my previous post if not setup correctly clustered environment can be a nightmare. Below are some of the configurations worth noting beforehand:

Server Affinity: a lost session

An HTTP (s) session should always be served by only one SAP Hybris application server otherwise session will be lost and user would need to re-login, even worse anonymous user will lose his cart and all other settings. To avoid this embarrassing experience, enable Sticky Session at application load balancing layer which will stick one session to one SAP hybris server.

Redirect rules: 

Very often redirect rules are defined at load balancing layer to redirect complete URL (base + context )-e.g. http://doodle.com/fun to base URL  e.g. http://doodle.com.

Here one exception should be medias because their urls are appended with /medias at end of base URL and redirecting these URLs to base URL wont load medias:

eg. a call to medias URL –  e.g. http://doodle.com/medias/abc/456789.jpg will be replace with http://doodle.com which will fail loading of medias into SAP Hybris applications.

 

 

Production Infrastructure for SAP Hybris

What is an ideal production server setup? How many servers, cores or nodes do you or customer need?

A production system should not be “it works” but it should be a full-fledged performance setup.

The production setup really varies from customer to customer but in general: one BackOffice server with couple of storefront servers along with webservers, solr servers and a load balancer is very standard infrastructure.

prod-setup

Measurement Metric:

Hybris gauges its performance with page impressions/ second/ core. Standard hybris accelerator comes with a ballpark 10-15 page impressions/second/core. Here fun part is – most of projects start with 1-2 pi/s/core and there can be seriously optimized applications where >50 pi/s/core can be found.

So it’s advised to analyse customer’s requirements with representative data rather than proposing a typically standard infrastructure setup.

 

 

 

What are component type group in Hybris?

Not everything is for everyone. This simple law of nature binds everything together. A polar beer is best kept away tropical area. Your business may want to keep only coordinated banners in rotating image banners. The content slots are bounded to have only few type of components to achieve these restrictions.

Components are grouped on basis of their types. These groups are termed as ComponentTypeGroup. There is one to many relations between this group and the components. They are persisted in database. In earlier versions, the valid component list was used just as macro in impex.

This approach is more optimal than the previous one which had a slow many to many relationship between ContentSlotName and Cms Component type.

<relation code="ComponentTypeGroups2ComponentType" generate="true" localized="false" autocreate="true">
			<deployment table="CompTypeGrp2CompType" typecode="1097" />
			<sourceElement qualifier="componentTypeGroups" type="ComponentTypeGroup" cardinality="many" collectiontype="set"/>
			<targetElement qualifier="cmsComponentTypes" type="CMSComponentType" cardinality="many" collectiontype="set"/>
</relation>

There are few groups which are defined in OOB Hybris. We can also define our custom groups.



INSERT_UPDATE ComponentTypeGroup;code[unique=true]
;logo
;headerlinks
;searchbox
;minicart
;wide
;narrow
;footer
;navigation
;mobile

Each valid component type is added to the group.

INSERT_UPDATE ComponentTypeGroups2ComponentType;source(code)[unique=true];target(code)[unique=true]
;narrow;ProductFeatureComponent
;narrow;CategoryFeatureComponent

When a component type is checked against its validity for a given content slot, the system checks if it is contained in the component type group.

INSERT_UPDATE ContentSlotName;name[unique=true];template(uid,$contentCV)[unique=true][default='LandingPage4Template'];validComponentTypes(code);compTypeGroup(code)

;SiteLogo;;;logo
;HeaderLinks;;;headerlinks
;SearchBox;;;searchbox
;MiniCart;;;minicart
;NavigationBar;;;navigation
;Section1;;;wide
;Section2A;;;narrow
;Section2B;;;narrow
;Section2C;;;wide
;Section3;;;wide
;Section4;;;narrow
;Section5;;;wide
;Footer;;;footer
;TopHeaderSlot;;;wide
;BottomHeaderSlot;;;wide
;PlaceholderContentSlot;;;

Relative URLs in Hybris Cockpits

Very often in several business scenarios it is required to share direct Urls of order, cart or product with internal teams, e.g.:

After order is placed:

  • Send confirmation email to customer.

And

  • Also send email to a team of internal staff with direct URL of that order so that staff can directly go to that specific order just by clicking on URL rather than logging into cockpit and searching for that order.

Considering different nature of cockpit framework it’s not straight to create direct URL of an item as compared to storefront which is MVC.

Here is solution:

https://<hostname>:<port>/cscockpit/index.zul?persp=cscockpitPerspective&events=activation&act-item=8796093055021

Understanding URL:

A request event handler parses request parameters and dispatches a Cockpit business event. Different components are then notified of this dispatched event.

According to above URL, Activation request events is triggered for order item with pk – 8796093055021