Getting bean from any context using groovy script in hybris

Hybris Logo

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.
5 2 votes
Article Rating
Subscribe
Notify of
guest

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

11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Lahcen
Lahcen
5 years ago

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

ayoub
ayoub
5 years ago

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 !

ayoub
ayoub
Reply to  El Mahdi Benzekri
5 years ago

Thank you Mehdi

Mark
Mark
5 years ago

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
5 years ago

Nice Post !
was very useful for me

Thanks El Mahdi

Ankit
Ankit
3 years ago

Anyone struggling with this, just remove the “/” before the web application name and it works. Thanks for the page, had been struggling to find how to do this for hours.

Ishwar Pote
Ishwar Pote
3 years ago

Hi,
First of all nice POST. I really loved it.

I have tried this solution to print the application context names: But couldn’t find the storefront and cmscockpit.
I am using Hybris 1905 version patch 15

authorizationserver
samlsinglesignon
interfaces
backoffice
hac
odata2webservices
datahubadapter
ROOT
Any suggestions?

Boufnichel
Boufnichel
1 year ago

here we go again, just use it
thanks Mahdi

11
0
Would love your thoughts, please comment.x
()
x