Useful Groovy Scripts. Part 2.
The Groovy console is a very handy tool to develop and run scripts inside hybris without touching the source code. It is a very powerful tool for debugging purposes, especially if you need to troubleshoot the remote system. In this article, I collected some of the scripts I use regularly in my work.
This is a PART 2 of the series. Today I share the following solutions:
After the code is executed, you will see the logger in the list in HAC without a server restart:
You can activate and deactivate a bunch of loggers in one go.
We can see in the output that some model values were set by the home page controller. The controller returns a name of JSP template, and you can find it in the output as well.
Result:
We can see a list of contexts. For each context, you have appContext.
- add any class to the logging subsystem
- print a bean list from the particular context
- execute a method from the page controller from HAC/Groovy console
- print all URLs from all controllers (request mappings)
- print all web contexts
Turn on/off logging for any class
In order to turn the logging on for any particular class, in the latest versions of SAP hybris Commerce normally you need to make some changes in local.properties and restart the server. After adding the class into the list, you will be able to turn off and on the logging for this class using HAC. However, sometimes we need to turn on the logging temporarily, just to troubleshoot. It is a very common scenario. So I believe, my solution will make things easier for the developers. The following code adds the logger for “jalo.flexibleSearch.FlexibleSearch” with a DEBUG level:import org.apache.logging.log4j.*;
import org.apache.logging.log4j.core.config.*;
import de.hybris.platform.util.logging.log4j2.HybrisLoggerContext;
// example:
setLogger("de.hybris.platform.jalo.flexiblesearch.FlexibleSearch", "DEBUG");
public String setLogger(String logClass, String logLevel ) {
final HybrisLoggerContext loggerCtx = (HybrisLoggerContext) LogManager.getContext(false);
final Configuration loggerCfg = loggerCtx.getConfiguration();
LoggerConfig loggerConfig = loggerCfg.getLoggers().get(logClass);
if (loggerConfig == null) {
// create
String additivity = "true";
String includeLocation = "true";
Property[] properties = null;
AppenderRef[] refs = [];
filter = null;
LoggerConfig createdLoggerConfig = LoggerConfig.createLogger(
additivity,
Level.getLevel(logLevel),
logClass,
includeLocation,
refs,
properties,
loggerCfg,
filter
);
loggerCfg.addLogger(logClass, createdLoggerConfig);
} else {
loggerCfg.getLoggers().get(logClass).setLevel(Level.getLevel(logLevel));
}
loggerCtx.updateLoggers();
}
import org.apache.logging.log4j.core.config.*;
import de.hybris.platform.util.logging.log4j2.HybrisLoggerContext;
// example:
setLogger("de.hybris.platform.jalo.flexiblesearch.FlexibleSearch", "DEBUG");
public String setLogger(String logClass, String logLevel ) {
final HybrisLoggerContext loggerCtx = (HybrisLoggerContext) LogManager.getContext(false);
final Configuration loggerCfg = loggerCtx.getConfiguration();
LoggerConfig loggerConfig = loggerCfg.getLoggers().get(logClass);
if (loggerConfig == null) {
// create
String additivity = "true";
String includeLocation = "true";
Property[] properties = null;
AppenderRef[] refs = [];
filter = null;
LoggerConfig createdLoggerConfig = LoggerConfig.createLogger(
additivity,
Level.getLevel(logLevel),
logClass,
includeLocation,
refs,
properties,
loggerCfg,
filter
);
loggerCfg.addLogger(logClass, createdLoggerConfig);
} else {
loggerCfg.getLoggers().get(logClass).setLevel(Level.getLevel(logLevel));
}
loggerCtx.updateLoggers();
}
Print a bean list from the particular context
The default example from the Groovy Hybris Scripting shows only the beans accessible from HAC. The list is quite short and not very useful. The code below shows the beans from any particular context.STOREFRONTCONTEXT = "/trainingstorefront";
import de.hybris.platform.spring.HybrisContextLoaderListener;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
if (contextName == STOREFRONTCONTEXT) {
appContext = loader.getValue();
}
}
if (appContext == null) { println ("context is not found. Please set up STOREFRONTCONTEXT (for example, '/trainingstorefront') "); }
printAllBeans(appContext);
void printAllBeans(context)
{
beanFactory = context.getAutowireCapableBeanFactory()
for (String beanName : beanFactory.getBeanDefinitionNames()) {
println beanName;
}
}
import de.hybris.platform.spring.HybrisContextLoaderListener;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
if (contextName == STOREFRONTCONTEXT) {
appContext = loader.getValue();
}
}
if (appContext == null) { println ("context is not found. Please set up STOREFRONTCONTEXT (for example, '/trainingstorefront') "); }
printAllBeans(appContext);
void printAllBeans(context)
{
beanFactory = context.getAutowireCapableBeanFactory()
for (String beanName : beanFactory.getBeanDefinitionNames()) {
println beanName;
}
}
Executing the method from the page controller bean
You may want to execute a method from the controller bean. Normally, it is not possible, because the bean is not accessible, the context is not set up properly etc. The code below that it is feasible.// replace "printAllBeans(appContext)" from the example above with the code below
import de.hybris.platform.catalog.model.CatalogVersionModel;
import de.hybris.platform.core.model.c2l.LanguageModel;
import de.hybris.platform.catalog.model.CatalogModel;
import org.springframework.validation.support.*;
import de.hybris.platform.commercefacades.user.data.CustomerData;
import de.hybris.platform.commercefacades.storesession.data.*;
import org.springframework.web.servlet.mvc.support.*;
catalog = "electronicsContentCatalog";
catalogVersion = "Online";
siteUid = "electronics";
currentUser = new CustomerData(); //set up the customer if needed ...
currentCurrency = new CurrencyData(); //set up the currency if needed ...
currentLanguage = new LanguageData(); //set up the language if needed
currencies = new java.util.ArrayList();
currencies.add(currentCurrency);
languages = new java.util.ArrayList();
languages.add(currentLanguage);
CatalogVersionModel catalogVersionModel = catalogVersionService.getCatalogVersion(catalog, catalogVersion);
CatalogModel catalogModel = catalogService.getCatalogForId(catalog);
LanguageModel languageModel = i18NService.getLanguage("en");
Collection<CatalogVersionModel> catalogVersions = new ArrayList<CatalogVersionModel>();
catalogVersions.add(catalogVersionModel);
sessionService.setAttribute("currentCatalogVersion", catalogVersionModel);
sessionService.setAttribute("catalogversions", catalogVersions);
sessionService.setAttribute("language", languageModel);
baseSiteService = spring.getBean("baseSiteService");
currentSite = baseSiteService.getBaseSiteForUID(siteUid);
sessionService.setAttribute("currentSite", currentSite);
locale = new Locale("en");
sessionService.setAttribute("locale", locale);
homePageController = appContext.getBean("homePageController");
model = new BindingAwareModelMap();
model.put("user", currentUser);
model.put("siteUid", siteUid);
model.put("siteName", siteUid);
model.put("currentCurrency", currentCurrency);
model.put("currentLanguage", currentLanguage);
model.put("currencies", currencies);
model.put("languages", languages);
redirectModel = new RedirectAttributesModelMap();
template = homePageController.home(false, model, redirectModel);
println "template = $template";
for (modelItem in model) {
println modelItem;
}
import de.hybris.platform.catalog.model.CatalogVersionModel;
import de.hybris.platform.core.model.c2l.LanguageModel;
import de.hybris.platform.catalog.model.CatalogModel;
import org.springframework.validation.support.*;
import de.hybris.platform.commercefacades.user.data.CustomerData;
import de.hybris.platform.commercefacades.storesession.data.*;
import org.springframework.web.servlet.mvc.support.*;
catalog = "electronicsContentCatalog";
catalogVersion = "Online";
siteUid = "electronics";
currentUser = new CustomerData(); //set up the customer if needed ...
currentCurrency = new CurrencyData(); //set up the currency if needed ...
currentLanguage = new LanguageData(); //set up the language if needed
currencies = new java.util.ArrayList();
currencies.add(currentCurrency);
languages = new java.util.ArrayList();
languages.add(currentLanguage);
CatalogVersionModel catalogVersionModel = catalogVersionService.getCatalogVersion(catalog, catalogVersion);
CatalogModel catalogModel = catalogService.getCatalogForId(catalog);
LanguageModel languageModel = i18NService.getLanguage("en");
Collection<CatalogVersionModel> catalogVersions = new ArrayList<CatalogVersionModel>();
catalogVersions.add(catalogVersionModel);
sessionService.setAttribute("currentCatalogVersion", catalogVersionModel);
sessionService.setAttribute("catalogversions", catalogVersions);
sessionService.setAttribute("language", languageModel);
baseSiteService = spring.getBean("baseSiteService");
currentSite = baseSiteService.getBaseSiteForUID(siteUid);
sessionService.setAttribute("currentSite", currentSite);
locale = new Locale("en");
sessionService.setAttribute("locale", locale);
homePageController = appContext.getBean("homePageController");
model = new BindingAwareModelMap();
model.put("user", currentUser);
model.put("siteUid", siteUid);
model.put("siteName", siteUid);
model.put("currentCurrency", currentCurrency);
model.put("currentLanguage", currentLanguage);
model.put("currencies", currencies);
model.put("languages", languages);
redirectModel = new RedirectAttributesModelMap();
template = homePageController.home(false, model, redirectModel);
println "template = $template";
for (modelItem in model) {
println modelItem;
}
Print all URLs from all controllers (RequestMappings)
The code below shows all request mappings from all controllers of the particular context.STOREFRONTCONTEXT = "/trainingstorefront";
import de.hybris.platform.spring.HybrisContextLoaderListener;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.reflect.*;
import java.lang.annotation.Annotation;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
if (contextName == STOREFRONTCONTEXT) {
appContext = loader.getValue();
}
}
if (appContext == null) { println ("context is not found. Please set up STOREFRONTCONTEXT (for example, '/trainingstorefront') "); }
beanMap = appContext.getBeanNamesForAnnotation(RequestMapping.class);
for (beanName in beanMap)
{
requestMapping(appContext.getBean(beanName).getClass());
}
String requestMapping(Class clazz)
{
classValue = "";
if (clazz.getDeclaredAnnotations()) {
for(Annotation annotation :clazz.getDeclaredAnnotations()){
if(annotation.toString().contains("RequestMapping"))
printAnnotation(annotation, "class", null, clazz, "");
classValue = getValue("value", annotation.toString());
}
}
for(Method method :clazz.getMethods()){
for(Annotation annotation :method.getDeclaredAnnotations()){
if(annotation.toString().contains("RequestMapping"))
printAnnotation(annotation, "method", method, clazz, classValue);
}
}
}
String printAnnotation(Annotation annotation, String type, Method method, Class clazz, String classValue)
{
print clazz?.getSimpleName() + "\t"+
((method==null)?"":method.getName()) + "\t" +
getValue("method", annotation.toString()) + "\t" +
classValue + getValue("value", annotation.toString()) + "\t" +
getValue("param", annotation.toString()) + "\n";
;
}
String getValue(String param, String annotation) {
retValue = "";
annotation.findAll(/$param=\[(.*?)\]/) { full, value -> retValue = value; }
return retValue;
}
import de.hybris.platform.spring.HybrisContextLoaderListener;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.reflect.*;
import java.lang.annotation.Annotation;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
if (contextName == STOREFRONTCONTEXT) {
appContext = loader.getValue();
}
}
if (appContext == null) { println ("context is not found. Please set up STOREFRONTCONTEXT (for example, '/trainingstorefront') "); }
beanMap = appContext.getBeanNamesForAnnotation(RequestMapping.class);
for (beanName in beanMap)
{
requestMapping(appContext.getBean(beanName).getClass());
}
String requestMapping(Class clazz)
{
classValue = "";
if (clazz.getDeclaredAnnotations()) {
for(Annotation annotation :clazz.getDeclaredAnnotations()){
if(annotation.toString().contains("RequestMapping"))
printAnnotation(annotation, "class", null, clazz, "");
classValue = getValue("value", annotation.toString());
}
}
for(Method method :clazz.getMethods()){
for(Annotation annotation :method.getDeclaredAnnotations()){
if(annotation.toString().contains("RequestMapping"))
printAnnotation(annotation, "method", method, clazz, classValue);
}
}
}
String printAnnotation(Annotation annotation, String type, Method method, Class clazz, String classValue)
{
print clazz?.getSimpleName() + "\t"+
((method==null)?"":method.getName()) + "\t" +
getValue("method", annotation.toString()) + "\t" +
classValue + getValue("value", annotation.toString()) + "\t" +
getValue("param", annotation.toString()) + "\n";
;
}
String getValue(String param, String annotation) {
retValue = "";
annotation.findAll(/$param=\[(.*?)\]/) { full, value -> retValue = value; }
return retValue;
}
Print all web contexts
import de.hybris.platform.spring.HybrisContextLoaderListener;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
appContext = loader.getValue();
// print any of context attributes (appContext)
println contextName + "\t" + appContext.getId();
}
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
appContext = null;
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
for (loader in contexts) {
contextName = loader.getKey().getContextName();
appContext = loader.getValue();
// print any of context attributes (appContext)
println contextName + "\t" + appContext.getId();
}
© Rauf Aliev, December 2017
Ivan
13 December 2017 at 07:38
Actually I’m using a bit shorter code to add logger. Although it strongly related on Log4j2 (but it’s used on our project)
def loggerCtx = org.apache.logging.log4j.LogManager.getContext(false)
def loggingConfig = loggerCtx.getConfiguration()
def specificConfig = new org.apache.logging.log4j.core.config.LoggerConfig(“org.apache.http”, org.apache.logging.log4j.Level.ALL, true)
loggingConfig.addLogger(“org.apache.http”, specificConfig)
loggerCtx.updateLoggers()