Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Sunday, July 24, 2022

How to parse JSON string to Object and vice versa in Groovy Grails application

In this tutorial, we will learn how to parse or convert the object to JSON string and JSON string to object.

Convert Object to JSON String:

Let's look into the example, here we will parse the Map to JSON string.

Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
List listToConvert = ["Test", "+10656564"]

Now, let's convert to JSON string using JSON class

import grails.converters.JSON
        Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
        List listToConvert = ["Test", "+10656564"]
        String jsonStringFromMap =  (mapToConvert as JSON).toString()
        String jsonStringFromList =  (listToConvert as JSON).toString()
        

You can use any other object data type to convert as above

Convert JSON String to Object:

For converting JSON string to object we are using JsonSlurper as below:

import grails.converters.JSON
import groovy.json.JsonSlurper
		Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
        List listToConvert = ["Test", "+10656564"]
        String jsonStringFromMap =  (mapToConvert as JSON).toString()
        String jsonStringFromList =  (listToConvert as JSON).toString()
        Map convertedMap = parseTo(jsonStringFromMap)
        List convertedList = parseTo(jsonStringFromList)
        
        private static def parseTo(String jsonString) {
        return new JsonSlurper().parseText(jsonString)
    }
        
Share:

Wednesday, June 29, 2022

How to use SiftingAppender in Gradle Groovy project

 In this tutorial, we are going to set up the SiftingAppender in our Gradle Groovy project.

Sifting Appender is useful when we want to separate the log files during runtime i.e if we want to separate the log files per thread or per user session basis.

Unfortunately, in the Gradle Groovy project, SiftingAppender is no longer supported since version 1.0.12 as mentioned in Groovy Configuration.

Let's look into the simple example where we are going to configure the SiftingAppender in logback.groovy, where we want to configure the per-user logging mechanism.

import ch.qos.logback.classic.PatternLayout
import ch.qos.logback.classic.sift.MDCBasedDiscriminator
import ch.qos.logback.classic.sift.SiftingAppender

appender("USER_ROLLING", SiftingAppender) {
    discriminator(MDCBasedDiscriminator) {
        key = 'userid'
        defaultValue = 'NONE'
    }
    sift {
        appender("FILE-${userid}", FileAppender) {
            file = "Path-to-log/${userid}.log"
            append = true
            layout(PatternLayout) {
                pattern = "%level %logger - %msg%n"
            }
        }
    }
}
logger("package-to-log",TRACE,['USER_ROLLING'], false)

This is a simple example SiftingAppender configuration; this is derived from logback sifting appender xml configuration.

We are using the Mapped Diagnostic Context for mapping the context user to create a separate file. We can do a similar for the thread as well.

Let's set up the MDC for user, the sample example looks as below.

import groovy.util.logging.Slf4j
import org.slf4j.MDC
@Slf4j
class UserLogging {

    public static void debug(String message, String userid = '') {
        setUserMDC(userid)
        log.debug(message)
    }

    public static void error(String message, String userid = '') {
        setUserMDC(userid)
        log.error(message)
    }

    public static void info(String message, String userid = '') {
        setUserMDC(userid)
        log.info(message)
    }

    public static void setUserMDC(String userid) {
        try {
            if (!userid) {
                MDC.remove("userid")
                return
            }
            MDC.put("userid", userid)
        }catch(e) {
            log.error("Error setting user Mapped Diagnostic Context due to "+e.getMessage())
        }
    }
}

Here, if the userid is available then we are setting the MDC for userid so the log file can be written in a separate file per user. If you want to do with request user do the similar in filter class or the place where it suits.

Now, if we run the application we will get the error as a result the appender doesn't work. So, here we found the solution project that extends Logback Gaffer so that SiftingAppender can be configured in Groovy DSL from this Github repo.

Simply download the jar file for that project and add it to the application.

For the Gradle project create a libs directory under the project directory and load and compile from build.gradle file.

Under build.gradle under dependencies{} section:

compile fileTree(dir: 'libs', include: '*.jar')

If we run the application it suppose to work. The log file will be created on the respective file path.

Share:

Friday, January 21, 2022

Splitting resources.groovy configuration in Grails applications

Splitting resources.groovy configuration in Grails applications

1. Introduction:

In grails, when our resources.groovy file is growing then it is better to split some logical bean configuration with a separate file and import that file in resources.groovy.  For this, Grails provides a neat way to specify Spring bean definitions with its custom Beans DSL by using importBeans or loadBeans.

2. How to split resources.groovy

You can simply create resources file under  "grails-app/conf/spring/" package: e.g

firstBean.groovy:
beans {
  beanConfiguration: yourBeanConfiguration
}

3. Import external bean file

Grails provide importBeans or loadBeans to import custom external bean file which can be done inside resources.groovy as bellow:
beans = { 
  importBeans('file:grails-app/conf/spring/firstBean.groovy') 
}

The problem is that this seems to work, but only if you run the application via  grails run-app with the embedded servlet container.

As soon we create a WAR file and deploy it into tomcat we are getting into trouble. The problem is Spring Bean Configuration file is moved on the different folder in tomcat "WEB-INF/classes/spring/" so we can get file-not-found-exception.

In order to resolve this problem, we need to locate custom resource path in resources.groovy.
def loadFromFile = { name ->
        importBeans("file:grails-app/conf/spring/"+name)
    }

    def loadFromWar = { name ->
        def resource = application.parentContext.getResource("WEB-INF/classes/spring/"+name)
        loadBeans(resource)
    }
    def loadResource = application.isWarDeployed() ? loadFromWar : loadFromFile

    loadResource "firstBean.groovy"
    loadResource "secondBean.groovy"



Here if the application is running via grails run-app then it will use the path "grails-app/conf/spring/". And if it is via external tomcat with deploying the WAR file then it uses the path "WEB-INF/classes/spring/".

Note: Be sure that your resource file is packaged on WAR with the right path.
Share: