Getting bean from any context using groovy script in hybris

Hybris featured image

1. Overview

The Scripting console is a powerful feature that allow users to execute scripts on a running environment. It is especially handy when debugging a remote system.

Sometimes when creating our groovy script we may need to access a spring bean to perform some action. In this article we will demonstrate how to access any bean in the hybris application.

We are using hybris 6.3.0, and we will execute the groovy script in the HAC console.

For more information about the groovy syntax: Groovy Documentation

2. Getting our bean

Let’s imagine that we want to access the synchronizationService of the CMSCockpit, we can write:

spring.getBean("synchronizationService")
Or you can directly start using the bean using it’s code only:
synchronizationService

But we will probably face the following error: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'synchronizationService' is defined

It’s normal as the the synchronizationService bean is not visible from the HAC web application context, we should try to retrieve the bean from an application context where the bean is accessible.

Let’s try with CMSCockpit extension using the /CMSCockpit application context.

import de.hybris.platform.core.PK
import de.hybris.platform.spring.HybrisContextLoaderListener
import org.apache.commons.lang3.reflect.FieldUtils
import org.springframework.web.context.ContextLoader
import org.springframework.web.context.WebApplicationContext

STOREFRONTCONTEXT = "/CMSCockpit"

def f = ContextLoader.getDeclaredField("currentContextPerThread")
f.setAccessible(true)

Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener)
def appContext = contexts.find {STOREFRONTCONTEXT.equals(it.key.getContextName())}
//When the context is found, we are ready to get our beans
if (appContext ==null) println "Impossible to retrieve application context"
else {
    defaultSyncService = appContext.value.getBean("synchronizationService")
}

Let’s dive into this code snippets, we have three different steps:

2.1 Getting all hybris contexts

ContextLoader.getDeclaredField("currentContextPerThread")
currentContextPerThread is an attribute of ContextLoader of type Map<ClassLoader, WebApplicationContext>, containing all the web application contexts.

2.2 Finding the required context

Search for the web application context having the required context name, using:

STOREFRONTCONTEXT.equals(it.key.getContextName())

contexts.find {} is the groovy method to find the first value of a collection that matches the criteria in the closure.

2.3 we are ready

When the web application context is found, we can retrieve any bean that is visible in the given context, using appContext.getBean().

appContext.value is the groovy style of getting the optional value.

 

3. Summary

The application context hierarchy is composed of the master hybris application context, and a web application context for every web module extension.

hybris application context hierarchy

 

  • Beans that are declared in a core module extension are accessible from every web application context. They are registred within the master hybris application context.
  • We have a WebApplicationContext for every extension with a web module.
  • In a given WebApplicationContext, other beans from other WebApplicationContexts are not visible.
  • When the required bean is not accessible from a given WebApplicationContext, for instance the HAC application context, we need to look for it from the web application context of the declaring extension.

8
Leave a Reply

avatar
4 Comment threads
4 Thread replies
4 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
BoufnichelMarkayoubEl Mahdi BenzekriLahcen Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
Lahcen
Guest
Lahcen

Regardless of use cases where your tip gonna help, it’s a nice post.

ayoub
Guest
ayoub

Thank you Mehdi for sharing, is it possible to change a bean implementation using groovy:

example:

customBeanImpl1 = spring.getBean(“customBeanImpl1”)
customBeanImpl1.setProperty1(val);
//how to do the following ?
spring.setBean(“customBeanImpl1”, customBeanImpl1);

Thanks in advance !

Mark
Guest
Mark

Hi Mahdi,

This post is really helpful. I am trying to run the same script to print all the web contexts. For some reason, storefront webcontext is not getting printed. I have tried in 2 different projects but no luck. Do you have idea what could be wrong?

Thanks
Mark

Boufnichel
Guest

Nice Post !
was very useful for me

Thanks El Mahdi